The following code gives an overview (Ask for full source code of application) to compute static and dynamic features of scanned handwritten image. The dynamic features compute drawing order of a handwritten image as shown in following figure. The code is written in Matlab.
The following function feature_extraction calls static and dynamic features and perform necessary preprocessing.
function v = feature_extraction(im)
v=[];
im=imresize(im,[100 100]); im=im2bw(im);
v=[v more_features(im)]; %%% static features computation, function written below
im2=im;
%%%% for thin image
fix_no=63; cch_length=12; path=[]; list=[];
im=bwmorph(im,'thin',Inf); im=bwmorph(im,'spur',3);
im1=regionprops(im,'PixelList','Extrema','Area');
for i=1:length(im1)
list1=im1(i).PixelList;
P1=ceil(im1(i).Extrema(1,:)); %P=P1;
P=one_ngh(list1,P1); %find one-ngh point close to (0,0)
x=P(1,1); y=P(1,2); path=[x y];
path=tr_list(list1,x,y,path); %traverse list as recover drawing order of skeleton image, function given below
list=[list; path];
end
[m n]=size(list);list=resample(list,fix_no,m); %to resample points
list=list(3:end,:);
ccpath=list_path(list,cch_length); v=[v ccpath];
%%%%%canny chain code
im=im2; fix_no=133; cch_length=12; path=[]; list=[];
im=edge(im,'canny');
im1=regionprops(im,'PixelList','Extrema','Area');
for i=1:length(im1)
list1=im1(i).PixelList;
P1=ceil(im1(i).Extrema(1,:)); %P=P1;
P=one_ngh(list1,P1); %find one-ngh point close to (0,0)
x=P(1,1); y=P(1,2); path=[x y];
path=tr_list(list1,x,y,path); %traverse list as recover drawing order of boundary pixels image, function given below
list=[list; path];
end
[m n]=size(list); list=resample(list,fix_no,m); %to resample points
list=list(3:end,:); list=[list;list(1,:)];
ccpath=list_path(list,cch_length); v=[v ccpath];
end
Static Features (compute pixels density in squares, horizontal, vertical and diagonal styles)
function v = more_features(im)
im=im_crop(im);
im=imresize(im,[100 100]);
[m n]=size(im);
t=10;
k=m/t; part=m/k; im2=[]; v=[]; r=1; c=1;
for i=1:part
for j=1:part
im2=im(r:(r+k-1),c:(c+k-1));
v=[v nnz(im2)];
c=c+k;
end
r=r+k; c=1;
end
ub=100; f=9;
for i=1:10:ub
v=[v nnz(im(i:i+9,:))];
v=[v nnz(im(:,i:i+9))];
end
%}
ub=100; f=9; v=[];
for i=1:10:ub
s=0; m=[];
for j=i:1:i+f
s=s+nnz(diag(im,j));
end
v=[v s];
end
for i=-1:-10:-ub
s=0; m=[];
for j=-i:-1:-(i+f)
s=s+nnz(diag(im,j));
end
v=[v s];
end
im=fliplr(im); [m n]=size(im);
for i=1:10:ub
s=0; m=[];
for j=i:1:i+f
s=s+nnz(diag(im,j));
end
v=[v s];
end
for i=-1:-10:-ub
s=0; m=[];
for j=-i:-1:-(i+f)
s=s+nnz(diag(im,j));
end
v=[v s];
end
end
Dynamic Features (Recover drawing order through skeleton and boundary pixels of image, its a recursive program)
function path=tr_list(list,x,y,path)
[m n]=size(path); [m1 n1]=size(list);
if m>=m1
return;
end
ngh=tr_ngh(x,y,path,list); [m1 n1]=size(path); [m2 n2]=size(ngh);
%
if m1>1 && m2>1
pp2(1,1)=x; pp2(1,2)=y; pp1(1,1)=path(end-1,1); pp1(1,2)=path(end-1,2);
ngh=tr_prev_list(ngh,pp1,pp2);
end
%
[m n]=size(ngh);
for i=1:m
P2=ngh(i,:);
checkp=is_member(P2,path);
if checkp==0
path=[path;P2];
end
x=P2(1,1); y=P2(1,2);
path=tr_list(list,x,y,path);
end
end