210 likes | 224 Views
Learn how to vectorize bitmaps based on the LSQ method, including mathematical background, line construction, perimeter extraction, and point ordering. This document provides a comprehensive guide on bitmap vectorization techniques.
E N D
Vectorization of bitmaps based on the LSQ method Doc. RNDr. Stanislav Bartoň, CSc. barton@mendelu.cz
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 Digital photo, main parameters
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 Mathematical background
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 The best lines and construction of the polygon
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 Perimeter’s point extraction > FN := "Carot2.jpg";W1 := ImageTools[Read](FN): > Rd := ImageTools[Width](W1);Cd := ImageTools[Height](W1); > o:=5; A3:=1/o^2*Matrix(o,o,1); > W2:=ToGrayscale(W1): > Laplace:=Matrix([[1,4,1],[4,-20,4],[1,4,1]]): > W1:=Array(map(u->`if`(u>1./o^2,1.0,0.0),Convolution(W2,A3)),datatype=float[8]): > W2:=Array(map(u->`if`(u>(1.-1./o^2),1.0,0.0),Convolution(W1,A3)),datatype=float[8]): > W1:=Clip(Convolution(W2,Laplace)): > ps:=map(u->[lhs(u)],[op(3,W1)[]]):ps:=map(u->[u[2],Cd+1-u[1]],ps): >plot(ps,scaling=constrained);
Vectorization of bitmaps based on the LSQ methodPANM165 Horní Maxov, 7.6.2010 Perimeter’s point ordering >Ym:=min(sort(map(u->u[2],ps))[]);Xm:=sort(map(u->`if`(u[2]=Ym,u[1],NULL),ps)); > PS:=[[Xm[2],Ym]]; >Dir:=[[1,0],[0,1],[-1,0],[0,-1]]; >ps:=subs(PS[1]=NULL,PS[-1]=NULL,ps): >lr:=map(u->select(has,ps,[PS[1]+u])[],Dir)[];l:=lr[1]; r:=lr[2];PS:=[l,PS[],r]; > ps:=subs(PS[1]=NULL,PS[-1]=NULL,ps): > while (l<>NULL and r<>NULL) do; l:=map(u->select(has,ps,[PS[1]+u])[],Dir)[]; r:=map(u->select(has,ps,[PS[-1]+u])[],Dir)[]; PS:=[l,PS[],r];ps:=subs(PS[1]=NULL,PS[-1]=NULL,ps): > end do: > Nu:=nops(PS)-1; > {seq(D2(PS[i],PS[i+1]),i=1..Nu)}; > plot(PS,scaling=constrained);
> i:='i': > d:=1.; Dist:=0; LPT1:=[]: LPT2:=[]:Lambda:=[]; > GO:=true; > N1:=1; s:=0; > while GO do: > N2:=N1+1; Dist:=0; s:=s+1: l:=[]: > while Dist<d and GO do; Cf0:=Cf: Sf0:=Sf; > Qx:=-S4/(-N2+N1-1.); Qy:=-1/(-N2+N1-1.)*S1; > S6:=-2*S1*S4-2*S3*N1+2*S3+2*S3*N2; S7:=2*S2*N2-2*S1^2+2*S2+2*S5*N1-2*S5+2*S4^2-2*S5*N2-2*S2*N1; S8:=2*S3*N1-2*S3+2*S1*S4-2*S3*N2; > if S8<>0 then Cf:=2.^(1/2)*S8/(2.*S8^2+S7^2+S7*(S7^2-4.*S8*S6)^(1/2)-2.*S8*S6)^(1/2); Sf:=-1/2*(S7+(S7^2-4.*S8*S6)^(1/2))*2.^(1/2)/(2.*S8^2+S7^2+S7*(S7^2-4.*S8*S6)^(1/2)-2.*S8*S6)^(1/2); df:=map(u->d0(u),PS[N1..N2]); Dist:=max(df[]); else Cf:=1; Sf:=0; df1:=map(u->d0(u),PS[N1..N2]); Cf:=0; Sf:=1; df2:=map(u->d0(u),PS[N1..N2]); Dist1:=max(df1[]); Dist2:=max(df2[]); if Dist1<Dist2 then Dist:=Dist1; Cf:=1: Sf:=0; else Dist:=Dist2: Cf:=0: Sf:=1: end if: end if; N2:=N2+1; if N2>Nu then GO:=false; end if; end do: Sf:=Sf0; Cf:=Cf0; if GO then N2:=N2-2; print(step=s,'N1'=N1,'N2'=N2,Delta=N2-N1); end if: > LPT1:=[LPT1[],PL(PS[N1])]; LPT2:=[LPT2[],PL(PS[N2])]; Lambda:=[Lambda[],[seq(PS[u],u=N1..N2-1)]]; > N1:=N2; > end do: Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 The best line segments estimation > i:='i':d:=1.; Dist:=0; LPT1:=[]: LPT2:=[]:Lambda:=[]; GO:=true;N1:=1; s:=0; > while GO do: N2:=N1+1; Dist:=0; s:=s+1: l:=[]: while Dist<d and GO do; Cf0:=Cf: Sf0:=Sf;Qx:=-S4/(-N2+N1-1.); Qy:=-1/(-N2+N1-1.)*S1; S6:=-2*S1*S4-2*S3*N1+2*S3+2*S3*N2; S8:=2*S3*N1-2*S3+2*S1*S4-2*S3*N2; S7:=2*S2*N2-2*S1^2+2*S2+2*S5*N1-2*S5+2*S4^2-2*S5*N2-2*S2*N1; if S8<>0 then Cf:=2.^(1/2)*S8/(2.*S8^2+S7^2+S7*(S7^2-4.*S8*S6)^(1/2)-2.*S8*S6)^(1/2); Sf:=-1/2*(S7+(S7^2-4.*S8*S6)^(1/2))*2.^(1/2)/(2.*S8^2+S7^2+S7*(S7^2-4.*S8*S6)^(1/2)-2.*S8*S6)^(1/2); df:=map(u->d0(u),PS[N1..N2]);Dist:=max(df[]); else Cf:=1; Sf:=0;df1:=map(u->d0(u),PS[N1..N2]);Cf:=0; Sf:=1;df2:=map(u->d0(u),PS[N1..N2]); Dist1:=max(df1[]); Dist2:=max(df2[]); if Dist1<Dist2 then Dist:=Dist1; Cf:=1: Sf:=0; else Dist:=Dist2: Cf:=0: Sf:=1: end if: end if; N2:=N2+1; if N2>Nu then GO:=false; end if; end do: Sf:=Sf0; Cf:=Cf0; if GO thenN2:=N2-2; print(step=s,'N1'=N1,'N2'=N2,Delta=N2-N1);end if: LPT1:=[LPT1[],PL(PS[N1])];LPT2:=[LPT2[],PL(PS[N2])]; Lambda:=[Lambda[],[seq(PS[u],u=N1..N2-1)]];N1:=N2; > end do:
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 Generation of the polygon and visualization > SP:=[0.5*(LPT1[1]+LPT2[-1]),seq(0.5*(LPT1[i+1]+LPT2[i]),i=1..n-1),0.5*(LPT1[1]+LPT2[n])]: > for i from 1 to n do: L[i]:=Lambda[i]: p[i]:=SP[i]: end do: L[n+1]:=Lambda[1]: L[0]:=Lambda[-1]: > p[n+1]:=SP[-1]: p[n+2]:=SP[2]: p[0]:=p[n]: > symb_opt:=symbol=box,symbolsize=15,thickness=1; > nu:=35: > G1:=plot([[LPT1[nu-1],LPT2[nu-1]],L[nu-1]],style=[line,point],symb_opt,color=blue): G2:=plot([[LPT1[nu],LPT2[nu]],L[nu]],style=[line,point],symb_opt,color=red): G3:=plot([[LPT1[nu+1],LPT2[nu+1]],L[nu+1]],style=[line,point],symb_opt,color=blue): G4:=plot([L[nu-1][],L[nu][],L[nu+1][]],color=black): G5:=plot([p[nu-1],p[nu],p[nu+1],p[nu+2]],color=black,thickness=2): > display({G1,G2,G3,G4,G5});
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 Unification of the parallel line segments > Colin:=[seq(`if`(Colin[i]<0.5,i,NULL),i=1..n)]: > while Colin<>[] do; k:=Colin[-1]: Colin:=subs(k=NULL,Colin); if k<>1 then L[k-1]:=[L[k-1][],L[k][]]; for j from k to n do: L[j]:=L[j+1]; p[j]:=p[j+1]: end do: p[n+1]:=p[n+2]: else L[0]:=[L[n][],L[1][]]; for j from 1 to n-2 do: L[j]:=L[j+1]: p[j]:=p[j+1]: end do: p[n]:=p[1]: p[n+1]:=p[2]: p[0]:=p[n-1]: L[n-1]:=L[0]: end if: n:=n-1; end do:
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 Visualization of the quality of the vectorization > D_All:=[seq(map(u->sqrt(S(u,p[i],p[i+1])),L[i]),i=1..n)]: > L_All:=map(u->u[],D_All): > d:=sum(L_All['i'],'i'=1..Nu-1)/(Nu-1); > sd:=sqrt(sum((L_All['i']-d)^2,'i'=1..Nu-1)/(Nu-1)); > Max:=max(L_All[]); > plot([seq([i,L_All[i]],i=1..Nu-1)],numpoints=2000);
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 Data saving and visualization of the result > plot([seq([p[i],p[i+1]],i=1..n)],scaling=constrained); > Lambda:=[seq(L[i],i=1..n)]: > SP:=[seq(p[i],i=1..n+1)]: > save PS, SP, Lambda, “Carot_LPS.sav";
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 “Data shaking” using Gauss-Newton method. Preparation of the Jacobi matrix
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 Example of the Jacobi matrix for the “Global shaking”
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 “Local shaking” – Example of the Jacobi matrix
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 “Local shaking” – Visualization Iteration_step:=proc() local JM, rest, H, eps, LM, h; global p; JM:=Matrix([map(u->ColL(u,p[N-1],p[N]),L[N-1])[], map(u->ColN(u,p[N],p[N+1]),L[N])[],map(u->ColR(u,p[N+1],p[N+2]),L[N+1])[]]): rest:=Vector([map(u->rf(u,p[N-1],p[N]),L[N-1])[], map(u->rf(u,p[N],p[N+1]),L[N])[],map(u->rf(u,p[N+1],p[N+2]),L[N+1])[]]): H:=LeastSquares(JM,rest): eps:=Norm(H,2);LM:=sqrt(4+eps^2);h:=1/LM*convert(H,list); p[N]:=p[N]-h[1..2]; p[N+1]:=p[N+1]-h[3..4]; end proc;
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 Visualization of the final result
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 Visualization of the quality of the vectorization
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 Visualization of the quality of the vectorization
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 Visualization of the quality of the vectorization Displacement 20× enlarged
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 Visualization of the quality of the vectorization Displacement 20× enlarged
Vectorization of bitmaps based on the LSQ methodPANM15, Horní Maxov, 7.6.2010 • Conclusions: • Data reduction: • Accuracy: • Quadratic displacement • Max. displacement • Sharpness of the original digital photo = ±1 pixel Result: Usefull tool Thank you for your patience!