C++ OpenCV实践:复杂划痕背景下检测缺陷


前言

最近在51Halcon中看到一条有意思的求助帖子,有热心朋友给出了Halcon的解决方法,这里给出C++ OpenCV的解决方法。


1. 检测步骤

Halcon实现(引用): 看到检测图像以及想要检测的目标(绿色实线闭合区域),我们知道,要检测的区域的区分度不高,这里给出个人实现思路:检测区域位于圆形的中心,而圆形中心区域亮度比周边要高,我们可以先分割出中心亮度高的区域,然后在这一分割出的区域进行检测目标,提取出目标轮廓。

2. C++ OpenCV实现

#include <opencv2imgcodecs.hpp>
#include <opencv2core.hpp>
#include <opencv2imgproc.hpp>
#include <opencv2highgui.hpp>
#include <vector>

using namespace cv;

int main()
{
          
   
	std::string strImgFile = "C:\Temp\common\Workspace\Opencv\images\detect_defect_with_complex_background.bmp";
	Mat mSrc = imread(strImgFile);
	CV_Assert(!mSrc.empty());

	Mat mGray;
	cvtColor(mSrc, mGray, COLOR_BGR2GRAY);
	CV_Assert(!mGray.empty());

	Mat mThresh;
	threshold(mGray, mThresh, 0, 255, THRESH_BINARY | THRESH_OTSU);
	CV_Assert(!mThresh.empty());

	imshow("thresh", mThresh);

	Mat mCenterLightArea;
	threshold(mGray, mCenterLightArea, 200, 255, THRESH_BINARY);
	CV_Assert(!mCenterLightArea.empty());

	imshow("center", mCenterLightArea);

	Mat kernel = getStructuringElement(MORPH_RECT, Size(11, 11));
	Mat mOpen;
	morphologyEx(mCenterLightArea, mOpen, MORPH_OPEN, kernel);
	CV_Assert(!mOpen.empty());

	imshow("open1", mOpen);

	morphologyEx(mOpen, mOpen, MORPH_DILATE, kernel, Point(-1, -1), 7);
	 
	imshow("open2", mOpen); 

	std::vector<std::vector<Point>> contours;
	findContours(mOpen, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
	Point2f center = {
          
    0 };
	float	radius = 0;

	for (int i = 0; i < contours.size(); i++)
	{
          
   
		Point2f tempCenter = {
          
    0 };
		float tempRadius = 0;
		minEnclosingCircle(contours[i], tempCenter, tempRadius);

		if (tempRadius > radius)
		{
          
   
			radius = tempRadius;
			center = tempCenter;
		}
	}

	Mat mMask = Mat::zeros(mOpen.size(), mOpen.type());
	CV_Assert(!mMask.empty());

	circle(mMask, Point(int(center.x + 0.5), int(center.y + 0.5)), int(radius + 0.5), 255, -1);

	imshow("mask", mMask);

	Mat mCenterArea = mGray & mMask;
	CV_Assert(!mCenterArea.empty());

	imshow("center", mCenterArea);

	Mat mResult;
	threshold(mCenterArea, mResult, 10, 255, THRESH_BINARY_INV | THRESH_OTSU);
	CV_Assert(!mResult.empty());
	imshow("result", mResult);

	contours.clear();
	findContours(mResult, contours, RETR_TREE, CHAIN_APPROX_NONE);

	for (int i = 0; i < contours.size(); i++)
	{
          
   
		double area = contourArea(contours[i]);
		if (area > 1000 && area < 10000)
		{
          
   
			drawContours(mSrc, contours, i, Scalar(0, 0, 255));
		}
	}

	imshow("Final Result", mSrc);

	waitKey(0);
	destroyAllWindows();

	system("pause");
	return 0;
}

3. 结果展示:

原图:

OpenCV实现:

Halcon实现(引用):


总结

本人的方法,只针对特定的原始图像,没法验证通用性,个人感觉很繁琐,没有Halcon简单方便,如果有大神提供简单的OpenCV实现方法,欢迎赐教,谢谢!

参考

经验分享 程序员 微信小程序 职场和发展