import cv2,numpy as np,tifffile,json,sys
from scipy import ndimage as ndi
from PIL import Image
from pathlib import Path
cv2.setNumThreads(2)
sources=json.load(open('/workspace/scratch/sources.json'));boxes=json.load(open('/workspace/scratch/chartboxes.json'));limits=json.load(open('/workspace/scratch/limits.json'))
Path('/workspace/scratch/hard').mkdir(exist_ok=True)
for s in sys.argv[1:] or ['HH-1041','HH-3315','HH-3360','HH-4402','HH-4461','HH-5547','HH-6618','HH-6672','HH-7150','HH-7186','HH-8205','HH-8248','HH-8256','HH-8285','HH-9395']:
 a=tifffile.imread('/workspace/input/'+sources[s]).astype('float32')/65535;b=tifffile.imread('/workspace/input/charts/'+s+'_chart.tif').astype('float32')/65535
 aa=cv2.GaussianBlur(a,(0,0),.5);bb=cv2.GaussianBlur(b,(0,0),.5)
 diff=np.linalg.norm(aa-bb,axis=2)
 ratio=(aa*bb).sum(2)/(bb*bb).sum(2)
 chroma=np.linalg.norm(aa-bb*np.minimum(ratio,1)[:,:,None],axis=2)
 gc=np.where(diff>.04,3,2).astype('uint8')
 gc[(diff>.12)&(chroma>.035)]=1;gc[diff<.014]=0
 cx0,cy0,cx1,cy1=boxes[s];gc[cy0-20:cy1+20,cx0-20:cx1+20]=3
 x0,y0,x1,y1=limits[s];x0-=70;y0-=70;x1+=70;y1+=70
 gc[:y0]=0;gc[y1:]=0;gc[:,:x0]=0;gc[:,x1:]=0
 # fine RGB grabcut incorporates colour across the chart's blind area
 cv2.grabCut((a*255).astype('uint8'),gc,None,np.zeros((1,65)),np.zeros((1,65)),3,cv2.GC_INIT_WITH_MASK)
 mask=np.isin(gc,[1,3])
 n,lab,stats,ctr=cv2.connectedComponentsWithStats(mask.astype('uint8'),8);keep=np.where(stats[:,4]>10)[0];keep=keep[keep!=0];mask=np.isin(lab,keep)
 cv2.imwrite('/workspace/scratch/hard/'+s+'.png',mask.astype('uint8')*255)
 comp=a*mask[:,:,None]+np.array([.1,.24,.37])*(1-mask[:,:,None])
 Image.fromarray(np.rint(np.clip(comp,0,1)*255).astype('uint8')).resize((1200,800)).save('/workspace/scratch/hard/'+s+'.jpg')
 print(s,flush=True)
