一、简介
本文主要介绍一种基于巴特沃斯滤波器的图像边缘粗糙度的刻画方法,可用于计算一个连通图,或者一条曲线的边缘粗糙度指标。(原理简单,但版权所有,不得随意抄袭,发论文)
二、问题引入
问题:使用自己的方法求如下四张图片的边缘粗糙度?
三、Matlab代码
原理分析:
步骤一、导入原图
步骤二、图像二值化
步骤三、求最大连通图
步骤四、进行巴特沃斯滤波
步骤五、求原图像边缘长度
步骤六、求滤掉的面积
步骤七、相除得到单位长度滤掉的面积
%用单位长度上被平滑掉的面积刻画闭合图形的边缘粗糙度(尽量让图形布满视野)
%对于非连通图像,让图像的两端与图像的左右边界重合
clear;clc;
%原图处理
ImageSource = imread('E:\software\MatLab2020b\myWorkPlace\linex.png');%原图
Image_Binary = im2bw(ImageSource,graythresh(ImageSource));%二值图
Image_Max = BigestConnectedDomain(Image_Binary);%最大连通图
[height,width] = size(Image_Binary);%图片的尺寸
[ImageSourceEdge,count_o,border_o] = ImageExcision(ImageSource,Image_Max,1);
%布特沃兹滤波图
n = 3;
d = 0.025*height;
im_out_b = ButterworthFilter(Image_Max,'l',n,d);
im_out_bw = im2bw(im_out_b,graythresh(im_out_b));
[ImageButterEdge,count_n,border_n] = ImageExcision(ImageSource,im_out_bw,1);
%显示图形
[n2,m2] = size(border_n);
ImageSourceMax = zeros(height,width,3,'uint8');
ImageButterMax = zeros(height,width,3,'uint8');
ImageSourceMax(:,:,1) = Image_Max.*255;
ImageButterMax(:,:,2) = im_out_bw.*255;
ImageAdd = ImageButterMax+ImageSourceMax;
figure(1);
subplot(2,2,1);imshow(ImageSource);title('原图');
subplot(2,2,2);imshow(Image_Binary);title('二值图');
subplot(2,2,3);imshow(Image_Max);title('最大连通图');
subplot(2,2,4);imshow(ImageSourceEdge);title('原始边缘标定');
figure(2);
subplot(2,2,1);imshow(im_out_b);title('巴特沃兹滤波');
subplot(2,2,2);imshow(ImageSourceMax);title('巴特沃兹滤波二值图');
subplot(2,2,3);imshow(ImageButterMax);title('滤波边缘标定');
subplot(2,2,4);imshow(ImageSourceMax+ImageButterMax);title('滤波前后叠加');
%求粗糙度
sumx = sum(sum(ImageAdd(:,:,1)==255&ImageAdd(:,:,2)==0&ImageAdd(:,:,3)==0))+sum(sum(ImageAdd(:,:,1)==0&ImageAdd(:,:,2)==255&ImageAdd(:,:,3)==0));
ronghness = sumx/n2;
fprintf("总面积 = %d,单位长度面积 = %f\n",sumx,ronghness);
%函数1、求最大连通图
function [output_image,area] = BigestConnectedDomain(image)
%本函数求二值化的图像的最大连通域
input_image = imfill(image,'hole');%填充连通域内孤立的孔洞
%获取连通域信息
[L,num] = bwlabel(input_image,4);
x = zeros(1,num);
for i = 1:num
x(i) = sum(sum(L == i));
end
%定位最大单连通域的位置
[~,n] = max(x);
%输出图像
output_image = (L == n);
%输出最大单连通域的面积
area = sum(sum(output_image));
end
%函数2、巴特沃斯滤波器
function [ output_image ] = ButterworthFilter( image ,mold,n,d)
%本函数为巴特沃斯滤波器,用于对图像进行巴特沃斯滤波
% image参数为读入的图像矩阵;
% mold参数为巴特沃斯滤波器的工作模式,有‘l’与‘h’可选,l为低通滤波,h为高通滤波;
% n参数为巴特沃斯滤波器的阶数;
% d参数为巴特沃斯滤波器的截止频率。
hight=size(image,1);
wide=size(image,2);
fftim = fftshift(fft2(double(image)));
[x,y]=meshgrid(floor(-wide/2):floor(wide/2)-1,floor(-hight/2):floor(hight/2)-1);
B = sqrt(2) - 1; %定义巴特沃斯滤波器中的参数B
D = sqrt(x.^2 + y.^2); %计算各点到图像中心的距离
%定义滤波器函数
if mold == 'l'
hhp = 1 ./ (1 + B * ((D ./ d).^(2 * n)));
elseif mold == 'h'
hhp = 1 ./ (1 + B * ((d ./ D).^(2 * n)));
end
%将滤波器的矩阵维度与图像的矩阵维度匹配
[~,~,page]= size(image);
hhp1 = hhp;
i = 1;
while i < page
hhp1 = cat(3,hhp1,hhp);
i = i + 1;
end
hhp = hhp1;
%滤波
out_spec_centre = fftim .* hhp;
%象限转换
out_spec = ifftshift(out_spec_centre);
%反变换并取实部
out = real(ifft2(out_spec));
%归一化
out = (out - min(out(:))) / (max(out(:)) - min(out(:)));
%反归一化图像
output_image = uint8(255*out);
end
%函数3、output_image:原图标记边缘,border_length:边缘点数,border_location:边缘点坐标
function [output_image,border_length,border_location] = ImageExcision(original_image,bw_image,color_type)
im = original_image;
[row,col] = size(bw_image);%row:高度,col宽度
%-------------------------------------------------------------------------%
count = 0; %边界点的个数
b_loc = []; %所有边界点的坐标
for j = 2:row-1 %内部像素边界判断
for k = 2:col-1
if(bw_image(j,k)==1)
if (bw_image(j-1,k)== 0 || bw_image(j+1,k)== 0 || bw_image(j,k-1)== 0 ||bw_image(j,k+1)== 0)
if(color_type == 1)
im(j,k,1) = 255;im(j,k,2) = 0;im(j,k,3) = 0;
else
im(j,k,1) = 0;im(j,k,2) = 0;im(j,k,3) = 255;
end
b_loc = [b_loc;[j k]];
count = count +1;
end
end
end
end
%-------------------------------------------------------------------------%
%图像边缘像素边界判断(四个角上的像素点除外)
%第一行与最后一行像素
for i = 2:col-1
if(bw_image(1,i) == 1)
if(bw_image(1,i+1) == 0 || bw_image(1,i-1) == 0 || bw_image(2,i) == 0)
if(color_type == 1)
im(1,i,1) = 255;im(1,i,2) = 0;im(1,i,3) = 0;
else
im(1,i,1) = 0;im(1,i,2) = 0;im(1,i,3) = 255;
end
b_loc = [b_loc;[1 i]];
count = count +1;
end
end
if(bw_image(row,i) == 1)
if(bw_image(row,i+1) == 0 || bw_image(row,i-1) == 0 || bw_image(row-1,i) == 0)
if(color_type == 1)
im(row,i,1) = 255;im(row,i,2) = 0;im(row,i,3) = 0;
else
im(row,i,1) = 0;im(row,i,2) = 0;im(row,i,3) = 255;
end
b_loc = [b_loc;[row i]];
count = count +1;
end
end
end
%第一列与最后一列像素
for i = 2:row-1
if(bw_image(i,1) == 1)
if (bw_image(i+1,1) == 0 || bw_image(i-1,1) == 0 || bw_image(i,2) == 0)
if(color_type == 1)
im(i,1,1) = 255;im(i,1,2) = 0;im(i,1,3) = 0;
else
im(i,1,1) = 0;im(i,1,2) = 0;im(i,1,3) = 255;
end
b_loc = [b_loc;[i 1]];
count = count +1;
end
end
if(bw_image(i,col) == 1)
if (bw_image(i+1,col) == 0 || bw_image(i-1,col) == 0 || bw_image(i,col-1) == 0)
if(color_type == 1)
im(i,col,1) = 255;im(i,col,2) = 0;im(i,col,3) = 0;
else
im(i,col,1) = 0;im(i,col,2) = 0;im(i,col,3) = 255;
end
b_loc = [b_loc;[i col]];
count = count +1;
end
end
end
%-------------------------------------------------------------------------%
%四个角上的像素点判断
if(bw_image(1,1)==1)%左上点
if (bw_image(1,2) == 0 || bw_image(2,1) == 0)
im(i,col,1) = 255;im(i,col,2) = 0;im(i,col,3) = 0;
if(color_type == 1)
im(i,col,1) = 255;im(i,col,2) = 0;im(i,col,3) = 0;
else
im(i,col,1) = 0;im(i,col,2) = 0;im(i,col,3) = 255;
end
b_loc = [b_loc;[1 1]];
count = count +1;
end
end
if(bw_image(row,1)==1)%左下点
if(bw_image(row,2) == 0 || bw_image(row-1,1) == 0)
if(color_type == 1)
im(i,col,1) = 255;im(i,col,2) = 0;im(i,col,3) = 0;
else
im(i,col,1) = 0;im(i,col,2) = 0;im(i,col,3) = 255;
end
b_loc = [b_loc;[row 1]];
count = count +1;
end
end
if(bw_image(1,col) == 1)%右上点
if(bw_image(1,col-1) == 0 || bw_image(2,col) == 0)
if(color_type == 1)
im(i,col,1) = 255;im(i,col,2) = 0;im(i,col,3) = 0;
else
im(i,col,1) = 0;im(i,col,2) = 0;im(i,col,3) = 255;
end
b_loc = [b_loc;[1 col]];
count = count +1;
end
end
if(bw_image(row,col)==1) %右下点
if(bw_image(row,col-1) == 0 || bw_image(row-1,col) == 0)
if(color_type == 1)
im(i,col,1) = 255;im(i,col,2) = 0;im(i,col,3) = 0;
else
im(i,col,1) = 0;im(i,col,2) = 0;im(i,col,3) = 255;
end
b_loc = [b_loc;[row col]];
count = count +1;
end
end
output_image = im;
border_length = count/2;
border_location = b_loc; %所有边界点坐标
end
function ret=fun_edgex(Input_image) %zhoujinhao add (提取图像的边缘)
ret_img = Input_image;
[height,width]=size(Input_image);
for i_x = 1:(height)
for j_x = 1:(width) %扫描每一个像素
if (i_x>1&&i_x<height&&j_x>1&&j_x<width)
if Input_image(i_x,j_x)==1
ret_img(i_x,j_x)=~(Input_image(i_x-1,j_x)&&Input_image(i_x+1,j_x)&&Input_image(i_x,j_x-1)&&Input_image(i_x,j_x+1));
end
end
end
end
ret = ret_img;
end
四、结果展示
图片一、云:总面积 = 6412,单位长度面积 = 2.800000(边缘粗糙度)
图片二、圆:总面积 = 88,单位长度面积 = 0.162362(边缘粗糙度)
图片三、折线:总面积 = 570,单位长度面积 = 1.113281(边缘粗糙度)
图片四、直线:总面积 = 0,单位长度面积 = 0.000000(边缘粗糙度)