前言
最近在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实现方法,欢迎赐教,谢谢!