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


前言

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


1. 检测步骤

Halcon实现(引用https://www.51halcon.com/thread-1173-1-2.html):
请添加图片描述
看到检测图像以及想要检测的目标(绿色实线闭合区域),我们知道,要检测的区域的区分度不高,这里给出个人实现思路:检测区域位于圆形的中心,而圆形中心区域亮度比周边要高,我们可以先分割出中心亮度高的区域,然后在这一分割出的区域进行检测目标,提取出目标轮廓。

2. C++ OpenCV实现

#include <opencv2\imgcodecs.hpp>
#include <opencv2\core.hpp>
#include <opencv2\imgproc.hpp>
#include <opencv2\highgui.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实现(引用https://www.51halcon.com/thread-1173-1-2.html):
请添加图片描述


总结

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

参考

https://www.51halcon.com/thread-1173-1-2.html

Guess you like

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