1、Matlab
代码
%% 圆度的计算
% 圆形需要是白色的,背景是黑色的,可以根据需要确定是否对图像进行反向
clc
clear;close all;
%
%读取源图像
I = imread('1.bmp');
% figure;imshow(I);
%
%灰度化、取反
h = I;
if ndims(h) == 3
h = rgb2gray(I);
end
% figure;imshow(h);%灰度图像
% h = imcomplement(h);%取反
% figure;imshow(h);
%
%中值滤波、二值化
h = medfilt2(h,[4,4]);
bw = im2bw(h,graythresh(h));
%
%消除噪点
se = strel('disk',2);
bw = imclose(bw,se);
% figure;imshow(bw);
%
%填补闭合图形,填充色为白色
bw = imfill(bw,'holes');
%
%边界寻找
[B,L] = bwboundaries(bw,'noholes');
% 为每个闭合图形设置颜色显示
figure;
imshow(label2rgb(L, @jet, [1 1 1]))
hold on
for k = 1:length(B)
boundary = B{k};
plot(boundary(:,2), boundary(:,1), 'b', 'LineWidth', 2)
end
%
%计算面积
roundness = zeros(size(B,1), 3); %圆度的统计值,将图形中每个分离的连通区域的周长、面积和圆度值记录下来
stats = regionprops(L,'Area','Centroid');
threshold = 0.94;% 循环处理每个边界,length(B)是闭合图形的个数,即检测到的陶粒对象个数
for k = 1:length(B) % 获取边界坐标'
boundary = B{k}; % 计算周长
delta_sq = diff(boundary).^2;
perimeter = sum(sqrt(sum(delta_sq,2))); % 对标记为K的对象获取面积
area = stats(k).Area; % 圆度计算公式4*PI*A/P^2
metric = 4*pi*area/perimeter^2; % 结果显示
roundness(k,:) = [perimeter, area, metric ];
metric_string = sprintf('%2.2f',metric); % 用一个黑色小圆圈标记圆度大于threshold = 0.94 的对象
if metric > threshold
centroid = stats(k).Centroid;
% plot(640-centroid(2), 640-centroid(1),'wo');
plot(centroid(1), centroid(2),'ko');
text(centroid(1), centroid(2),metric_string,'Color','r',...
'FontSize',14,'FontWeight','bold');
end
end
title('圆度识别结果,越圆越接近1,');
%% 以下两种方法均可以提取出连通区域的面积
% method 1
a = struct2cell( stats );
b = a(1,:);
c = cell2mat( b );
figure,plot(c)
% method 2
% d = struct2array( stats );
% e = d(1:3:end);
% figure,plot(e)
图片
2、C++ Opencv
#include<iostream>
#include"opencv2\opencv.hpp"
#include<math.h>
using namespace std;
using namespace cv;
RNG g_rng(12345);
int g_nElementShape=MORPH_RECT;
Mat srcImage, dstImage;
void centerPoints(vector<Point>contour);
int main()
{
srcImage = imread("bw_0133.png", 0);//读取文件,可以是文件目录
if (!srcImage.data){ printf("图片读取错误!\n"); return false; }
namedWindow("原图");
imshow("原图", srcImage);
//进行开运算平滑
//namedWindow("【开运算/闭运算】", 1);
Mat dstImage = Mat::zeros(srcImage.rows, srcImage.cols, CV_8UC3);
Mat element = getStructuringElement(g_nElementShape,
Size(5, 5), Point(-1, -1));
morphologyEx(srcImage, dstImage, MORPH_OPEN, element, Point(-1, -1),2);
imshow("【开运算/闭运算】", dstImage);
vector<vector<Point>>contour;//用来储存轮廓
vector<Vec4i>hierarchy;
findContours(dstImage, contour, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
for (unsigned int i = 0; i < contour.size(); ++i)
{
centerPoints(contour[i]);
}
Mat drawing = Mat::zeros(dstImage.size(), CV_8UC3);
for (int unsigned i = 0; i < contour.size(); i++)
{
Scalar color = Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255));
drawContours(drawing, contour, i, color, 1, 8, vector<Vec4i>(), 0, Point());
}
imshow("轮廓图", drawing);//画出轮廓线,在轮廓线上显示坐标
//计算矩
vector<Moments>mu(contour.size());
for (unsigned int i = 0; i < contour.size(); i++)
{
mu[i] = moments(contour[i], false);
}
//计算矩中心
vector<Point2f>mc(contour.size());
for (unsigned int i = 0; i < contour.size(); i++)
{
mc[i] = Point2f(static_cast<float>(mu[i].m10 / mu[i].m00), static_cast<float>(mu[i].m01 / mu[i].m00));
}
for (unsigned int i = 0; i< contour.size(); ++i)
{
circle(drawing, mc[i], 5, Scalar(0, 0, 255), -1, 8, 0);
rectangle(drawing, boundingRect(contour.at(i)), Scalar(0, 255, 0));
char tam[100];
sprintf_s(tam, "(%0.0f,%0.0f)", mc[i].x, mc[i].y);
putText(drawing, tam, Point(mc[i].x, mc[i].y), FONT_HERSHEY_SIMPLEX, 0.4, Scalar(255, 0, 255), 1);
//计算质心 坐标
cout << "质心点坐标:" << "(" << (int)mc[i].x << "." << (int)mc[i].y << ")" << endl;
//下标输出
}
namedWindow("Contours", WINDOW_AUTOSIZE);
imshow("Contours", drawing);
waitKey(0);
return 0;
}
void centerPoints(vector<Point>contour)
{
double factor = (contourArea(contour) * 4 * CV_PI) /
(pow(arcLength(contour, true), 2));
cout << "factor:" << factor << endl; //计算出圆形度factor
}
3、参考
1、matlab 求图像的连通区域的圆度并可视化
https://blog.csdn.net/u012526003/article/details/52522745
2、opencv基础之测试质心和圆形度
https://blog.csdn.net/u014003644/article/details/77779661?utm_source=blogxgwz6
写于关雎
新浪微博:https://weibo.com/tianzhejia
CSDN博客:https://blog.csdn.net/qq_35605018
博客网站:http://www.zhijiadeboke.xyz
GitHub:https://github.com/ZhijiaTian
QQ邮箱:2461824656@qq.com
126邮箱:tianzhejia@126.com
Outlook邮箱:tianzhejia@outlook.com
以上均可与本人取得联系,欢迎探讨。^ v ^