图像处理作业(三)

题目描述:编一个程序实现如下功能:读入指纹图像,进行形态学骨架提取和基于距离变换的骨架提取,并实现剪裁算法。

 

1. 读入一幅指纹图像;

(1)代码

% 读取图片

clc;

clear;

I=imread('figureprint.png');

imshow(I)

(2)效果

图1  读取指纹图像

 

2. 对图像进行二值化(方法自定,可以是阈值法);

(1)代码

%对图像进行二值化(方法自定,可以是阈值法);

thresh = graythresh(I);     %自动确定二值化阈值

I2 = im2bw(I,thresh);       %对图像二值化

imshow(I2)

(2)效果

图2  二值化之后

 

3. 采用形态学骨架提取和距离变换骨架提取两种算法分别提取图像骨架;

(1)形态学骨架提取

①算法描述

形态学骨架提取算法要求给定提取的迭代次数k,在每次子迭代中主要分为3个步骤,第一步利用结构元B对图像进行腐蚀处理;第二步将腐蚀得到的结果与结构元B做开运算;第三步将前两步得到的结果做差得到下式中的 求并集(在代码中利用“逻辑与”运算实现),得到最终的骨架。

 

②编写函数getbone1

function  result= getbone1(img,B,k)

% 形态学提取骨架

% img:二值图像 B : 结构元 k: 迭代次数

% 

M=size(img,1);

N=size(img,2);

SkA=zeros(M,N);

for i = 0:k

   % 1.先腐蚀

   if i==0

       temp1=img;

   else

       SE=logical(i*B);  

       temp1=imerode(logical(temp1),SE);

   end

  

   % 2.得到的结果再与B做开运算

   temp2=imopen(temp1,B);

   % 3. Sk(A)等于前两个结果做差, 再求并集,使用逻辑或实现。

   SkA=(temp1-temp2)|SkA;  

   % 画图部分

   figure;

   subplot(1,3,1), imshow(temp1);

   subplot(1,3,2), imshow(temp2)

   subplot(1,3,3), imshow(SkA)

end

result=SkA

end

③测试效果

测试代码如下:

img=[0,1,0,0,0,0,0;

   0,0,1,1,0,0,0;

    0,0,1,1,0,0,0;

    0,0,1,1,1,0,0;

    0,0,1,1,1,0,0;

    0,1,1,1,1,1,0;

    0,1,1,1,1,1,0;

    0,1,1,1,1,1,0;

    0,1,1,1,1,1,0;

    0,1,1,1,1,1,0;

     0,0,0,0,0,0,0;]

B=[1,1,1;

    1,1,1;

    1,1,1;]

getbone1(img,B,2);

 

 

图1 书上形态学骨架提取方法示意图

 

 

图3  自己编写的算法迭代过程

 

④最终效果

最终效果如图5所示,指纹图像的骨架提取迭代过程如图4所示,可见除了少量噪声值以外,指纹图像的骨架得到了充分细化,提取成功。

图4  指纹图片骨架提取迭代过程(k=2)

 

 

图5 最终效果

 

(2)基于距离的骨架提取

①算法描述

step1:求取二值图像的边界;

step2:对边界二值图像求取距离变换;

step3:求距离变换图中的局部极大值;

step4:落入原二值图像中的局部极大值就是图像的骨架。

②主要函数getbone2编写

 

function result = getbone2(img)

%  GETBONE2 利用距离变换提取骨架

%   img为传入的图像

%     1. 求取二值图像的边界

M=size(img,1);

N=size(img,2);

img_boundary=zeros(M,N);


ed=[-1 -1; 0 -1; 1 -1;  1 0; 1 1; 0 1; -1 1; -1 0];

for i=2:M-1

    for j=2:N-1

        if img(i,j)==1%如果当前像素是前景像素

            for k=1:8

                ii=i+ed(k,1);

                jj=j+ed(k,2);

                if img(ii,jj)==0%当前像素周围如果是背景,边界标记图像相应像素标记

                    img_boundary(ii,jj)=1;

                end

            end

        end

    end 

end


