【问题标题】:Contour area does not show all the relevant areas轮廓区域未显示所有相关区域
【发布时间】:2017-12-21 06:21:46
【问题描述】:

我正在尝试识别图像中的所有圆圈。增强对比度后,使用阈值,使用精巧的边缘我找到所有轮廓并循环遍历它们,我在结果图像上出现的区域>0。结果并不好。请帮忙...

#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;
void changeGain(cv::Mat&,double,int);


int main(int argc, char** argv)
{

// Load the original image and make a duplication
cv::Mat rawImage = cv::imread("..\\3.png");
cv::Mat duplicateImage= rawImage.clone();

// Add contrast
changeGain(duplicateImage,1.9 ,-240);


// Apply thershold
cv::threshold( duplicateImage, duplicateImage, 150, 200, cv::THRESH_BINARY );


// Use canny edges
cv::Mat img_canny;
cv::Canny(duplicateImage,img_canny,150,200);

// Find all the contours from the canny image
vector<vector<cv::Point>> contours;
findContours(img_canny, contours, RETR_TREE, CHAIN_APPROX_SIMPLE);

// Approximate contours to polygons + get circles
vector<vector<Point> > contours_poly;

for( int i = 0; i < contours.size(); i++ )
{
    double area = contourArea(contours[i],true);
    if (area > 0 )
        contours_poly.push_back(contours[i]);
}

// Draw the circles on the image
drawContours(rawImage, contours_poly, -1, Scalar(rand() & 255, rand() & 255, rand() & 255));

// Show result
cv::imshow("Final Result", rawImage);
cv::waitKey(0);
imwrite("..\\contour_result.jpg",rawImage);

}

void changeGain(cv::Mat& image,double alpha, int beta)
{
//cv::Mat new_image = cv::Mat::zeros( image.size(), image.type() );

 /// Do the operation new_image(i,j) = alpha*image(i,j) + beta
 for( int y = 0; y < image.rows; y++ )
 {
     for( int x = 0; x < image.cols; x++ )
     {
         for( int c = 0; c < 3; c++ )
             image.at<cv::Vec3b>(y,x)[c] =
                     cv::saturate_cast<uchar>( alpha*( image.at<cv::Vec3b>(y,x)[c] ) + beta );

    }
 }

 return;

}

这是原图

这是显示所有轮廓时的结果

这是仅显示面积 >0 的轮廓时的结果

阈值后的图像

Image after canny

【问题讨论】:

  • 您是否有机会保存对阈值图像的引用?这对调试最有帮助
  • 在原帖后面加了图片。 @PatrickRoberts
  • 查看阈值,边缘突出的斑点似乎导致您的轮廓无法完全闭合循环。你看到了吗?
  • 要解决这个问题,请考虑在设置阈值之前添加erosion and dilation,并查看是否会消除导致开放轮廓的圆圈周围的锯齿状边缘。它应该可以解决问题,但您的轮廓在圆圈边缘可能不太精确。
  • 为什么你想要具有正导向区域的轮廓?你不能只过滤掉不够“圆形”的轮廓(根据一些适当的统计数据)吗?

标签: c++ opencv-contour


【解决方案1】:

首先,考虑使用形态学 (https://docs.opencv.org/trunk/d9/d61/tutorial_py_morphological_ops.html) 来清理然后阈值化的图像。使用诸如打开然后关闭之类的方法将消除噪声并填补阈值图像中的空白。

其次,您不需要检测 Canny 边缘。您可以从阈值中提取轮廓就好了,这就是我正在为我当前的项目做的事情。

第三,我假设您正在寻找圈子,在这种情况下,您可以使用minEnclosingCircle (https://docs.opencv.org/3.3.1/d3/dc0/group__imgproc__shape.html#ga8ce13c24081bbc7151e9326f412190f1)。由于形状是圆形,它应该只包含圆形,您可以通过将轮廓的contourArea 和圆形面积与minEnclosingCircle 返回的半径进行比较来确定。如果你的轮廓确实是一个圆,这个比率应该接近 1。(这也是我目前正在使用的一种技术)。

【讨论】:

  • 谢谢,奥斯卡。我会试试看效果如何
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-24
  • 2019-07-19
  • 2020-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多