c – Opencv:边缘检测,膨胀和质量绘图

c – Opencv:边缘检测,膨胀和质量绘图,第1张

概述我的工作基于带有点阵的图像(图1),最终结果如图4所示.我将逐步解释我的工作. 图1原始图像 步骤1:检测每个对象的边缘,包括点和我想要删除的“环”以获得更好的性能.边缘检测的结果如图2所示.我使用Canny边缘探测器,但它对一些浅灰色点不起作用.我的第一个问题是如何关闭点的轮廓并尽可能减少其他噪音? 图2边缘检测 第2步:扩张每个物体.我找不到填补洞的好方法,所以我直接扩张它们.如图3所示,孔看 我的工作基于带有点阵的图像(图1),最终结果如图4所示.我将逐步解释我的工作.

图1原始图像

步骤1:检测每个对象的边缘,包括点和我想要删除的“环”以获得更好的性能.边缘检测的结果如图2所示.我使用Canny边缘探测器,但它对一些浅灰色点不起作用.我的第一个问题是如何关闭点的轮廓并尽可能减少其他噪音?

图2边缘检测

第2步:扩张每个物体.我找不到填补洞的好方法,所以我直接扩张它们.如图3所示,孔看起来太大,其他噪音也是如此.我的第二个问题是如何填充或扩大孔,以使它们以相同/相似的尺寸填充圆圈?

图3扩张

第3步:找到并绘制每个点的质心.如图4所示,由于粗略图像处理,存在“环”的标记,并且一些点以两个白色像素示出.想要的结果应该只显示一个点的点和一个白色像素.

图4:质量中心

这是我的这3个步骤的代码.任何人都可以帮助我的工作做得更好吗?

#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"#include <stdlib.h>#include <stdio.h>#include <cv.h>#include <highgui.h>using namespace std;using namespace cv;// Global variablesMat src,edge,dilation;int dilation_size = 2;// Function headervoID thresh_callback(int,voID*);int main(int argc,char* argv){    Iplimage* img = cvLoadImage("c:\dot1.bmp",0);         // dot1.bmp = fig. 1    // Perform canny edge detection    cvCanny(img,img,33,100,3);    // Iplimage to Mat    Mat imgMat(img);    src = img;    nameDWindow("Step 1: Edge",CV_WINDOW_autoSIZE);    imshow("Step 1: Edge",src);    // Apply the dilation operation    Mat element = getStructuringElement(2,Size(2 * dilation_size + 1,2 * dilation_size + 1),Point(dilation_size,dilation_size));     // dilation_type = MORPH_ELliPSE    dilate(src,dilation,element);    // imwrite("c:\dot1_dilate.bmp",dilation);                nameDWindow("Step 2: dilation",CV_WINDOW_autoSIZE);    imshow("Step 2: dilation",dilation);    thresh_callback( 0,0 );    waitKey(0);    return 0;}/* function thresh_callback */voID thresh_callback(int,voID*){    vector<vector<Point>> contours;    vector<Vec4i> hIErarchy;    // Find contours    findContours(dilation,contours,hIErarchy,CV_RETR_TREE,CV_CHAIN_APPROX_SIMPLE,Point(0,0));    // Get the moments    vector<Moments> mu(contours.size());    for(int i = 0; i < contours.size(); i++) {        mu[i] = moments(contours[i],false);    }    // Get the mass centers    vector<Point2f> mc(contours.size());    for(int i = 0; i < contours.size(); i++) {        mc[i] = Point2f(mu[i].m10/mu[i].m00,mu[i].m01/mu[i].m00);     }    // Draw mass centers    Mat drawing = Mat::zeros(dilation.size(),CV_8UC1);    for( int i = 0; i< contours.size(); i++ ) {        Scalar color = Scalar(255,255,255);        line(drawing,mc[i],color,1,8,0);    }    nameDWindow("Step 3: Mass Centers",CV_WINDOW_autoSIZE);    imshow("Step 3: Mass Centers",drawing);}
解决方法 您可以采取一些措施来改善结果.要减少图像中的噪点,可以在应用Canny运算符之前应用中值模糊.这是一种常见的去噪技术.另外,尽量避免使用C API和Iplimage.
cv::Mat img = cv::imread("c:\dot1.bmp",0);         // dot1.bmp = fig. 1    cv::medianBlur(img,7);    // Perform canny edge detection    cv::Canny(img,100);

这可以显着减少边缘图像中的噪声量:

为了更好地保留点的原始大小,您可以使用较小的内核而不是扩张来执行一些形态学闭合迭代.这也会减少点与圆的连接:

// This replaces the call to dilate()cv::morphologyEx(src,MORPH_CLOSE,cv::noArray(),cv::Point(-1,-1),2);

这将使用3×3内核执行两次迭代,使用cv :: noArray()表示.

结果更清晰,点完全填满:

保持管道的其余部分不被修改会产生最终结果.圆圈中仍有一些虚假的质量中心,但比原始方法少得多:

如果您想尝试完全从结果中删除圆圈,可以尝试使用cv::HoughCircles()并调整参数,直到获得良好的结果.这可能会有一些困难,因为整个圆圈在图像中不可见,只有细分,但我建议你试一试.如果您确实检测到最里面的圆圈,则可以将其用作遮罩来过滤掉外部质量中心.

总结

以上是内存溢出为你收集整理的c – Opencv:边缘检测,膨胀和质量绘图全部内容,希望文章能够帮你解决c – Opencv:边缘检测,膨胀和质量绘图所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1243069.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-06
下一篇 2022-06-06

发表评论

登录后才能评论

评论列表(0条)

保存