%     2. 对边界二值图像求取距离变换

D = bwdist(img_boundary)


%     3. 求距离变换图中的局部极大值


m =5;                                                     % 方形邻域,即子矩阵范围大小

% 标记

imge_bone=zeros(M,N);   % 最终显示的骨架图

subMatrix = zeros(m,m);                                % 子矩阵,局部最大值为这个矩阵内的最大值

I2=zeropadding(D,m) %由于有方形邻域(类似于卷积核的滑动),故需要将图像进行0填充

I3=zeropadding(img,m) % 将原图像也进行0填充,便于最后的比较这个局部最大值是不是落在图像内部

for x = 1:m:M

    for y = 1:m:N

        subMatrix = I2(x:x+m-1,y:y+m-1); % 从原图中提取子矩阵,即m*m的邻域

        s = sort(subMatrix(:),'descend');     %排序

        [r,c] = find(subMatrix == s(1)); % 取最大值

        r=x+r-1;c=y+c-1; % 在原图像中,对应的行列坐标应当加上当前位置(x,y)   

        if I3(r,c)==1 %判断局部最大值是不是落在图像内部

%     4. 这些局部极大值组成骨架

            imge_bone(r,c)=1; % 骨架图赋值为1

        end

    end 

end

result=imge_bone

end

③用于调用的main函数代码

clear

% 读取图片

clc;

clear;

I=imread('figureprint.png');

thresh = graythresh(I);     %自动确定二值化阈值

I2 = im2bw(I,thresh);       %对图像二值化

imshow(I2)

result=getbone2(I2);

imshow(result)

③指纹图像实现效果

基于距离变换的指纹图像骨架提取效果如图6所示,可见,对比之前的形态学骨架提取,该方法在骨架的连续性上不如之前的好。(图6图像在提取之前经过形态学的去噪处理)

图6 指纹图像距离变换骨架提取

 

 

 

 

4、采用裁剪算法,并分析其效果。

(1)算法流程

Step1:假设是任何具有三个或小于三个像素长度的分支都将被删除。使用一系列仅设计用来检测端点的结构元对输人集合A进行细化可以得到期望的结果。也就是说,令:

式中,{B}表示结构元序列,这个结构元序列由两种不同的结构组成,每种结构对全部8个元素旋转。

而后4个结构元中的“×”表示一个“不必考虑"的条件,在这种意义上,该位置上的像素的值是0还是1无关紧要。如下图所示:

图7  共8个用于细化的结构元

 

结构元B对集合A的细化根据击中或击不中变换来定义。

Step2:连续对步骤1三次,再形成一个包含X1中所有端点的集合。

Step3:下式中H是元素值为1的3×3结构元,并且在每一步之后都要与A求交集。如区域填充和提取连通分量的情况一样,这种有条件的膨胀可以防止在我们关注的区域外产生值为1的元素。

Step4: X3和X1的并集就是我们想要的结果

(2)代码编写

cut函数是自定义的剪裁算法,首先定义了所需的8个结构元,其次再进行细化、击中击不中等步骤,由于matlab自带的击中击不中变换需要传入两个结构元,处理时较为麻烦,因此自定义了hitormiss函数。具体代码如下:

①cut函数

function X4= cut(A)

%CUT 此处显示有关此函数的摘要

%   此处显示详细说明

%8个结构元{B}

A=logical(A);

B1=[2,0,0;

       1,1,0;

       2,0,0];

B2=[2,1,2;

    0,1,0;

    0,0,0];

B3=[0,0,2;

    0,1,1;

    0,0,2];

B4=[0,0,0;

    0,1,0;

    2,1,2];

B5=[1,0,0;

       0,1,0;

      0,0,0];

B6=[0,0,1;

      0,1,0;

      0,0,0];

B7=[0,0,0;

      0,1,0;

       0,0,1];

B8=[0,0,0;

      0,1,0;

      1,0,0];

B={B1,B2,B3,B4,B5,B6,B7,B8};

X1=A;

% 1. 细化 X1=A细化符号{B}

