cat > /workspace/scratch/edits.json <<'JSON'
{
"HH-1041":{"bottom":1034,"fg":[[[183,619],[219,616],[253,620],[272,635],[282,660],[306,731],[318,779],[318,822],[307,858],[287,885],[258,899],[218,900],[180,890],[156,868],[141,834],[138,795],[145,751],[162,693],[171,650]]]},
"HH-8256":{"bottom":1075,"fg":[[[181,112],[184,105],[212,104],[219,110],[218,137],[215,171],[215,270],[219,327],[235,390],[240,425],[236,458],[224,478],[214,486],[214,502],[181,502],[183,483],[169,471],[158,448],[153,424],[157,397],[169,347],[176,310],[180,265],[180,170],[177,139]]]},
"HH-4402":{"bottom":1045,"bg":[[[220,317],[470,318],[474,372],[470,655],[450,675],[218,676],[213,658],[218,393]],[[194,316],[207,316],[200,558],[187,634],[178,664],[169,660],[180,478]],[[480,318],[502,316],[539,486],[557,666],[548,677],[526,647],[508,446]],[[199,722],[201,850],[242,825],[270,813],[391,811],[437,827],[474,859],[469,717]],[[216,857],[257,841],[390,839],[428,854],[456,875],[453,893],[410,914],[348,921],[283,916],[237,896],[214,873]],[[166,760],[177,817],[177,868],[159,886],[148,887]],[[524,747],[519,846],[535,886],[552,893],[550,835]],[[135,953],[169,951],[197,920],[277,953],[356,960],[437,946],[503,912],[537,946],[570,964],[574,1064],[129,1064]]]},
"HH-4461":{"bottom":1049,"bg":[[[221,109],[318,105],[310,577],[207,576]],[[411,109],[506,114],[505,452],[487,467],[488,582],[401,581]],[[134,473],[183,456],[179,574],[162,578]],[[520,485],[529,484],[528,534],[522,570]],[[210,693],[237,700],[272,704],[293,693],[301,677],[326,679],[327,696],[351,708],[385,696],[414,697],[433,714],[451,744],[452,851],[208,852]],[[211,881],[462,894],[462,948],[176,935]],[[143,971],[475,1005],[475,1090],[144,1090]]]},
"HH-7150":{"bottom":1043,"bg":[[[270,199],[297,199],[297,361],[270,361]],[[326,198],[351,198],[351,362],[326,362]],[[380,199],[417,199],[417,364],[380,364]],[[446,199],[477,199],[477,365],[446,365]],[[506,200],[536,200],[536,366],[506,366]],[[566,200],[590,200],[590,367],[566,367]],[[619,202],[630,202],[630,336],[619,354]],[[243,385],[607,389],[576,450],[571,514],[301,524],[245,526]],[[151,924],[576,945],[576,1060],[149,1060]]]},
"HH-8205":{"fg":[[[430,180],[443,180],[447,201],[448,232],[450,249],[447,271],[450,297],[449,324],[450,352],[450,380],[450,405],[450,434],[450,465],[450,498],[431,498],[430,471],[430,445],[428,419],[425,394],[427,376],[426,359],[428,340],[426,320],[428,305],[428,286],[426,269],[430,250],[427,239],[430,221],[426,212]],[[55,814],[151,813],[146,836],[132,851],[106,861],[80,854],[63,840]],[[112,812],[211,811],[204,837],[185,853],[155,861],[130,850]],[[174,739],[279,736],[269,761],[249,778],[228,784],[198,772],[180,751]],[[241,807],[348,807],[339,835],[313,851],[294,857],[268,845],[250,830]],[[242,736],[345,736],[337,759],[316,775],[293,782],[267,773]],[[334,750],[415,747],[408,773],[391,785],[374,790],[352,779]],[[390,806],[491,806],[481,833],[465,850],[439,856],[414,846],[396,828]],[[452,736],[549,735],[543,758],[523,775],[500,782],[476,772]],[[525,821],[623,819],[615,843],[594,859],[571,864],[546,849]],[[534,750],[623,750],[615,774],[598,786],[577,791],[550,781]],[[603,806],[700,806],[693,832],[668,850],[650,854],[625,843]],[[603,737],[703,736],[695,762],[674,778],[650,783],[628,773]],[[658,813],[751,814],[744,839],[725,856],[704,859],[680,847]],[[717,815],[817,814],[808,839],[787,857],[765,859],[741,848]]]},
"HH-9395":{"bottom":1068,"bg":[[[209,519],[224,529],[224,688],[209,688]],[[240,584],[256,582],[256,689],[240,688]],[[273,523],[284,532],[291,576],[293,687],[273,687]],[[308,584],[322,582],[322,688],[307,688]],[[190,711],[321,716],[320,733],[190,731]],[[123,839],[133,829],[151,831],[160,844],[160,938],[132,965],[124,968]],[[192,851],[207,852],[215,847],[228,840],[249,839],[266,852],[276,848],[290,839],[304,843],[315,854],[316,925],[192,936]],[[191,960],[316,975],[317,1014],[128,1009]],[[120,1047],[320,1057],[320,1110],[117,1110]]]}
}
JSON
cat > /workspace/scratch/applyedits.py <<'PY'
import cv2,numpy as np,json,tifffile,sys
from scipy import ndimage as ndi
from PIL import Image
from pathlib import Path
cv2.setNumThreads(2)
edits=json.load(open('/workspace/scratch/edits.json'));boxes=json.load(open('/workspace/scratch/detailboxes.json'));sources=json.load(open('/workspace/scratch/sources.json'))
Path('/workspace/scratch/refined').mkdir(exist_ok=True)
for s in sys.argv[1:] or list(edits):
 a=tifffile.imread('/workspace/input/'+sources[s]).astype('float32')/65535
 m=cv2.imread('/workspace/scratch/hard/'+s+'.png',0)
 e=edits[s];x,y,_,_=boxes[s]
 if 'bottom' in e:m[y+e['bottom']:]=0
 for key,col in [('bg',0),('fg',255)]:
  for poly in e.get(key,[]):
   p=np.array(poly,dtype='int32')+[x,y];cv2.fillPoly(m,[p],col)
 # Snap boundaries to original RGB edges in a limited 3 px band
 di=ndi.distance_transform_edt(m>127);do=ndi.distance_transform_edt(m<128)
 gc=np.where(m>127,3,2).astype('uint8');gc[di>3]=1;gc[do>3]=0
 cv2.grabCut((a*255).astype('uint8'),gc,None,np.zeros((1,65)),np.zeros((1,65)),2,cv2.GC_INIT_WITH_MASK)
 m=np.isin(gc,[1,3]).astype('uint8')*255
 cv2.imwrite('/workspace/scratch/refined/'+s+'.png',m)
 comp=a*(m[:,:,None]/255)+np.array([.15,.4,.45])*(1-m[:,:,None]/255)
 Image.fromarray(np.rint(comp*255).astype('uint8')).crop(tuple(boxes[s])).save('/workspace/scratch/refined/'+s+'_detail.jpg')
 print(s,flush=True)
PY
OPENBLAS_NUM_THREADS=1 python /workspace/scratch/applyedits.py