import cv2,numpy as np,json,tifffile,os,sys
from scipy import ndimage as ndi
from PIL import Image
from pathlib import Path
cv2.setNumThreads(2)
sources=json.load(open('/workspace/scratch/sources.json'));soft=json.load(open('/workspace/input/page_plan.json'))['soft_edge_skus']
Path('/workspace/scratch/finalmasks').mkdir(exist_ok=True)
for s in sys.argv[1:] or list(sources):
 folders=['refined','auto','hard'] if s!='HH-2342' else ['auto']
 p=next(f'/workspace/scratch/{f}/{s}.png' for f in folders if os.path.exists(f'/workspace/scratch/{f}/{s}.png'))
 m=cv2.imread(p,0)>127
 if s in ['HH-1041','HH-4402','HH-4461','HH-7150','HH-8256','HH-9395']:
  n,lab,st,ct=cv2.connectedComponentsWithStats(m.astype('uint8'),8);m=lab==1+np.argmax(st[1:,4])
 if s=='HH-9374':
  poly=np.array([[0,0],[2400,0],[2400,580],[1750,708],[1590,662],[1400,623],[1200,602],[1010,614],[840,633],[710,668],[600,735],[0,735]],'int32')
  reg=np.zeros(m.shape,'uint8');cv2.fillPoly(reg,[poly],1);m[reg>0]=0
  di=ndi.distance_transform_edt(m);do=ndi.distance_transform_edt(~m)
  gc=np.where(m,3,2).astype('uint8');gc[di>15]=1;gc[do>15]=0
  aa=(tifffile.imread('/workspace/input/'+sources[s])/257).astype('uint8')
  cv2.grabCut(aa,gc,None,np.zeros((1,65)),np.zeros((1,65)),2,cv2.GC_INIT_WITH_MASK)
  m=np.isin(gc,[1,3]);m=ndi.binary_fill_holes(m)
 if s in soft:
  a=tifffile.imread('/workspace/input/'+sources[s]).astype('float32')/65535
  # Narrow-band colour matting. Opaque core is never altered.
  di=ndi.distance_transform_edt(m);do=ndi.distance_transform_edt(~m)
  fg=di>6;bg=do>10
  _,fi=ndi.distance_transform_edt(~fg,return_indices=True);_,bi=ndi.distance_transform_edt(~bg,return_indices=True)
  smooth=cv2.GaussianBlur(a,(3,3),.7);F=smooth[fi[0],fi[1]];B=smooth[bi[0],bi[1]]
  D=F-B;al=np.clip(np.sum((a-B)*D,2)/(np.sum(D*D,2)+1e-5),0,1)
  al[fg]=1;al[bg]=0
  # retain mechanical wooden parts' hard edges on upholstered seating
  if s in ['HH-8248','HH-8285']:
   cutoff=900 if s=='HH-8248' else 650
   hard=cv2.GaussianBlur(m.astype('float32'),(3,3),.4);al[cutoff:]=hard[cutoff:]
  al[al<.02]=0
 else:
  al=cv2.GaussianBlur(m.astype('float32'),(3,3),.4)
 cv2.imwrite('/workspace/scratch/finalmasks/'+s+'.png',np.rint(al*255).astype('uint8'))
 print(s,flush=True)
{
  "HH-1041": {
    "bottom": 1038,
    "solid_small": 200,
    "fg": [
      [
        [
          139,
          380
        ],
        [
          149,
          368
        ],
        [
          182,
          359
        ],
        [
          223,
          356
        ],
        [
          274,
          359
        ],
        [
          303,
          368
        ],
        [
          313,
          377
        ],
        [
          317,
          383
        ],
        [
          295,
          387
        ],
        [
          167,
          387
        ]
      ],
      [
        [
          163,
          625
        ],
        [
          188,
          620
        ],
        [
          233,
          617
        ],
        [
          273,
          620
        ],
        [
          309,
          629
        ],
        [
          327,
          651
        ],
        [
          340,
          681
        ],
        [
          346,
          710
        ],
   {"HH-1041": [970, 250, 1410, 1325], "HH-1206": [440, 150, 1940, 1300], "HH-2203": [650, 260, 1810, 1350], "HH-2342": [500, 90, 1950, 1290], "HH-3315": [690, 310, 1700, 1300], "HH-3360": [880, 220, 1485, 1355], "HH-4402": [860, 265, 1580, 1350], "HH-4461": [855, 265, 1540, 1340], "HH-5547": [750, 260, 1690, 1380], "HH-5593": [605, 210, 1840, 1420], "HH-6618": [790, 270, 1580, 1350], "HH-6672": [890, 250, 1460, 1390], "HH-7101": [540, 180, 1950, 1430], "HH-7150": [810, 280, 1540, 1365], "HH-7158": [400, 190, 2000, 1420], "HH-7186": [750, 225, 1650, 1390], "HH-8205": [760, 225, 1630, 1380], "HH-8248": [750, 285, 1660, 1400], "HH-8256": [1000, 210, 1380, 1350], "HH-8285": [680, 195, 1720, 1350], "HH-9328": [415, 170, 1960, 1460], "HH-9340": [560, 170, 1870, 1460], "HH-9374": [520, 460, 1840, 1080], "HH-9395": [970, 235, 1430, 1370]}