%颗粒圆度
%完成图像预处理%imread-rgb2gray-complement(0,1)-medfilt(GS)-imbinarize(graythresh)自动阈值控制边界轮廓,杂乱边界
%形态学优化 bwareaopen(bw,50);
%特征提取及显示: 面积 周长 圆度
clear;close all;
%% 预处理
I = imread('01.png');
figure;
subplot(231),imshow(I),title('rgb');
%读取源图像
h = rgb2gray(I);
subplot(232),imshow(h),title('gray');
%灰度图像
h = imcomplement(h); %!!!
%subplot(233),imshow(h),title('h');
%取反,0,1 convert
h = medfilt2(h,[4,4]);
subplot(234),imshow(h),title('med');
%中值滤波
bw= im2bw(h,[0.90]);%graythresh(h)% []
subplot(235),imshow(h),title('graythresh');
%graythresh二值化
%bw = im2bw(h,0.1);
%subplot(236),imshow(bw),title('bw');
%自定义二值化
%% 形态学优化
bw=bwareaopen(bw,10); %和yuandu_2 区别是:像素数小于50的去掉,
figure;
subplot(221),imshow(bw),title('bwareaopen');
%去掉像素数低的目标(腐蚀=bwareaopen),像素数小于30的(30根据具体应用中目标的大小调节),关键点理解图像连通域的含义。
se = strel('disk',2);
%结构元素半径为2的圆,
%二值图像去除小区域后,对大区域中的缝隙填充(膨胀close),同时平滑边界
%膨胀腐蚀所用圆单元,需要注意参数2需要调试,以满足不同场合应用。
bw = imclose(bw,se);
subplot(222),imshow(bw);title('close')
%close运算平滑轮廓
%bw = imfill(bw,'holes');
%subplot(223),imshow(bw);title('fill')
%imfill 填补闭合图形,填充色为白色;在上一步先腐蚀膨胀之后,对连通域填孔(fill),使其变为实心体。
%bw=edge(bw,'canny');
%subplot(224),imshow(bw), title('edge');
%canny 边缘提取
%%
[B,L] = bwboundaries(bw,'noholes');
%边界提取,返回一个含有k个cell数组(B是边界像素位置,)。L是标记矩阵[0,1],标识图像区域中全部目标点
figure;imshow(label2rgb(L, @jet, [.5 .5 .5])),title('boundary');
% 为每个闭合图形[0,1] L 设置颜色显示(@jet对不同目标显示不同颜色)
hold on% 图像保持
for k = 1:length(B) %K表示B单元数组中的第k个cell。即代表第k个边界区域。
boundary = B{k}; %计算k个边界的所有点
plot( boundary(:,2),boundary(:,1), 'r', 'LineWidth', 2)
%(:,2) 第二列的所有元素, plot 用红色 r 框来显示边界 线宽是2
end
%%
stats = regionprops(L,'Area','Centroid');
%计算面积 regionprops %求出标记矩阵L中,各个区域的面积Area和质心Centroid
for k = 1:length(B)
% 循环处理每个边界,length(B)是闭合图形的个数,即检测到的边界对象个数
boundary = B{k};
% 获取边界坐标
delta_square = diff(boundary).^2; %x,y增量平方
perimeter = sum(sqrt(sum(delta_square,2))); %sum(A,n)表示将矩阵A沿着第n个维度(列)求和。
perimeter_string = sprintf('%2.3f', perimeter); % '%2.3f' 2个宽度,保留3位小数!!!
% 计算周长
area = stats(k).Area;
area_string = sprintf('%2.3f', area);
% 对标记为K的对象获取面积
metric = (4*pi*area)/((perimeter)^2);
% 圆度计算公式4*PI*A/P^2
metric_string = sprintf('%f\n',metric);
% 在工作空间显示结果 sprintf,区别 fprintf
%%
threshold = 0.4;
if metric > threshold
centroid = stats(k).Centroid;
plot(centroid(1),centroid(2),'k*');
% 用一个黑色 小圆圈'ko' 'k*' 'r*' 标记圆度大于threshold 的对象质心
end
text(boundary(1,2)-30,boundary(1,1)+13,metric_string,...
'Color','y','FontSize',12,'FontWeight','bold');
text(boundary(1,2)+35,boundary(1,1)+26,strcat('Area:',area_string),...
'Color','r','FontSize',12,'FontWeight','bold');
text(boundary(1,2)+35,boundary(1,1)+56,strcat('Perimeter:',perimeter_string),...
'Color','r','FontSize',12,'FontWeight','bold');
title('圆度识别结果:越圆越接近1,');
%设置图形显示 位置:相对左边界x,y 显示内容:metric_string/ strcat
%颜色'Color'黄色'y' 字号 'FontSize',14,字形加粗'FontWeight','bold'
fprintf('round_area = %f\n', area); % 在命令窗口输出高精度\n结果
fprintf('perimeter_string = %f\n', perimeter);
fprintf('metric_string = %f\n', metric);
xlswrite('test.xls',area) ; % ??? 输出到表格中 待修改
end
%颗粒圆度
%完成图像预处理%imread-rgb2gray-complement(0,1)-medfilt(GS)-imbinarize(graythresh)自动阈值控制边界轮廓,杂乱边界
%形态学优化 bwareaopen(bw,50);
%特征提取及显示: 面积 周长 圆度
clear;close all;
%% 预处理
I = imread('01.png');
figure;
subplot(231),imshow(I),title('rgb');
%读取源图像
源图像: 目标识别区域和背景区域颜色应该相反,边界识别会更准确
h = rgb2gray(I);
subplot(232),imshow(h),title('gray');
%灰度图像gray(8bit)
%h=rgb2hsv(h); (扩展:颜色空间)
%subplot(2,2,2),imshow(hsv);
%h=h(:,:,1);%显示 v分量
%subplot(2,2,3),imshow(v);
% 转化 RGB 值为 HSV 颜色空间
h = imcomplement(h); %!!! 看是否需要
%subplot(233),imshow(h),title('h');
%取补,255(1) - convert %黑白互补,灵活调整计算区域(白色),配合二值化操作,一般在二值化之前(会影响二值化的阈值),若在之后(非0即1)(一般是二值化结果特别好,取反可以直接获得二值化对立的结果)
h = medfilt2(h,[4,4]);
subplot(234),imshow(h),title('med');
%中值滤波
%sigma = 1;
%gausFilter=fspecial('gaussian',[5 5],sigma);
%h= imfilter(h, gausFilter, 'replicate');
%subplot(235),imshow(h),title('gaus'); %高斯滤波 和中值滤波可以合用,会稍微提高均匀度
%bw= im2bw(h,graythresh(h)]); %graythresh(h)%
%subplot(235),imshow(h),title('graythresh');
%graythresh二值化 % 出现多个白色干扰区域,不利于精确提取,但可以参考
bw = im2bw(h,0.1);
subplot(236),imshow(bw),title('bw');
%自定义二值化 阈值选取是 保证图形识别精度的关键,调整阈值使小圆点刚刚消失(误差在百分位) 像素值大于阈值 变为白色
%level_1=graythresh(h); % 可以获取全局阈值 作为参考值
%level_2=0.1
%bw = im2bw(h,level_); % 此结构更灵活
BWimg = grayimg; (扩展:循环处理二值化)
[width,height]=size(grayimg);
T1=80;
for i=1:width
for j=1:height
if(grayimg(i,j)<T1)
BWimg(i,j)= 255;
else
BWimg(i,j)= 0;
end
end
end
figure(3);
imshow(BWimg);
%二值化
%bw = imcomplement(bw ); % 一般是二值化结果特别好,取反可以直接获得二值化对立的结果)
%相当于取 二值化阈值的补(1-level_2)。
%% 形态学优化
bw=bwareaopen(bw,10); %和yuandu_2 区别是:像素数小于50的去掉,
figure;
subplot(221),imshow(bw),title('bwareaopen');
%抹去目标外围小连通域(抹去小的白色圆点变为黑色)对目标一般无影响(腐蚀=bwareaopen??),像素数小于30的(30根据具体应用中目标的大小调节),关键点理解图像连通域的含义。阈值根据拟抹除连通域的最大值设定。只有连通域大于设定阈值的区域可以保留下来(变为白色) 通过区域大小标定白色区域,当有多个独立连通域时可与自动阈值graythresh(h) 搭配有奇效
se = strel('disk',2);
%结构元素半径为2的圆,
%二值图像去除小区域后,对大区域中的缝隙填充(膨胀imclose),同时平滑边界
%膨胀腐蚀所用圆单元,需要注意参数2需要调试,以满足不同场合应用。
bw = imclose(bw,se);
subplot(222),imshow(bw);title('close')
%imclose运算平滑轮廓
%bw = imopen(bw,se);
%subplot(223),imshow(bw);title('open')
%imopen运算 ???
%bw = imfill(bw,'holes');
%subplot(223),imshow(bw);title('fill')
%imfill 填补闭合图形,填充色为白色;在上一步先腐蚀膨胀之后,对连通域填孔(fill),使其变为实心体。用来获取外轮廓
%bw=edge(bw,'canny');
%subplot(224),imshow(bw), title('edge');
%canny 边缘提取
%% 特征提取
[B,L] = bwboundaries(bw,'noholes');
%边界提取(各部分白色区域的边界),返回一个含有N*M的 cell数组(B是边界像素位置,)。L是标记矩阵[0,1]矩阵,标识图像区域中全部目标
figure;imshow(label2rgb(L, @jet, [.5 .5 .5])),title('boundary');
% 为每个闭合图形[0,1] 矩阵 L 设置颜色显示(@jet对不同目标显示不同颜色)
hold on% 图像保持
for k = 1:length(B) %K表示B单元数组中(1-N)个cell。即代表1-N个边界区域。
boundary = B{k}; %计算第k个边界的所有点坐标
plot( boundary(:,2),boundary(:,1), 'r', 'LineWidth', 2)
%(:,2) 第二列的所有元素, plot 用红色 r 框来显示边界 线宽是2
end
%%
stats = regionprops(L,'Area','Centroid');
%计算面积 regionprops %求出标记矩阵L中,各个区域的面积Area和质心Centroid
for k = 1:length(B)
% 循环处理每个边界,length(B)是闭合图形的个数,即检测到的边界对象个数
boundary = B{k};
% 获取边界坐标
delta_square = diff(boundary).^2; %x,y增量平方
perimeter = sum(sqrt(sum(delta_square,2))); %sum(A,n)表示将矩阵A沿着第n个维度(列)求和。
perimeter_string = sprintf('%2.3f', perimeter); % '%2.3f' 2个宽度,保留3位小数!!!
% 计算周长 此方法用公式计算的周长精度高,regionprops获取的周长偏大。
area = stats(k).Area;
area_string = sprintf('%2.3f', area);
% 对标记为K的对象获取面积
metric = (4*pi*area)/((perimeter)^2);
% 圆度计算公式4*PI*A/P^2
metric_string = sprintf('%f\n',metric);
% 在工作空间显示结果 sprintf,区别 fprintf
%字符串格式
%% 结果输出
threshold = 0.4;
if metric > threshold
centroid = stats(k).Centroid;
plot(centroid(1),centroid(2),'k*');
% 用'ko'(黑圈)'k*'(黑星) 'r*'(红星) w g b y r k 标记圆度大于threshold 的对象质心
end
text(boundary(1,2)-30,boundary(1,1)+13,metric_string,...
'Color','y','FontSize',12,'FontWeight','bold');
text(boundary(1,2)+35,boundary(1,1)+26,strcat('Area:',area_string),...
'Color','r','FontSize',12,'FontWeight','bold');
text(boundary(1,2)+35,boundary(1,1)+56,strcat('Perimeter:',perimeter_string),...
'Color','r','FontSize',12,'FontWeight','bold');
title('圆度识别结果:越圆越接近1,');
%text 设置图上显示 位置:相对左边界x,y 显示数值内容:metric_string 或者(strcat(‘显示字符串:’,数值),)
%颜色'Color'黄色'y' 字号 'FontSize',12,字形加粗'FontWeight','bold'
fprintf('round_area = %f\n', area); % 在命令窗口输出高精度\n结果
fprintf('perimeter_string = %f\n', perimeter);
fprintf('metric_string = %f\n', metric);
%% xlswrite('test.xls',area) ; % ??? 输出到表格中 待修改
end