cat > /workspace/scratch/fur7101.py <<'PY'
import cv2,numpy as np,tifffile,json
from scipy import ndimage as ndi
from PIL import Image
s='HH-7158';p='/workspace/scratch/finalmasks/'+s+'.png';cv2.imwrite(p,np.minimum(cv2.imread(p,0),cv2.imread('/workspace/scratch/7158_pre.png',0)))
s='HH-7101';p='/workspace/scratch/finalmasks/'+s+'.png';old=cv2.imread('/workspace/scratch/7101_pre.png',0);m=old>127
ox,oy=json.load(open('/workspace/scratch/detailboxes.json'))[s][:2]
a=(tifffile.imread('/workspace/input/photos/'+s+'.tif').astype('float32')/65535)**2.2
fg=ndi.distance_transform_edt(m)>23;bg=ndi.distance_transform_edt(~m)>14
_,fi=ndi.distance_transform_edt(~fg,return_indices=True);_,bi=ndi.distance_transform_edt(~bg,return_indices=True)
T=cv2.GaussianBlur(np.abs(a-cv2.GaussianBlur(a,(11,1),1.8)).mean(2),(5,5),.9)
Ts=cv2.GaussianBlur(T,(15,15),3)
TF=Ts[fi[0],fi[1]];TB=Ts[bi[0],bi[1]]
al=np.clip((T-TB)/(TF-TB+1e-6),0,1);al[fg]=1;al[bg]=0;al[al<.1]=0
# Only the dark sofa-facing top edge needs this texture separation.
old[:oy+260]=np.minimum(old[:oy+260],np.rint(al[:oy+260]*255).astype('uint8'))
# Fine dark fibres on the bright floor: remove horizontal boards, not the hairs.
B=cv2.morphologyEx(a,cv2.MORPH_CLOSE,np.ones((1,41),np.uint8));F=cv2.GaussianBlur(a,(5,5),1)[fi[0],fi[1]];D=F-B
al2=np.clip(((a-B)*D).sum(2)/((D*D).sum(2)+1e-7),0,1);al2[fg]=1;al2[bg]=0;al2[al2<.035]=0
old[oy+1030:]=np.minimum(old[oy+1030:],np.rint(al2[oy+1030:]*255).astype('uint8'))
cv2.imwrite(p,old)
im=Image.open('/workspace/input/photos/'+s+'.tif');o=Image.new('RGB',im.size,(130,72,132));o.paste(im,(0,0),Image.fromarray(old));o.crop(json.load(open('/workspace/scratch/detailboxes.json'))[s]).save('/workspace/scratch/check_'+s+'.png')
PY
OPENBLAS_NUM_THREADS=1 python /workspace/scratch/fur7101.py