for i=1:3 %连续3次

    for j=1:8

       temp=cell2mat(B(j));

       img_hit=hitormiss(X1,temp);

       X1=X1&(~img_hit);%hitormiss 击中击不中变换(调用自定义hitormiss)

       X1=logical(X1);

    end

end

% imshow(X1)

% 2. 连续式子1三次,得到图中的集合下一步是将字符“复原"成其原来的形状,但要去掉寄生分支。为做到这一点,首先需要求形成一个包含XI中所有端点的集合X2

figure

imshow(img_hit)

figure

imshow(X1)  %X1没问题了

X2=zeros(size(A));

for k=1:8

    temp=cell2mat(B(k));

    img_hit2=hitormiss(X1,temp);

    X2=X2|img_hit2;

end

for n=1:8

    temp=cell2mat(B(n));

    X2=X2|hitormiss(X2,temp);

end

figure

imshow(X2)

% 3. 三次膨胀

X3=X2;

H=[1,1,1;

    1,1,1;

    1,1,1;];

for m=1:3

    X3=imdilate(X3,H)&A;

end

figure

imshow(X3)

% 4 求并集

X4=X1|X3;

End


②自定义hitormiss函数

function imge_hit =hitormiss(img,B)

%   只传入一个B,进行hitormiss判断,此时检测img中有没有与B完全相同的

[M,N]=size(img);

m =size(B,2);                                                 % B的大小,一般是3

% 原结构元中X是用2表示的

flag=false;

[r,c] = find(B == 2);

if  size(r,1)~=0

    flag=true;

end

imge_hit=zeros(M,N);   % 最终显示的骨架图

subMatrix = zeros(m,m);      % 子窗口,用于滑动

I2=zeros(M+2,N+2);

I2(2:M+1,2:N+1)=img;

for x = 2:M-1

    for y =2:N-1

       % subMatrix = I2(x-1:x+1,y-1:y+1); % 从原图中提取子矩阵,即m*m的邻域

       subMatrix = img(x-1:x+1,y-1:y+1);

        if ~flag

            if subMatrix==B %判断提取的矩阵是不是和结构元B一样,一样就击中

                imge_hit(x,y)=1; % 击中的点1

            end

        else % flag 为true ,即有X的情况

            [r0,c0] = find(B == 0); %r[2,3] c[2,2]

            key=true;

            for i =1:size(r0,1) % size(r,1)=2

                if subMatrix(r0(i),c0(i))~=0 %不等于1

                    key=false;

                end

            end

            [r1,c1] = find(B == 1); %r[2,3] c[2,2]

            for i =1:size(r1,1) % size(r,1)=2

                if subMatrix(r1(i),c1(i))~=1 %不等于1

                    key=false;

                end

            end

            if key

                 imge_hit(x,y)=1; % 击中的点1

            end

        end

    end

end

imge_hit=logical(imge_hit);

end

 

(3)测试效果

①测试代码

%测试

%裁剪

clear

% 读取图片

clc;

img=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;

    0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0;

    0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0;

    0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0;

    0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0;

    0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0;

    0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0;

    0,0,0,1,0,0,0,0,0,1,0,1,0,0,0,0;

    0,0,1,0,0,0,0,0,0,1,0,1,0,0,0,0;

    0,0,1,0,0,0,0,0,1,0,0,1,0,0,1,0;

    0,0,0,1,1,1,1,1,0,0,0,0,1,1,0,0;

    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;]

imshow(img)

result=cut(img);

imshow(result)

②测试代码的运行过程

     

(a)原图像 (b)去掉寄生分支后的X1  (c)X1的端点

 

   

(d)由端点开始膨胀  (e)最终效果

图8 测试过程的运行效果

 

与书上结果对比

图9 书上裁剪算法的运行效果

 

由图8和图9的结果可以看出,自定义的裁剪算法与书上效果基本一致。

③指纹图像运行效果

  

图10 指纹图像裁剪算法的运行效果

 

由图10可以看出,指纹图像的一些边缘部分已被裁剪掉。

参考

主要参考书籍:冈萨雷斯图像处理第4版本

未经允许禁止转载~

 

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值