cat > /workspace/scratch/grabsoft.py <<'PY'
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'));polys=json.load(open('/workspace/scratch/softpolys.json'))
Path('/workspace/scratch/grab').mkdir(exist_ok=True)
for s in sys.argv[1:] or list(polys):
 a=tifffile.imread('/workspace/input/'+sources[s]).astype('float32')/65535;b=tifffile.imread('/workspace/input/charts/'+s+'_chart.tif').astype('float32')/65535
 mask=np.zeros(a.shape[:2],'uint8');cv2.fillPoly(mask,[np.rint(np.array(polys[s])*2).astype('int32')],1)
 disti=ndi.distance_transform_edt(mask);disto=ndi.distance_transform_edt(1-mask)
 gc=np.where(mask,cv2.GC_PR_FGD,cv2.GC_PR_BGD).astype('uint8');gc[disti>25]=cv2.GC_FGD;gc[disto>40]=cv2.GC_BGD
 aa=cv2.GaussianBlur(a,(0,0),.6);bb=cv2.GaussianBlur(b,(0,0),.6)
 diff=np.linalg.norm(aa-bb,axis=2)
 ratio=(aa*bb).sum(2)/(bb*bb).sum(2)
 chroma=np.linalg.norm(aa-bb*ratio[:,:,None],axis=2)
 # difference in two channels + object luminance
 feat=np.stack([np.clip(diff*3,0,1),np.clip(chroma*9,0,1),aa.mean(2)],2)
 feat=(feat*255).astype('uint8')
 cv2.grabCut(feat,gc,None,np.zeros((1,65)),np.zeros((1,65)),4,cv2.GC_INIT_WITH_MASK)
 m=np.isin(gc,[1,3])
 m=ndi.binary_fill_holes(m)
 cv2.imwrite('/workspace/scratch/grab/'+s+'.png',m.astype('uint8')*255)
 comp=a*m[:,:,None]+np.array([.1,.24,.37])*(1-m[:,:,None])
 Image.fromarray(np.rint(np.clip(comp,0,1)*255).astype('uint8')).resize((1200,800)).save('/workspace/scratch/grab/'+s+'.jpg')
 print(s,flush=True)
PY
OPENBLAS_NUM_THREADS=1 python /workspace/scratch/grabsoft.py