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