cat > /workspace/scratch/softpolys.json <<'JSON'
{
"HH-1206":[[268,254],[276,198],[320,146],[404,119],[550,106],[742,115],[845,145],[898,194],[924,245],[923,347],[917,459],[906,555],[895,600],[860,635],[800,666],[720,687],[609,698],[493,685],[393,660],[321,614],[287,563],[275,462]],
"HH-2203":[[368,157],[393,156],[465,185],[588,226],[769,204],[846,184],[850,235],[841,280],[815,335],[816,481],[838,568],[840,632],[800,665],[715,675],[606,648],[471,629],[398,622],[363,609],[363,560],[378,506],[379,297],[365,231]],
"HH-2342":[[599,90],[698,105],[799,155],[859,218],[899,309],[910,400],[897,494],[862,578],[804,641],[724,683],[634,699],[542,696],[453,668],[381,610],[329,532],[301,460],[290,374],[310,270],[351,201],[416,146],[503,108]],
"HH-5593":[[362,166],[478,130],[566,122],[698,156],[870,181],[891,235],[863,315],[863,407],[850,496],[852,577],[825,611],[762,632],[650,651],[550,651],[464,626],[390,615],[362,582],[351,510],[351,410],[342,330],[335,260],[348,204]],
"HH-7101":[[302,300],[343,264],[399,253],[491,251],[651,300],[780,369],[877,423],[909,455],[906,500],[895,550],[864,597],[803,644],[732,682],[686,690],[649,673],[609,655],[556,647],[478,609],[411,575],[345,529],[310,493],[302,423]],
"HH-7158":[[277,149],[400,119],[475,116],[657,139],[776,164],[904,230],[935,299],[925,367],[882,436],[830,482],[815,524],[813,602],[790,626],[753,626],[722,597],[710,523],[631,531],[570,520],[575,548],[561,569],[532,565],[510,550],[490,510],[451,499],[447,559],[429,630],[406,661],[386,661],[364,643],[359,608],[373,545],[375,486],[315,445],[268,402],[245,361],[235,310],[245,233]],
"HH-9328":[[290,153],[388,151],[530,171],[599,190],[685,166],[833,149],[874,146],[906,196],[918,268],[883,327],[859,392],[849,469],[863,582],[848,642],[813,661],[722,679],[557,673],[441,664],[331,641],[320,604],[331,552],[345,484],[346,407],[331,333],[303,280],[285,210]],
"HH-9340":[[359,146],[437,157],[541,174],[601,192],[682,179],[763,173],[820,175],[826,216],[854,258],[866,292],[841,360],[833,408],[840,538],[835,602],[839,646],[800,660],[698,664],[602,645],[509,635],[420,610],[373,595],[369,559],[378,504],[368,432],[365,365],[345,292],[337,223],[331,179]],
"HH-9374":[[345,353],[414,335],[478,321],[565,316],[656,317],[765,329],[844,351],[870,373],[872,402],[852,442],[809,462],[735,477],[648,489],[537,491],[440,477],[371,458],[341,445],[323,413],[315,383]]
}
JSON
cat > /workspace/scratch/matting.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/matted').mkdir(exist_ok=True)
def matte(a,b,mask,inner=20,outer=35):
 # linear RGB for alpha calculations
 a=a**2.2;b=b**2.2
 di,ii=ndi.distance_transform_edt(mask,return_indices=True);do,io=ndi.distance_transform_edt(~mask,return_indices=True)
 fg=di>inner;bg=do>outer
 _,fi=ndi.distance_transform_edt(~fg,return_indices=True)
 _,bi=ndi.distance_transform_edt(~bg,return_indices=True)
 F=a[fi[0],fi[1]]
 # Background reflecting illumination correction in local surrounding ring
 delta=cv2.GaussianBlur(a-b,(0,0),2)
 B=b+delta[bi[0],bi[1]]
 B=np.clip(B,0,1)
 v=F-B;num=((a-B)*v).sum(2);den=(v*v).sum(2)
 alpha=np.clip(num/(den+1e-8),0,1)
 alpha[fg]=1;alpha[bg]=0
 return alpha
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)
 al=matte(a,b,mask.astype(bool),20,40)
 # mostly opaque interiors; suppress remote speckles, keep natural edge
 al[al<.02]=0
 cv2.imwrite('/workspace/scratch/matted/'+s+'.png',np.rint(al*255).astype('uint8'))
 comp=a*al[:,:,None]+np.array([.1,.24,.37])*(1-al[:,:,None])
 Image.fromarray(np.rint(np.clip(comp,0,1)*255).astype('uint8')).resize((1200,800)).save('/workspace/scratch/matted/'+s+'.jpg')
 print(s,flush=True)
PY
OPENBLAS_NUM_THREADS=1 python /workspace/scratch/matting.py