import numpy as np, cv2, json
from PIL import Image
a=np.asarray(Image.open('brand/logo-asli.jpg').convert('RGB')).astype(np.int32)
H,W,_=a.shape
r,g,b=a[:,:,0],a[:,:,1],a[:,:,2]
navy=(b>r+25)&(b<170)&(r<120)
gold=(r>g)&(g>b+20)&(r>120)
white=(r>200)&(g>200)&(b>200)
out={}
# rings: gold components
n,lab,st,cen=cv2.connectedComponentsWithStats(gold.astype(np.uint8),8)
comps=[(st[i,cv2.CC_STAT_AREA],i) for i in range(1,n)]
comps.sort(reverse=True)
print('gold comps',[(c,st[i][:4].tolist()) for c,i in comps[:6]])
def fit_circle(pts):
    x=pts[:,0].astype(float); y=pts[:,1].astype(float)
    A=np.c_[2*x,2*y,np.ones(len(x))]; bb=x*x+y*y
    c=np.linalg.lstsq(A,bb,rcond=None)[0]
    cx,cy=c[0],c[1]; R=np.sqrt(c[2]+cx*cx+cy*cy); return cx,cy,R
ys,xs=np.where(gold)
# left ring: use gold pixels left of x=930 ; right ring: right of x=1070
for name,sel in [('L',xs<905),('R',xs>1095)]:
    px=np.c_[xs[sel],ys[sel]]
    cx,cy,_=fit_circle(px)
    d=np.hypot(px[:,0]-cx,px[:,1]-cy)
    # refine: outer edge points = max d per angle bin, inner = min
    ang=np.arctan2(px[:,1]-cy,px[:,0]-cx)
    bins=np.digitize(ang,np.linspace(-np.pi,np.pi,181))
    outer=[];inner=[]
    for k in np.unique(bins):
        m=bins==k
        if m.sum()<5: continue
        i1=np.argmax(d[m]);i2=np.argmin(d[m])
        outer.append(px[m][i1]);inner.append(px[m][i2])
    o=fit_circle(np.array(outer)); iN=fit_circle(np.array(inner))
    out['ring'+name]={'outer':[round(v,2) for v in o],'inner':[round(v,2) for v in iN]}
    print(name,'outer',o,'inner',iN)
# navy outline around ring: navy pixels just outside gold outer edge along left side
for name in ['L','R']:
    cx,cy,Ro=out['ring'+name]['outer']; _,_,Ri=out['ring'+name]['inner']
    sgn=-1 if name=='L' else 1
    # scan horizontally from center outward along y=cy
    row=int(round(cy))
    xsr=range(int(cx),int(cx)+sgn*int(Ro+40),sgn)
    seq=''.join('G' if gold[row,x] else 'N' if navy[row,x] else 'W' if white[row,x] else '?' for x in xsr)
    print(name,'scan from center:',seq)
# heart
n,lab,st,cen=cv2.connectedComponentsWithStats(white.astype(np.uint8),8)
for i in range(1,n):
    x,y,w,h,area=st[i]
    if 900<x<1000 and 300<y<400 and area>500:
        print('heart',x,y,w,h,area); out['heart']=[int(x),int(y),int(w),int(h)]
        m=(lab==i).astype(np.uint8)*255
        cs,_=cv2.findContours(m,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
        c=max(cs,key=cv2.contourArea); ap=cv2.approxPolyDP(c,0.8,True)
        out['heartPoly']=ap.reshape(-1,2).tolist()
json.dump(out,open('brand/measure.json','w'))
