OpenCV应用实例:标出低对比度图像中的圆


前言

今天看了篇微信公众号,是使用python opencv 检测出低对比度图像中所有的圆,感觉挺有意思的,这里用C++实现出来,对原始的参数做了改动(发现原始参数检测出的圆有漏检的情况,主要是由于形态学开闭操作结果和预期结果不一致导致的)。


1. 低对比度图像中圆的检测步骤

  1. 读取彩色图像;
  2. 转换灰度图像;
  3. 模糊图像(ksize=50);
  4. 计算灰度图像与模糊图像的差值图像;
  5. 对差值图像进行二值化操作(阈值为15);
  6. 对二值化图像进行闭操作,连接不连续区域;(核大小为11x11)
  7. 对闭操作后的图像进行形态学开运算,分割出不同圆;(核大小为9x9)
  8. 查找轮廓;
  9. 过滤轮廓并绘制圆,主要针对图像上的水印;

2. C++ OpenCV实现

#include <iostream>
#include <opencv2\imgcodecs.hpp>
#include <opencv2\imgproc.hpp>
#include <opencv2\core.hpp>
#include <opencv2\highgui.hpp>
#include <vector>

int main()
{
    
    
	using namespace std;
	using namespace cv;

	string strImgFile = "C:\\Temp\\common\\Workspace\\Opencv\\images\\low_contrast_circle.jpg";
	Mat src = imread(strImgFile);
	CV_Assert(src.empty() == false);
	imshow("Src", src);

	Mat grayImg;
	cvtColor(src, grayImg, COLOR_BGR2GRAY);
	CV_Assert(grayImg.empty() == false);

	Mat blurImg;
	blur(grayImg, blurImg, Size(50, 50));
	CV_Assert(blurImg.empty() == false);

	imshow("Mean Blur", blurImg);
	waitKey(0);

	Mat diffImg;
	absdiff(grayImg, blurImg, diffImg);
	CV_Assert(diffImg.empty() == false);

	imshow("Diff", diffImg);
	waitKey(0);

	Mat binaryImg;
	threshold(diffImg, binaryImg, 15, 255, THRESH_BINARY);
	CV_Assert(binaryImg.empty() == false);

	imshow("Threshold", binaryImg);
	waitKey(0);

	Mat closeKernel = getStructuringElement(MORPH_ELLIPSE, Size(11, 11));
	Mat closeImg;
	morphologyEx(binaryImg, closeImg, MORPH_CLOSE, closeKernel);
	CV_Assert(closeImg.empty() == false);

	imshow("Close", closeImg);
	waitKey(0);

	Mat openKernel = getStructuringElement(MORPH_ELLIPSE, Size(9, 9));
	Mat openImg;
	morphologyEx(closeImg, openImg, MORPH_OPEN, openKernel);
	CV_Assert(openImg.empty() == false);

	imshow("Open", openImg);
	waitKey(0);
	
	vector<vector<Point>> contours;

	Mat src_copy = src.clone();
	findContours(openImg, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
	for (int i = 0; i < contours.size(); i++)
	{
    
    
		Point2f center;
		float radius = 0;
		minEnclosingCircle(contours[i], center, radius);
		if (radius < 30)
			circle(src_copy, Point((int)center.x, (int)center.y), (int)radius, Scalar(0, 0, 255));
	}

	imshow("Circles", src_copy);
	waitKey(0);

	system("pause");
	return 0;
}

3. 结果展示:

原图:
在这里插入图片描述
检测结果:
在这里插入图片描述


总结

传统图像处理技术就是要针对具体问题具体分析,然后调整参数,同一张图像由于某些改变(水印,图像大小)都有可能导致之前的参数失效。所以一般检测时都会选择一些尺度、旋转、光照等不变的特征进行检测。

参考

https://blog.csdn.net/stq054188/article/details/120322770

Guess you like

Origin blog.csdn.net/DU_YULIN/article/details/120366415