# -*- coding: utf-8 -*-
"""Đo màu cho yêu cầu "công thức màu nền nhuộm ra như mẫu" (dự án B).
- Ảnh MẪU (đã sơn) và ảnh GỖ MỘC = ảnh anh gửi (trùng byte với ảnh lô 09 dự án A).
- Đo bằng CODE (trung vị pixel của từng vùng, KHÔNG ước lượng bằng AI) + cắt ô zoom để soi.
- Xuất: _do_mau_nen_<ngày>.json + các ảnh crop trong thư mục dự án B.
Nguyên tắc: số nào cũng nói rõ vùng đo; vùng dính băng keo/carton/bìa thì ghi rõ KHÔNG dùng kết luận màu."""
import io, json, os
from datetime import datetime
import numpy as np
from PIL import Image

B = r'C:\Claw 2\Nghien cuu\Du-an-B-He-mau-Stain-Glaze'
OUT = os.path.join(B, 'anh_lo09_nen_mau')
os.makedirs(OUT, exist_ok=True)
MAU = r'C:\Users\admin\AppData\Local\hermes\cache\images\img_d3d125fe9364.jpg'   # mẫu đã lên màu
MOC = r'C:\Users\admin\AppData\Local\hermes\cache\images\img_94ae2ffb4ecc.jpg'   # gỗ mộc


def srgb_to_lab(rgb):
    a = np.asarray(rgb, float) / 255.0
    a = np.where(a <= 0.04045, a / 12.92, ((a + 0.055) / 1.055) ** 2.4)
    M = np.array([[0.4124, 0.3576, 0.1805], [0.2126, 0.7152, 0.0722], [0.0193, 0.1192, 0.9505]])
    xyz = (M @ a) / np.array([0.95047, 1.0, 1.08883])
    f = np.where(xyz > 0.008856, np.cbrt(xyz), 7.787 * xyz + 16 / 116)
    L = 116 * f[1] - 16
    return L, 500 * (f[0] - f[1]), 200 * (f[1] - f[2])


def do_vung(im, ten, box, ghi_chu=''):
    x1, y1, x2, y2 = box
    crop = im.crop(box)
    a = np.asarray(crop.convert('RGB'), float).reshape(-1, 3)
    med = np.median(a, axis=0)
    rgb = tuple(int(round(v)) for v in med)
    L, A, Bb = srgb_to_lab(rgb)
    hexs = '#%02X%02X%02X' % rgb
    crop.save(os.path.join(OUT, 'zoom_%s.jpg' % ten), quality=92)
    return dict(ten=ten, box=list(box), rgb=list(rgb), hex=hexs,
                L=round(float(L), 1), a=round(float(A), 1), b=round(float(Bb), 1),
                sd_sang=round(float(np.std(a.mean(axis=1))), 1), ghi_chu=ghi_chu)


im_mau = Image.open(MAU).convert('RGB')
im_moc = Image.open(MOC).convert('RGB')
print('MẪU  %sx%s · GỖ MỘC %sx%s' % (*im_mau.size, *im_moc.size))

W, H = im_mau.size
# --- MẪU: đo 6 vùng vân, né băng keo (góc phải trên) ---
vung_mau = [
    ('mau_1_trai_tren',  (int(W * .05), int(H * .06), int(W * .25), int(H * .22)), 'mảng trái trên'),
    ('mau_2_trai_duoi',  (int(W * .06), int(H * .55), int(W * .28), int(H * .80)), 'mảng trái dưới'),
    ('mau_3_giua',       (int(W * .40), int(H * .30), int(W * .60), int(H * .45)), 'giữa vân sẫm'),
    ('mau_4_giua_duoi',  (int(W * .42), int(H * .62), int(W * .62), int(H * .80)), 'giữa dưới'),
    ('mau_5_phai',       (int(W * .70), int(H * .45), int(W * .90), int(H * .65)), 'phải giữa'),
    ('mau_6_nen_bang_keo', (int(W * .78), int(H * .02), int(W * .97), int(H * .12)), 'BĂNG KEO — không dùng kết luận màu'),
]
W2, H2 = im_moc.size
vung_moc = [
    ('moc_1_trai',       (int(W2 * .05), int(H2 * .15), int(W2 * .30), int(H2 * .45)), 'gỗ mộc trái'),
    ('moc_2_giua_tren',  (int(W2 * .35), int(H2 * .10), int(W2 * .60), int(H2 * .35)), 'gỗ mộc giữa trên'),
    ('moc_3_giua_duoi',  (int(W2 * .35), int(H2 * .60), int(W2 * .60), int(H2 * .85)), 'gỗ mộc giữa dưới'),
    ('moc_4_phai',       (int(W2 * .62), int(H2 * .30), int(W2 * .80), int(H2 * .60)), 'gỗ mộc phải'),
    ('moc_5_thanh_dam',  (int(W2 * .86), int(H2 * .30), int(W2 * .98), int(H2 * .70)), 'THANH GỖ ĐẬM dán mép — không dùng kết luận màu'),
    ('moc_6_carton',     (int(W2 * .05), int(H2 * .88), int(W2 * .30), int(H2 * .98)), 'NỀN CARTON — không dùng kết luận màu'),
]

