Attempt at cubism

@Joan_Rake1 You could always hide it with [details=text]...[/details].

Toggle to see Joan's awesome code.
#@gui Cubism: fx_jr_cubism_preview
#@gui : sep = separator()
#@gui : 0. Recompute = button()
#@gui : 1. Threshold=float(2,0,15)
#@gui : 2. Smoothness=float(1,0,500)
#@gui : 3. Offset Amplitude=float(10,0,100)
#@gui : 4. Anti-Aliasing=bool(1)
fx_jr_cubism:
repeat $! l[$>]
ww={w}
hh={h}
aa=$4
amp={$3*norm(w,h)*0.01}
+b. $2 segment_watershed. $1
f. ">begin(srand();rand=u(100,200));srand(i*rand);u"
repeat {s}
sh. $> *. {u(1,2)} rm.
done
to_gray.
label.
initsize={1+iM#1}
$initsize,5,1,1
vsize={$initsize*2}
eval ${-math_lib}"
coordinates_per_val=vector"$vsize"(0);
count_per_val=vector"$initsize"(0);
for(px=0,px<w#1,px++,
    for(py=0,py<h#1,py++,
        pos=i(#1,px,py);
        coordinates_per_val[pos*2]+=px;
        coordinates_per_val[pos*2+1]+=py;
        count_per_val[pos]++;
    );
);
for(n=0,n<"$initsize",n++,
    coordinates_per_val[n*2]/=count_per_val[n];
    coordinates_per_val[n*2+1]/=count_per_val[n];
	I(n,0)=coordinates_per_val[n*2];
	I(n,1)=coordinates_per_val[n*2+1];
);
"
repeat {3}
row={$>+2}
sh. $row,$row,0,0 f. ">begin(randm=u(100+y,200+y);randa=u(1,3));srand((x+(randa))*randm);u"
if {$>==2} n. 0,{2*pi} else n. 0,$amp fi
rm.
done
$ww,$hh,1,2
f. "val=vector2(0);
I(#1)!=J(#1,1)?(val[0]+=1);
I(#1)!=J(#1,0,1)?(val[1]+=1);
I(#1)!=J(#1,-1)?(val[0]-=1);
I(#1)!=J(#1,0,-1)?(val[1]-=1);
val"
*. 255
+smooth. 10,0,1,1,5,15,0
-.. .
rm.
/. 510
f[0] "begin(const spec=s;
cubism(id,xx,yy)=(
params=crop(#2,id,0,0,0,1,5,1,1);
xro=params[0];
yro=params[1];
xoff=params[2];
yoff=params[3];
ang=params[4];
sang=sin(ang);
cang=cos(ang);
vx=xx-xro-xoff;
vy=yy-yro-yoff;
I(vx*cang+vy*sang+xoff+xro,vy*cang-vx*sang+yoff+yro,0,1,3)));
xs=i(#-1,x,y,0,0);
ys=i(#-1,x,y,0,1);
("$aa"&&xs!=0&&ys!=0)?(
idlist=vector(#4,-1);
freqlist=vector(#4,0);
idnum=0;
xdir=sign(xs);ydir=sign(ys);
xo=abs(xs);yo=abs(ys);
gridmult=[(1-xo)*(1-yo),xo*(1-yo),(1-xo)*yo,xo*yo];
for(py=0,py<2,py++,
	for(px=0,px<2,px++,
		curr=i(#1,x+xdir*px,y+ydir*py,0,0,1);
		pos=find(idlist,curr);
		pos==-1?(idnum+=1;pos=find(idlist,-1);idlist[pos]=curr);
		freqlist[pos]+=gridmult[py*2+px];
	);
);
val=vector(#spec,0);
for(n=0,n<idnum,n++,
val+=cubism(idlist[n],x,y)*freqlist[n]);
val):(cubism(i(#1,x,y,0,0,1),x,y))
"
rm[^0]
endl done
fx_jr_cubism_preview:
fx_jr_cubism ${2-5}

After testing it, I still find myself to have odd structures.

Test Picture (does not exist woman):

Result:

This is after pushing smoothness to half-value.

That’s because the blurring would be at 250 pixels and the segmentation begins looking for very small differences which seem to all be linear.

Okay, I don’t know how I’m gonna handle the 3D rotations. I want to use rot(u,v,w,angle), but is the matrix normalised?

Cubism but 3D!
#@gui Cubism: fx_jr_cubism_preview
#@gui : sep = separator()
#@gui : 0. Recompute = button()
#@gui : 1. Threshold=float(2,0,15)
#@gui : 2. Smoothness=float(5,0,20)
#@gui : 3. Offset Amplitude=float(10,0,100)
#@gui : 4. Anti-Aliasing=bool(1)
#@gui : 5. X Offset Centre=float(0,-100,100)
#@gui : 6. X Offset Range=float(25,0,200)
#@gui : 7. Y Offset Centre=float(0,-100,100)
#@gui : 8. Y Offset Range=float(25,0,200)
#@gui : 9. Z Offset Centre=float(0,-100,100)
#@gui : 10. Z Offset Range=float(0,0,200)
#@gui : 11. Rot Angle Centre=float(0,-360,360)
#@gui : 12. Rot Angle Range=float(360,0,360)
#@gui : 13. Rot Axis X Centre=float(0,-1,1)
#@gui : 14. Rot Axis X Range=float(0,0,2)
#@gui : 15. Rot Axis Y Centre=float(0,-1,1)
#@gui : 16. Rot Axis Y Range=float(0,0,2)
#@gui : 17. Rot Axis Z Centre=float(1,-1,1)
#@gui : 18. Rot Axis Z Range=float(0,0,2)
fx_jr_cubism:
repeat $! l[$>]
ww={w}
hh={h}
dd={d}
aa=$4
xoffc=$5*0.01*$ww
xoffr=$6*0.01*$hh
yoffc=$7*0.01*$dd
yoffr=$8*0.01*$ww
zoffc=$9*0.01*$hh
zoffr=$10*0.01*$dd
rotac=$11
rotar=$12
rotxxc=$13
rotxxr=$14
rotxyc=$15
rotxyr=$16
rotxzc=$17
rotxzr=$18
amp={$3*norm(w,h,d)*0.01}
+b. $2% segment_watershed. $1
#temporary multichannel label workaround
f. ">begin(srand();rand=u(100,200));srand(i*rand);u"
repeat {s}
sh. $> *. {u(1,2)} rm.
done
to_gray.
#end workaround
label.
initsize={1+iM#1}
$initsize,10,1,1
vsize={$initsize*3}
eval ${-math_lib}"
coordinates_per_val=vector"$vsize"(0);
count_per_val=vector"$initsize"(0);
for(px=0,px<w#1,px++,
    for(py=0,py<h#1,py++,
		for(pz=0,pz<d#1,pz++,
			pos=i(#1,px,py,pz);
			coordinates_per_val[pos*3]+=px;
			coordinates_per_val[pos*3+1]+=py;
			coordinates_per_val[pos*3+2]+=pz;
			count_per_val[pos]++;
		);
    );
);
for(n=0,n<"$initsize",n++,
    coordinates_per_val[n*3]/=count_per_val[n];
    coordinates_per_val[n*3+1]/=count_per_val[n];
	coordinates_per_val[n*3+2]/=count_per_val[n];
	I(n,0)=coordinates_per_val[n*3];
	I(n,1)=coordinates_per_val[n*3+1];
	I(n,2)=coordinates_per_val[n*3+2];
);
"
sh. 3,9,0,0 f. ">begin(randm=u(100+y,200+y);randa=u(1,3));srand((x+(randa))*randm);u(-1,1)"
eval. "for(n=0,n<w,n++,
strip=crop(n,0,0,0,1,7,1,1);
strip=strip*["$xoffr","$yoffr","$zoffr","$rotar","$rotxxr","$rotxyr","$rotxzr"]+["$xoffc","$yoffc","$zoffc","$rotac","$rotxxc","$rotxyc","$rotxzc"];
draw(strip,n,0,0,0,1,7,1,1,1))
"
rm.
$ww,$hh,$dd,3
f. "begin(boundary=1);val=vector3(0);
I(#1)!=J(#1,1)?(val[0]+=1);
I(#1)!=J(#1,0,1)?(val[1]+=1);
I(#1)!=J(#1,0,0,1)?(val[2]+=1);
I(#1)!=J(#1,-1)?(val[0]-=1);
I(#1)!=J(#1,0,-1)?(val[1]-=1);
I(#1)!=J(#1,0,0,-1)?(val[2]-=1);
val"
if $4
*. 255
+smooth. 10,0,1,1,5,15,0
-.. .
rm.
/. 510
fi
f[0] "begin(const spec=s;
cubism(id,xx,yy,zz)=(
params=crop(#2,id,0,0,0,1,10,1,1);
xoff=params[0]+params[3];
yoff=params[1]+params[4];
zoff=params[2]+params[5];
ang=params[6];
xa=params[7];
ya=params[8];
za=params[9];
vx=xx-xoff;
vy=yy-yoff;
vz=zz-zoff;
select=rot(asin([xa,ya,za])*2/pi,ang)*[vx,vy,vz]+[xoff,yoff,zoff];
I(select,1,3)));
xs=i(#-1,x,y,z,0);
ys=i(#-1,x,y,z,1);
zs=i(#-1,x,y,z,2);
("$aa"&&xs!=0&&ys!=0&&zs!=0)?(
idlist=vector(#8,-1);
freqlist=vector(#8,0);
idnum=0;
xdir=sign(xs);ydir=sign(ys);zdir=sign(zs);
xo=abs(xs);yo=abs(ys);zo=abs(zs);
gridmult=[(1-xo)*(1-yo)*(1-zo),xo*(1-yo)*(1-zo),(1-xo)*yo*(1-zo),xo*yo*(1-zo),(1-xo)*(1-yo)*zo,xo*(1-yo)*zo,(1-xo)*yo*zo,xo*yo*zo];
for(pz=0,pz<2,pz++,
	for(py=0,py<2,py++,
		for(px=0,px<2,px++,
			curr=i(#1,x+xdir*px,y+ydir*py,z+zdir*pz,0,1);
			pos=find(idlist,curr);
			pos==-1?(idnum+=1;pos=find(idlist,-1);idlist[pos]=curr);
			freqlist[pos]+=gridmult[pz*4+py*2+px];
		);
	);
);
val=vector(#spec,0);
for(n=0,n<idnum,n++,
val+=cubism(idlist[n],x,y,z)*freqlist[n]);
val):(cubism(i(#1,x,y,z,0,1),x,y,z))
"
rm[^0]
endl done
fx_jr_cubism_preview:
fx_jr_cubism ${2-19}

I wanted to do this because I’d be able to take 2D slices of jumbled 3D images.

3D Cubism? That’s just insanity. After testing, I see anti-alias doesn’t work after changing 3D setting.

Damn. I can’t test on 2.9.1 because label doesn’t work with 3D images. I was looking forward to really blitzing 2D images together.

Hmm, you can make a feature request via github to make it work with 3D image.

From what I gather it’s a bug. If we look at Function 'CImg<T>::label()' : change behavior to return only a single… · dtschump/CImg@dafbc86 · GitHub then even before it had a single-channel output (in 2.9.2) it was supposed to handle 3D inputs.

sh. 3,9,0,0 f. ">begin(randm=u(100+y,200+y);randa=u(1,3));srand((x+(randa))*randm);u(-1,1)"
eval. "begin(multvec=["$xoffr","$yoffr","$zoffr","$rotar","$rotxxr","$rotxyr","$rotxzr"];addvec=["$xoffc","$yoffc","$zoffc","$rotac","$rotxxc","$rotxyc","$rotxzc"]);for(n=0,n<w,n++,
strip=crop(n,0,0,0,1,7,1,1);
draw(#3,strip*multvec+addvec,n,0,0,0,1,7,1,1,1))

I updated to 2.9.2 and for some reason this doesn’t work. The variables aren’t being assigned properly.

Edit: now that’s working, I will check if the labelling works fine later. The AA is broken again and I don’t know why. Am I just not doing trilinear interpolation right? As usual I cannot see any errors in here, although well after I complain I’ll find something.

Broken AA
#@gui Cubism: fx_jr_cubism_preview
#@gui : sep = separator()
#@gui : 0. Recompute = button()
#@gui : 1. Threshold=float(2,0,15)
#@gui : 2. Smoothness=float(5,0,20)
#@gui : 3. Offset Amplitude=float(10,0,100)
#@gui : 4. X Offset Centre=float(0,-100,100)
#@gui : 5. X Offset Range=float(25,0,200)
#@gui : 6. Y Offset Centre=float(0,-100,100)
#@gui : 7. Y Offset Range=float(25,0,200)
#@gui : 8. Z Offset Centre=float(0,-100,100)
#@gui : 9. Z Offset Range=float(0,0,200)
#@gui : 10. Rot Angle Centre=float(0,-360,360)
#@gui : 11. Rot Angle Range=float(360,0,360)
#@gui : 12. Rot Axis X Centre=float(0,-1,1)
#@gui : 13. Rot Axis X Range=float(0,0,2)
#@gui : 14. Rot Axis Y Centre=float(0,-1,1)
#@gui : 15. Rot Axis Y Range=float(0,0,2)
#@gui : 16. Rot Axis Z Centre=float(1,-1,1)
#@gui : 17. Rot Axis Z Range=float(0,0,2)
#@gui : 18. Anti-Aliasing=bool(1)
fx_jr_cubism:
rotac=$10
rotar=$11
rotxxc=$12
rotxxr=$13
rotxyc=$14
rotxyr=$15
rotxzc=$16
rotxzr=$17
aa=$18
repeat $! l[$>]
ww={w}
hh={h}
dd={d}
xoffc=$4*0.01*$ww
xoffr=$5*0.01*$hh
yoffc=$6*0.01*$dd
yoffr=$7*0.01*$ww
zoffc=$8*0.01*$hh
zoffr=$9*0.01*$dd
amp={$3*norm(w,h,d)*0.01}
+b. $2% segment_watershed. $1
label.
initsize={1+iM#1}
$initsize,10,1,1
vsize={$initsize*3}
eval ${-math_lib}"
coordinates_per_val=vector"$vsize"(0);
count_per_val=vector"$initsize"(0);
for(px=0,px<w#1,px++,
    for(py=0,py<h#1,py++,
		for(pz=0,pz<d#1,pz++,
			pos=i(#1,px,py,pz);
			coordinates_per_val[pos*3]+=px;
			coordinates_per_val[pos*3+1]+=py;
			coordinates_per_val[pos*3+2]+=pz;
			count_per_val[pos]++;
		);
    );
);
for(n=0,n<"$initsize",n++,
    coordinates_per_val[n*3]/=count_per_val[n];
    coordinates_per_val[n*3+1]/=count_per_val[n];
	coordinates_per_val[n*3+2]/=count_per_val[n];
	I(n,0)=coordinates_per_val[n*3];
	I(n,1)=coordinates_per_val[n*3+1];
	I(n,2)=coordinates_per_val[n*3+2];
);
"

sh. 3,9,0,0 f. ">begin(randm=u(100,200);randa=u(1,3));srand((x+(randa)+(u))*(randm+y));u(-1,1)"
eval. "begin(multvec=["$xoffr","$yoffr","$zoffr","$rotar","$rotxxr","$rotxyr","$rotxzr"];
addvec=["$xoffc","$yoffc","$zoffc","$rotac","$rotxxc","$rotxyc","$rotxzc"]);
for(n=0,n<w,n++,
strip=crop(n,0,0,0,1,7,1,1);
draw(#3,strip*multvec+addvec,n,0,0,0,1,7,1,1,1))
"

rm.
$ww,$hh,$dd,3
f. "begin(boundary=1);val=vector3(0);
I(#1)!=J(#1,1)?(val[0]+=1);
I(#1)!=J(#1,0,1)?(val[1]+=1);
I(#1)!=J(#1,0,0,1)?(val[2]+=1);
I(#1)!=J(#1,-1)?(val[0]-=1);
I(#1)!=J(#1,0,-1)?(val[1]-=1);
I(#1)!=J(#1,0,0,-1)?(val[2]-=1);
val"
*. 255
+smooth. 10,0,1,1,5,15,0
-.. .
rm.
/. 510
f[0] "begin(const spec=s;
cubism(id,xx,yy,zz)=(
params=crop(#2,id,0,0,0,1,10,1,1);
xoff=params[0]+params[3];
yoff=params[1]+params[4];
zoff=params[2]+params[5];
ang=params[6];
xa=params[7];
ya=params[8];
za=params[9];
vx=xx-xoff;
vy=yy-yoff;
vz=zz-zoff;
pix=[xa,ya,za];
select=rot(asin(pix/norm(pix))*2/pi,ang)*[vx,vy,vz]+[xoff,yoff,zoff];
I(select,1,3)));
xs=i(#-1,x,y,z,0);
ys=i(#-1,x,y,z,1);
zs=i(#-1,x,y,z,2);
("$aa"&&xs!=0&&ys!=0&&zs!=0)?(
idlist=vector(#8,-1);
freqlist=vector(#8,0);
idnum=0;
xdir=sign(xs);ydir=sign(ys);zdir=sign(zs);
xo=abs(xs);yo=abs(ys);zo=abs(zs);
gridmult=[(1-xo)*(1-yo)*(1-zo),xo*(1-yo)*(1-zo),(1-xo)*yo*(1-zo),xo*yo*(1-zo),(1-xo)*(1-yo)*zo,xo*(1-yo)*zo,(1-xo)*yo*zo,xo*yo*zo];
for(pz=0,pz<2,pz++,
	for(py=0,py<2,py++,
		for(px=0,px<2,px++,
			curr=i(#1,x+xdir*px,y+ydir*py,z+zdir*pz,0,1);
			pos=find(idlist,curr);
			pos==-1?(idnum+=1;pos=find(idlist,-1);idlist[pos]=curr);
			freqlist[pos]+=gridmult[pz*4+py*2+px];
		);
	);
);
val=vector(#spec,0);
for(n=0,n<idnum,n++,
val+=cubism(idlist[n],x,y,z)*freqlist[n]);
val):(cubism(i(#1,x,y,z,0,1),x,y,z))
"
rm[^0]
endl done
fx_jr_cubism_preview:
fx_jr_cubism ${2-19}

Finally figured it out. I was using the wrong condition in the last fill block.

First-ish stab at AA
#@gui Cubism: fx_jr_cubism_preview
#@gui : sep = separator()
#@gui : 0. Recompute = button()
#@gui : 1. Threshold=float(2,0,15)
#@gui : 2. Smoothness=float(5,0,20)
#@gui : 3. Offset Amplitude=float(10,0,100)
#@gui : 4. X Offset Centre=float(0,-100,100)
#@gui : 5. X Offset Range=float(25,0,200)
#@gui : 6. Y Offset Centre=float(0,-100,100)
#@gui : 7. Y Offset Range=float(25,0,200)
#@gui : 8. Z Offset Centre=float(0,-100,100)
#@gui : 9. Z Offset Range=float(0,0,200)
#@gui : 10. Rot Angle Centre=float(0,-360,360)
#@gui : 11. Rot Angle Range=float(360,0,360)
#@gui : 12. Rot Axis X Centre=float(0,-1,1)
#@gui : 13. Rot Axis X Range=float(0,0,2)
#@gui : 14. Rot Axis Y Centre=float(0,-1,1)
#@gui : 15. Rot Axis Y Range=float(0,0,2)
#@gui : 16. Rot Axis Z Centre=float(1,-1,1)
#@gui : 17. Rot Axis Z Range=float(0,0,2)
#@gui : 18. AA Iterations=int(10,0,100)
#@gui : 19. Sharpness=float(0,0,2)
#@gui : 20. AA Anisotropy=float(1,0,1)
#@gui : 21. AA Gradient Smoothness=float(1,0,10)
#@gui : 22. Tensor Smoothness=float(5,0,10)
#@gui : 23. Time Step=float(15,5,50)

fx_jr_cubism:
rotac=$10
rotar=$11
rotxxc=$12
rotxxr=$13
rotxyc=$14
rotxyr=$15
rotxzc=$16
rotxzr=$17
aa=$18
repeat $! l[$>]
ww={w}
hh={h}
dd={d}
xoffc=$4*0.01*$ww
xoffr=$5*0.01*$hh
yoffc=$6*0.01*$dd
yoffr=$7*0.01*$ww
zoffc=$8*0.01*$hh
zoffr=$9*0.01*$dd
amp={$3*norm(w,h,d)*0.01}
+b. $2% segment_watershed. $1
label.
initsize={1+iM#1}
$initsize,10,1,1
vsize={$initsize*3}
eval ${-math_lib}"
coordinates_per_val=vector"$vsize"(0);
count_per_val=vector"$initsize"(0);
for(px=0,px<w#1,px++,
    for(py=0,py<h#1,py++,
		for(pz=0,pz<d#1,pz++,
			pos=i(#1,px,py,pz);
			coordinates_per_val[pos*3]+=px;
			coordinates_per_val[pos*3+1]+=py;
			coordinates_per_val[pos*3+2]+=pz;
			count_per_val[pos]++;
		);
    );
);
for(n=0,n<"$initsize",n++,
    coordinates_per_val[n*3]/=count_per_val[n];
    coordinates_per_val[n*3+1]/=count_per_val[n];
	coordinates_per_val[n*3+2]/=count_per_val[n];
	I(n,0)=coordinates_per_val[n*3];
	I(n,1)=coordinates_per_val[n*3+1];
	I(n,2)=coordinates_per_val[n*3+2];
);
"

sh. 3,9,0,0 f. ">begin(randm=u(100,200);randa=u(1,3));srand((x+(randa)+(u))*(randm+y));u(-1,1)"
eval. "begin(multvec=["$xoffr","$yoffr","$zoffr","$rotar","$rotxxr","$rotxyr","$rotxzr"];
addvec=["$xoffc","$yoffc","$zoffc","$rotac","$rotxxc","$rotxyc","$rotxzc"]);
for(n=0,n<w,n++,
strip=crop(n,0,0,0,1,7,1,1);
draw(#3,strip*multvec+addvec,n,0,0,0,1,7,1,1,1))
"
rm.
$ww,$hh,$dd,3
f. "begin(boundary=1);val=vector3(0);
I(#1)!=J(#1,1)?(val[0]+=1);
I(#1)!=J(#1,0,1)?(val[1]+=1);
I(#1)!=J(#1,0,0,1)?(val[2]+=1);
I(#1)!=J(#1,-1)?(val[0]-=1);
I(#1)!=J(#1,0,-1)?(val[1]-=1);
I(#1)!=J(#1,0,0,-1)?(val[2]-=1);
val"
*. 255
+smooth. $aa,${19-23},0
-.. .
rm.
/. 510
f[0] "begin(const spec=s;aa="$aa";
cubism(id,xx,yy,zz)=(
params=crop(#2,id,0,0,0,1,10,1,1);
xoff=params[0]+params[3];
yoff=params[1]+params[4];
zoff=params[2]+params[5];
ang=params[6];
xa=params[7];
ya=params[8];
za=params[9];
vx=xx-xoff;
vy=yy-yoff;
vz=zz-zoff;
pix=[xa,ya,za];
select=rot(asin(pix/norm(pix))*2/pi,ang)*[vx,vy,vz]+[xoff,yoff,zoff];
I(select,1,3)));
xs=i(#-1,x,y,z,0);
ys=i(#-1,x,y,z,1);
zs=i(#-1,x,y,z,2);
(aa&&(xs!=0||ys!=0||zs!=0))?(
idlist=vector(#8,-1);
freqlist=vector(#8,0);
idnum=0;
xdir=sign(xs);ydir=sign(ys);zdir=sign(zs);
xo=abs(xs);yo=abs(ys);zo=abs(zs);
gridmult=[(1-xo)*(1-yo)*(1-zo),xo*(1-yo)*(1-zo),(1-xo)*yo*(1-zo),xo*yo*(1-zo),(1-xo)*(1-yo)*zo,xo*(1-yo)*zo,(1-xo)*yo*zo,xo*yo*zo];
for(pz=0,pz<2,pz++,
	for(py=0,py<2,py++,
		for(px=0,px<2,px++,
			curr=i(#1,x+xdir*px,y+ydir*py,z+zdir*pz,0,1);
			pos=find(idlist,curr);
			pos==-1?(idnum+=1;pos=find(idlist,-1);idlist[pos]=curr);
			freqlist[pos]+=gridmult[pz*4+py*2+px];
		);
	);
);
val=vector(#spec,0);
for(n=0,n<idnum,n++,
val+=cubism(idlist[n],x,y,z)*freqlist[n]);
val):(cubism(i(#1,x,y,z,0,1),x,y,z))
"
rm[^0]
endl done
fx_jr_cubism_preview:
fx_jr_cubism ${2-24}

I’m far from done though. There’s some kinks in the AA algorithm I need to take care of, such as the fact that the window for blending can be too small and produce some very jagged effects.

1 Like

First-ish stab

My brain’s auto-complete read fish stab. :roll_eyes:

David, could you please add a directional version of the distance transform? If that’s not possible, I guess I could somehow build it myself. I know that direction2rgb exists but it won’t work in 3 dimensions.

He does not seem to be active. I guess you should do it. I cannot help as it is difficult for me to code 3D.

Okay. I could use this:

gradient_norm
f. "i==0?0:1"
distance 1
+g xyz
a[1-3] c
*. ..

I’ll use smoothing on a gradient norm and then use the difference between the smoothed version and the original to get distances and directions for the thing it’s gonna copy.

1 Like

Would gradient_orientation be useful to you?

I could add the result to the previous thing I got somehow…

+label l[1]
g xy +sqr +[-2,-1] +. 1e-8 sqrt. /... . /[-2,-1]
a c
endl
l[0]
gradient_norm
f. "i==0?0:1"
distance 1
+g xyz
a[1-3] c
*. ..
k[1]
endl
f[0] "(i==0)?(i(#1)):(sign(i)*(abs(i)+1))"
k[0]
``

Improved this a bit.

+label l[1]
+gradient_orientation. 3
a[^0] c
100%,100%,100%,1,"round(norm(I(#1)))"
distance. 1
+gradient_orientation. 3
f[2] "i+0.5"
*[3-5] [2] a[3-5] c
rm[^3]
endl

I don’t know how I can do this with the present method. All I want is to have a location for the nearest pixel that’s just beyond the boundary of the segment that the pixel is in using the distance thing but I don’t know if I’ve got it working right and the method is wrong or I haven’t implemented it properly. When the width of a segment is less than 1 it doesn’t blur anything at all.

Another try
#@gui Cubism: fx_jr_rep_cubism_preview
#@gui : sep = separator()
#@gui : 0. Recompute = button()
#@gui : 1. Threshold=float(2,0,15)
#@gui : 2. Smoothness=float(5,0,20)
#@gui : 3. Offset Amplitude=float(10,0,100)
#@gui : 4. X Offset Centre=float(0,-100,100)
#@gui : 5. X Offset Range=float(25,0,200)
#@gui : 6. Y Offset Centre=float(0,-100,100)
#@gui : 7. Y Offset Range=float(25,0,200)
#@gui : 8. Z Offset Centre=float(0,-100,100)
#@gui : 9. Z Offset Range=float(0,0,200)
#@gui : 10. Rot Angle Centre=float(0,-360,360)
#@gui : 11. Rot Angle Range=float(360,0,360)
#@gui : 12. Rot Axis X Centre=float(0,-1,1)
#@gui : 13. Rot Axis X Range=float(0,0,2)
#@gui : 14. Rot Axis Y Centre=float(0,-1,1)
#@gui : 15. Rot Axis Y Range=float(0,0,2)
#@gui : 16. Rot Axis Z Centre=float(1,-1,1)
#@gui : 17. Rot Axis Z Range=float(0,0,2)
#@gui : 18. AA Iterations=int(10,0,100)
#@gui : 19. Sharpness=float(0,0,2)
#@gui : 20. AA Anisotropy=float(1,0,1)
#@gui : 21. AA Gradient Smoothness=float(1,0,10)
#@gui : 22. Tensor Smoothness=float(5,0,10)
#@gui : 23. Time Step=float(15,5,50)

fx_jr_rep_cubism:
rotac=$10
rotar=$11
rotxxc=$12
rotxxr=$13
rotxyc=$14
rotxyr=$15
rotxzc=$16
rotxzr=$17
aa=$18
repeat $! l[$>]
ww={w}
hh={h}
dd={d}
xoffc=$4*0.01*$ww
xoffr=$5*0.01*$hh
yoffc=$6*0.01*$dd
yoffr=$7*0.01*$ww
zoffc=$8*0.01*$hh
zoffr=$9*0.01*$dd
amp={$3*norm(w,h,d)*0.01}
+b. $2% segment_watershed. $1
label.
l[1]
+gradient_orientation. 3
a[^0] c
100%,100%,100%,1,"min(1,ceil(norm(I(#1))))"
rm[1]
distance. 1
+gradient_orientation. 3
f[1] "-(i+0.5)"
*[2-4] [1] a[2-4] c
rm[1]
endl
initsize={1+iM#1}
$initsize,10,1,1
vsize={$initsize*3}
eval ${-math_lib}"
coordinates_per_val=vector"$vsize"(0);
count_per_val=vector"$initsize"(0);
for(px=0,px<w#1,px++,
    for(py=0,py<h#1,py++,
		for(pz=0,pz<d#1,pz++,
			pos=i(#1,px,py,pz);
			coordinates_per_val[pos*3]+=px;
			coordinates_per_val[pos*3+1]+=py;
			coordinates_per_val[pos*3+2]+=pz;
			count_per_val[pos]++;
		);
    );
);
for(n=0,n<"$initsize",n++,
    coordinates_per_val[n*3]/=count_per_val[n];
    coordinates_per_val[n*3+1]/=count_per_val[n];
	coordinates_per_val[n*3+2]/=count_per_val[n];
	I(n,0)=coordinates_per_val[n*3];
	I(n,1)=coordinates_per_val[n*3+1];
	I(n,2)=coordinates_per_val[n*3+2];
);
"

sh. 3,9,0,0 f. ">begin(randm=u(100,200);randa=u(1,3));srand((x+(randa)+(u))*(randm+y));u(-1,1)"
eval. "begin(multvec=["$xoffr","$yoffr","$zoffr","$rotar","$rotxxr","$rotxyr","$rotxzr"];
addvec=["$xoffc","$yoffc","$zoffc","$rotac","$rotxxc","$rotxyc","$rotxzc"]);
for(n=0,n<w,n++,
strip=crop(n,0,0,0,1,7,1,1);
draw(#4,strip*multvec+addvec,n,0,0,0,1,7,1,1,1))
"

rm.
$ww,$hh,$dd,3
f. "begin(boundary=1);val=vector3(0);
I(#1)!=J(#1,1)?(val[0]+=1);
I(#1)!=J(#1,0,1)?(val[1]+=1);
I(#1)!=J(#1,0,0,1)?(val[2]+=1);
I(#1)!=J(#1,-1)?(val[0]-=1);
I(#1)!=J(#1,0,-1)?(val[1]-=1);
I(#1)!=J(#1,0,0,-1)?(val[2]-=1);
val"
*. 255
+smooth. $aa,${19-23},0
-.. .
rm.
/. 510

f[0] "begin(const spec=s;aa="$aa";
cubism(id,xx,yy,zz)=(
params=crop(#3,id,0,0,0,1,10,1,1);
xoff=params[0]+params[3];
yoff=params[1]+params[4];
zoff=params[2]+params[5];
ang=params[6];
xa=params[7];
ya=params[8];
za=params[9];
vx=xx-xoff;
vy=yy-yoff;
vz=zz-zoff;
pix=[xa,ya,za];
select=rot(asin(pix/norm(pix))*2/pi,ang)*[vx,vy,vz]+[xoff,yoff,zoff];
I(select,1,3)));
xs=i(#2,x,y,z,0);
ys=i(#2,x,y,z,1);
zs=i(#2,x,y,z,2);
dist=max(abs([xs,ys,zs]));
(aa&&(dist<=1))?(
idlist=vector(#9,-1);
freqlist=vector(#9,0);
idnum=0;
xint=floor(xs);yint=floor(ys);zint=floor(zs);
xo=xs-xint;yo=ys-yint;zo=zs-zint;
gridmult=[(1-xo)*(1-yo)*(1-zo),xo*(1-yo)*(1-zo),(1-xo)*yo*(1-zo),xo*yo*(1-zo),(1-xo)*(1-yo)*zo,xo*(1-yo)*zo,(1-xo)*yo*zo,xo*yo*zo];
for(pz=0,pz<2,pz++,
	for(py=0,py<2,py++,
		for(px=0,px<2,px++,
			curr=i(#1,x+xint+px,y+yint+py,z+zint+pz,0,1);
			pos=find(idlist,curr);
			pos==-1?(idnum+=1;pos=find(idlist,-1);idlist[pos]=curr);
			freqlist[pos]+=gridmult[pz*4+py*2+px];
		);
	);
);
val=vector(#spec,0);
for(n=0,n<idnum,n++,
val+=cubism(idlist[n],x,y,z)*freqlist[n]);
lerp(val,cubism(i(#1,x,y,z,0,1),x,y,z),dist)):(cubism(i(#1,x,y,z,0,1),x,y,z))
"
rm[^0]
endl done
fx_jr_rep_cubism_preview:
fx_jr_rep_cubism ${2-24}

I’ve even tried a slightly different route but the edges remain jagged in slightly different ways!

Alternative try
#@gui Cubism: fx_jr_rep_cubism_preview
#@gui : sep = separator()
#@gui : 0. Recompute = button()
#@gui : 1. Threshold=float(2,0,15)
#@gui : 2. Smoothness=float(5,0,20)
#@gui : 3. Offset Amplitude=float(10,0,100)
#@gui : 4. X Offset Centre=float(0,-100,100)
#@gui : 5. X Offset Range=float(25,0,200)
#@gui : 6. Y Offset Centre=float(0,-100,100)
#@gui : 7. Y Offset Range=float(25,0,200)
#@gui : 8. Z Offset Centre=float(0,-100,100)
#@gui : 9. Z Offset Range=float(0,0,200)
#@gui : 10. Rot Angle Centre=float(0,-360,360)
#@gui : 11. Rot Angle Range=float(360,0,360)
#@gui : 12. Rot Axis X Centre=float(0,-1,1)
#@gui : 13. Rot Axis X Range=float(0,0,2)
#@gui : 14. Rot Axis Y Centre=float(0,-1,1)
#@gui : 15. Rot Axis Y Range=float(0,0,2)
#@gui : 16. Rot Axis Z Centre=float(1,-1,1)
#@gui : 17. Rot Axis Z Range=float(0,0,2)
#@gui : 18. AA Iterations=int(16,0,100)
#@gui : 19. Time Step=float(16,5,50)

fx_jr_rep_cubism:
rotac=$10
rotar=$11
rotxxc=$12
rotxxr=$13
rotxyc=$14
rotxyr=$15
rotxzc=$16
rotxzr=$17
aa=$18
repeat $! l[$>]
ww={w}
hh={h}
dd={d}
xoffc=$4*0.01*$ww
xoffr=$5*0.01*$hh
yoffc=$6*0.01*$dd
yoffr=$7*0.01*$ww
zoffc=$8*0.01*$hh
zoffr=$9*0.01*$dd
amp={$3*norm(w,h,d)*0.01}
+b. $2% segment_watershed. $1
label.
l[1]
+gradient_orientation. 3
a[^0] c
100%,100%,100%,1,"min(1,ceil(norm(I(#1))))"
rm[1]
distance. 1
+gradient_orientation. 3
f[1] "-(i)"
*[2-4] [1] a[2-4] c
rm[1]
endl
b. 2
initsize={1+iM#1}
$initsize,10,1,1
vsize={$initsize*3}
eval ${-math_lib}"
coordinates_per_val=vector"$vsize"(0);
count_per_val=vector"$initsize"(0);
for(px=0,px<w#1,px++,
    for(py=0,py<h#1,py++,
		for(pz=0,pz<d#1,pz++,
			pos=i(#1,px,py,pz);
			coordinates_per_val[pos*3]+=px;
			coordinates_per_val[pos*3+1]+=py;
			coordinates_per_val[pos*3+2]+=pz;
			count_per_val[pos]++;
		);
    );
);
for(n=0,n<"$initsize",n++,
    coordinates_per_val[n*3]/=count_per_val[n];
    coordinates_per_val[n*3+1]/=count_per_val[n];
	coordinates_per_val[n*3+2]/=count_per_val[n];
	I(n,0)=coordinates_per_val[n*3];
	I(n,1)=coordinates_per_val[n*3+1];
	I(n,2)=coordinates_per_val[n*3+2];
);
"

sh. 3,9,0,0 f. ">begin(randm=u(100,200);randa=u(1,3));srand((x+(randa)+(u))*(randm+y));u(-1,1)"
eval. "begin(multvec=["$xoffr","$yoffr","$zoffr","$rotar","$rotxxr","$rotxyr","$rotxzr"];
addvec=["$xoffc","$yoffc","$zoffc","$rotac","$rotxxc","$rotxyc","$rotxzc"]);
for(n=0,n<w,n++,
strip=crop(n,0,0,0,1,7,1,1);
draw(#4,strip*multvec+addvec,n,0,0,0,1,7,1,1,1))
"

rm.

+gradient_norm[1] f. "i>0?255:0"
+meancurvature_flow. $aa,$19
-.. .
rm.
abs.
/. 510
display
f[0] "begin(const spec=s;aa="$aa";
cubism(id,xx,yy,zz)=(
params=crop(#3,id,0,0,0,1,10,1,1);
xoff=params[0]+params[3];
yoff=params[1]+params[4];
zoff=params[2]+params[5];
ang=params[6];
xa=params[7];
ya=params[8];
za=params[9];
vx=xx-xoff;
vy=yy-yoff;
vz=zz-zoff;
pix=[xa,ya,za];
select=rot(asin(pix/norm(pix))*2/pi,ang)*[vx,vy,vz]+[xoff,yoff,zoff];
I(select,1,3)));
xs=i(#2,x,y,z,0);
ys=i(#2,x,y,z,1);
zs=i(#2,x,y,z,2);
dist=max(abs([xs,ys,zs]));
(aa&&(i(#4)>0))?(
idlist=vector(#9,-1);
freqlist=vector(#9,0);
idnum=0;
xint=floor(xs);yint=floor(ys);zint=floor(zs);
xo=xs-xint;yo=ys-yint;zo=zs-zint;
gridmult=[(1-xo)*(1-yo)*(1-zo),xo*(1-yo)*(1-zo),(1-xo)*yo*(1-zo),xo*yo*(1-zo),(1-xo)*(1-yo)*zo,xo*(1-yo)*zo,(1-xo)*yo*zo,xo*yo*zo];
for(pz=0,pz<2,pz++,
	for(py=0,py<2,py++,
		for(px=0,px<2,px++,
			curr=i(#1,x+xint+px,y+yint+py,z+zint+pz,0,1);
			pos=find(idlist,curr);
			pos==-1?(idnum+=1;pos=find(idlist,-1);idlist[pos]=curr);
			freqlist[pos]+=gridmult[pz*4+py*2+px];
		);
	);
);
val=vector(#spec,0);
for(n=0,n<idnum,n++,
val+=cubism(idlist[n],x,y,z)*freqlist[n]);
lerp(val,cubism(i(#1,x,y,z,0,1),x,y,z),i(#4))):(cubism(i(#1,x,y,z,0,1),x,y,z))
"
rm[^0]
endl done
fx_jr_rep_cubism_preview:
fx_jr_rep_cubism ${2-20}

I think I’m out of ideas. I don’t want to have to split the entire image up, anti-alias each segment separately and then put it all back together again - the only thing that works for me is the Gaussian blur because the usual anti-aliasing methods either leave gaps at the boundaries or they’re really slow.

I kinda wish Garagecoder came back since he’d be able to sort this entire mess out within an hour.

He has been busy. Sorry I couldn’t help. Tiredness makes my head spin when looking at code. :dizzy_face:

PS I will tell you what I tell everyone. Please show us your intermediary image (where the aliasing problems begin) and associated location in the code. The more context the easier it is to help.