[攻略][Matlab][C++][opencv]Matlab及C++ Opencv求图像的连通区域的圆度并可视化

5 篇文章 4 订阅
4 篇文章 0 订阅

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 ^

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值