kq = {'do_luc': datetime.now().strftime('%d/%m/%Y %H:%M'), 'anh_mau': MAU, 'anh_moc': MOC,
      'phuong_phap': 'trung vị pixel RGB từng vùng → sRGB→CIELAB (D65). Không quy chiếu thẻ màu trắng ⇒ '
                     'số liệu mang tính so sánh trong cùng một ảnh, sai lệch tuyệt đối có thể vài đơn vị L*.',
      'mau': [], 'moc': []}
print('\n=== MẪU (đã lên màu) ===')
for t, box, gc in vung_mau:
    r = do_vung(im_mau, t, box, gc)
    kq['mau'].append(r)
    print('  %-22s %s  L*%5.1f a*%6.1f b*%6.1f  SD sáng %4.1f  %s' % (t, r['hex'], r['L'], r['a'], r['b'], r['sd_sang'], gc))
print('\n=== GỖ MỘC ===')
for t, box, gc in vung_moc:
    r = do_vung(im_moc, t, box, gc)
    kq['moc'].append(r)
    print('  %-22s %s  L*%5.1f a*%6.1f b*%6.1f  SD sáng %4.1f  %s' % (t, r['hex'], r['L'], r['a'], r['b'], r['sd_sang'], gc))

dung = [r for r in kq['mau'] if 'KHÔNG' not in r['ghi_chu']]
dungm = [r for r in kq['moc'] if 'KHÔNG' not in r['ghi_chu']]
kq['tong_hop'] = {
    'mau_L_tb': round(float(np.mean([r['L'] for r in dung])), 1),
    'mau_a_tb': round(float(np.mean([r['a'] for r in dung])), 1),
    'mau_b_tb': round(float(np.mean([r['b'] for r in dung])), 1),
    'mau_L_min': min(r['L'] for r in dung), 'mau_L_max': max(r['L'] for r in dung),
    'moc_L_tb': round(float(np.mean([r['L'] for r in dungm])), 1),
    'moc_a_tb': round(float(np.mean([r['a'] for r in dungm])), 1),
    'moc_b_tb': round(float(np.mean([r['b'] for r in dungm])), 1),
    'moc_L_min': min(r['L'] for r in dungm), 'moc_L_max': max(r['L'] for r in dungm),
}
t = kq['tong_hop']
print('\n=== TỔNG HỢP (chỉ vùng hợp lệ) ===')
print('  MẪU   : L* %.1f (%.1f–%.1f) · a* %+.1f · b* %+.1f' % (t['mau_L_tb'], t['mau_L_min'], t['mau_L_max'], t['mau_a_tb'], t['mau_b_tb']))
print('  GỖ MỘC: L* %.1f (%.1f–%.1f) · a* %+.1f · b* %+.1f' % (t['moc_L_tb'], t['moc_L_min'], t['moc_L_max'], t['moc_a_tb'], t['moc_b_tb']))
print('  ⇒ cần HẠ SÁNG  ΔL* = %.1f  · dịch đỏ-vàng a%+.1f b%+.1f' % (t['moc_L_tb'] - t['mau_L_tb'], t['mau_a_tb'] - t['moc_a_tb'], t['mau_b_tb'] - t['moc_b_tb']))

p = os.path.join(OUT, '_do_mau_nen_%s.json' % datetime.now().strftime('%Y%m%d'))
json.dump(kq, io.open(p, 'w', encoding='utf-8'), ensure_ascii=False, indent=1)
print('\nlưu:', p)
print('ảnh zoom:', len(os.listdir(OUT)) - 1, 'ô trong', OUT)
