我正在尝试识别图像中的所有圆圈。在增强对比度之后,使用阈值,使用精细边缘我找到所有轮廓并循环通过它们,其在结果图像上具有> 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
的轮廓时的结果thershold之后的图片
答案 0 :(得分:0)
首先,考虑使用形态学(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.(这也是我目前使用的一种技术)。