最近任务比较重,要多线程实现400张掌纹掌静脉图片的裁剪,要求只保留中心部分,如图所示这是相机拍摄的掌纹图片我要提取掌纹中心部分区域,其他其余要剔除,这是目标图像,如图所示
注意哈,这个图像是上面图像经过旋转裁剪得来的哈。这就是我们所需要实现的效果,接下来我们用matlab代码实现,这是我们实验室祖传的代码,部分算法如下所示
function [newzg1y, newzg1x, d0, shuchusrc,angle]=ROI(InBw1,InImg)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
[x,y]=size(InBw1);
s=[];
[a, LabMtx]=bwboundaries(InBw1); %寻找连通域的函数 L是一个标记矩阵
for k=1:length(a)
sz=size(a{k});
s=[s sz(1)];
end %取了a中的个数
[M, Ind]=max(s); %Ind为索引值
boundary1=a{Ind}; %获取了手掌的边界,X,Y 排序是从9点钟方向上的一点顺时针开始沿着边界走
PalmBoundaryImg=zeros(x, y);%开始描边
for z=1:size(boundary1, 1)
PalmBoundaryImg(boundary1(z,1), boundary1(z,2))=1;
end
%figure(2),imshow(PalmBoundaryImg),title('边界图');%边界图
% % % % hold on;
% % % % plot(1012, 145,'r*');
% % % % hold off;
%%%%%%%%%% getting centroid of palm and displaying it 获得掌心的质心并显示它
cent=regionprops(LabMtx,'centroid'); %标注矩阵L中每一个标注区域的一系列属性。质心 返回值STATS是一个 长度为max(L(:))的结构数组,结构数组的相应域定义了每一个区域相应属性下的度量
centcor=[cent(Ind).Centroid];
%%%%%%%%%%找出质心画一条竖线与掌轮廓有两个交点选大的,对轮廓矩阵转移 %%%%%%%%%%%%
cenY=round(centcor(1));
cenX=round(centcor(2));
% % % % hold on;
% % % % plot(cenY, cenX,'ro');
% % % % hold off;
[xInd]=find(boundary1(:,2)==cenY); %第二例取出判断 相当于Y的值等于944的 x1 x2
leftIndX=max(xInd); %leftIndY的数值代表boundary1中的排列数 相当于确定了手掌的位置
boundary2=circshift(boundary1,max(size(boundary1(:,1))-leftIndX+1));%矩阵的循环移动boundary2 将边界1逆时针旋转 让起始点逆时针变动到 原来手掌的位置
PalmBoundaryImg2=zeros(x, y);%开始描边
for z2=1:size(boundary2, 1)
PalmBoundaryImg2(boundary2(z2,1), boundary2(z2,2))=1;
end
% figure(3),imshow(PalmBoundaryImg2); %起始点在6点钟手掌的位置,逆时针进行排序
% % % % hold on;
% % % % plot(516, 247,'r*');
% % % % hold off;
L=length(boundary2);
distance=sqrt( sum( (boundary2-repmat(boundary2(1,:),L,1) ).^2,2) );%应该是求到手掌位置的距离 边界上的点
%%%%%%%%%%%%%%%%%%%%% Finding finger extremeties 找到手指四肢%%%%%%%%%%%%%%%%%%%%%%%%%%%
W1=round(L/23);%23
W2=round(L/46);%46
tips=[];%代表指尖的标号
valleys=[];%代表指谷的标号
k=0;
tip=1;
valley=1;
%%%%%%%%%%%%%%% tips and valleys are found as the maxima and minima on the
%%%%%%%%%%%%%%% windoweddistance signal 在窗口距离信号上找到尖端和波谷作为最大值和最小值
%figure(3),plot(distance(:,1),'r*'),title('轮廓线各点距离手掌底部中心距离');%看出距离变化局部极小值代表手指谷点
while k<L-W1
k=k+1;
window1=distance(k:k+(W1-1));
[Min,MinIndex1]=min(window1);
[Max,MaxIndex1]=max(window1);
if MaxIndex1~=1 & MaxIndex1~=W1
if MaxIndex1+k-1+W2<=L & MaxIndex1+k-1-W2>=1
window2=distance(MaxIndex1+k-1-W2:MaxIndex1+k-1+W2);
elseif MaxIndex1+k-1-W2<1
window2=distance(1:MaxIndex1+k-1+W2);
else
window2=distance(MaxIndex1+k-1-W2:L);
end
[Max,MaxIndex2]=max(window2);
if MaxIndex2==W2+1
tip=MaxIndex1+k-1;
tips=[tips;tip];%tip列向合并给tips
end
end
%%%%%%%%{1,88}为一段,找凹点,最小值点不在两端,记下最小值的索引号
if MinIndex1~=1 & MinIndex1~=W1%最小值点不在两端
if MinIndex1+k-1+W2<=L & MinIndex1+k-1-W2>=1%判断是否超出边界
window2=distance(MinIndex1+k-1-W2:MinIndex1+k-1+W2);%再重新从MinIndex1+k-1-W2(以最小值的索引点两边平分44为区间)
elseif MinIndex1+k-1-W2<1
window2=distance(1:MinIndex1+k-1+W2);
else
window2=distance(MinIndex1+k-1-W2:L);
end
[Min,MinIndex2]=min(window2);%把以最低点为中心重新分好的区间最小值给Min,索引号给MinIndex2一般为45
if MinIndex2==W2+1%45=44+1
valley=MinIndex1+k-1;
valleys=[valleys;valley];%valley列向合并给valleys
end
end
k=max([tip valley k]);
end
tips=[distance(tips) tips];%把索引号的距离与tips行向合并 先距离后索引号 距离是到手掌6点钟原点的直线距离
tips=flipud(sortrows(tips,1));%flipud(X)实现了矩阵的翻转 从大到小
if length(tips) < 3
shuchu=0;
newzg1y=0;
newzg1x=0;
d0=0;
shuchusrc=0;
else
shuchu=1;
tips=sort(tips(1:4,2));%根据距离找到四根手指,去掉拇指 根据距离去掉最小的拇指
temp=zeros(4,1);
valleys=flipud(sortrows(valleys,1));
for v=1:3%把valleys中数值从小到大插入到tips中
kk=find(valleys>tips(v) & valleys<tips(v+1));
if length(kk)<1
shuchu=0;
angle=0;
break;
else
temp(v)=valleys(kk(1));
end
end
if shuchu==0
newzg1y=0;
newzg1x=0;
d0=0;
shuchusrc=0;
else
valleys=temp;
%imtool(PalmBoundaryImg)
%hold(imgca,'on')
zg=boundary2(valleys(1:3),:);%代表手指谷的位置 分别为从左到右 XY
zj=boundary2(tips(1:4),:);%代表手指尖的位置 分别为从左到右
%
%---------------------------------------------------------------------------------------------------
% figure(4),imshow(PalmBoundaryImg2),title('*代表指谷点、o代表指尖点'); %起始点在6点钟手掌的位置,逆时针进行排序
% figure(6),imshow(InImg),title('*代表指谷点、o代表指尖点'); %起始点在6点钟手掌的位置,逆时针进行排序
hold on; plot( zg(:,2),zg(:,1),'r*');
hold off;
% hold on;
% plot( zj(:,2),zj(:,1),'ro');
% hold off;
zg1X=boundary2(valleys(1),2);
zg1Y=boundary2(valleys(1),1);
zg2X=boundary2(valleys(2),2);
zg2Y=boundary2(valleys(2),1);
zg3X=boundary2(valleys(3),2);
zg3Y=boundary2(valleys(3),1);
% hold(imgca,'on') %@@@@@@@@@@@@@@@@@@@@@@@@@@
% plot(imgca,[zg1X zg3X],[zg1Y zg3Y]);
% hold(imgca,'off');%@@@@@@@@@@@@@@@@@@@@@@@
zhijiaoX=zg3X;
zhijiaoY=zg1Y;% 代表三角形的直角顶点
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
angle=atan((zg3Y-zhijiaoY)/(zhijiaoX-zg1X))*(180/pi); %两谷点角度
TT=angle;
%@@@@@@@@@@@@@@@@@@@@
% hold(imgca,'on')
% t=180;
% nxx1=(xx1*cosd(t))-(yy1*sind(t))-320*cosd(t)+240*sind(t)+320;
% nyy1=(xx1*sind(t))+(yy1*cosd(t))-320*sind(t)-240*cosd(t)+240;
% plot(imgca,nxx1,nyy1,'w+');
% hold(imgca,'off');
%@@@@@@@@@@@@@@@@@
RotdImg=imrotate(InImg,angle,'nearest','crop'); %旋转,crop输出图像和原来一样大小
figure(5),imshow(RotdImg),title('旋转后的掌纹图像');
t=-TT;%旋转角度
zg1tomidlength=sqrt((0.5*y-zg(1,2))^2+(0.5*x-zg(1,1))^2);%求左边第一个手指谷点到 图形旋转中心的距离 旋转中心为图像中心
zg1tomidangle=atan( (0.5*x -(zg(1,1))) / (0.5*y-zg(1,2)) )*(180/pi); %求左边第一个手指谷点到 中心点的一个角度 也可以理解为初始点的角度
newzg1tomidangle=zg1tomidangle + t;%角度相加 因为要旋转
newzg1y=0.5*y - zg1tomidlength * cosd(newzg1tomidangle);
newzg1x=0.5*x - zg1tomidlength * sind(newzg1tomidangle);%计算旋转后的左边第一个手指谷的点的新坐标
newzg1y=round(newzg1y);
newzg1x=round(newzg1x);
d0=sqrt((zg1X-zg3X)^2+(zg1Y-zg3Y)^2);%求两点距离 求一条斜线的长度 左边第一个手指谷点到第三个谷点的直线距离 横向ROI长度
hold on;
plot( newzg1y,newzg1x,'ro');
hold off;
hold on;
plot( newzg1y+d0,newzg1x,'ro');
hold off;
im1=RotdImg;
palm1=imcrop(im1,[newzg1y newzg1x 640 480]);%剪切函数以nxx1 (nyy1+10)为图像左上角d0为宽度d1为高度[xmin ymin width height] d0是找的两个手指谷的间隙
k=im1;
shuchusrc=palm1;%ROI原始
[m,n]=size(k);
%%%%%%%%%%%%%%%%%%%%%%%%%%灰度归一化
p=max(max(k(:,:)))-min(min(k(:,:)));
y=double(256/double(p));
k(:,:)=double((double(y)*double((k(:,:)-min(min(k(:,:)))))));
% shuchu=k;%归一化后的ROI
end
end
%imtool(k);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
由于我c++上要实现多线程裁剪,直接打包成dll即可,十分方便!!!!,需要源码的可以联系我qq:1449917271 ,微信:liuyoudyping。
点击此处登录后即可评论