最近,在学习如何从PCB上提取出胶点轮廓。故,从网上找了一个复杂背景图,学习如何提取轮廓。
目标:从充满划痕的背景中,提取出如下图的轮廓。

处理流程:原图-》转为灰度图-》中值滤波提取背景图-》背景图-灰度图,得到目标区域和划痕区域-》二值化-》形态学-》轮廓寻找,排序-》绘制轮廓。
处理过程的代码:
cpp
m_srcImg = cv::imread("D:/work/vision/OpenCVDemo/image/demo1.png");
cv::Mat gray, blur_img, binary_img, binary_img_low, binary_img_high, diff_img, morphology_img_open, morphology_img_close;
if (m_srcImg.channels() == 3)
{
cv::cvtColor(m_srcImg, gray, cv::COLOR_BGR2GRAY);
}
else
{
gray = m_srcImg.clone();
}
cv::medianBlur(gray, blur_img, 199);
//cv::bilateralFilter(gray, blur_img, 149, 30, 30);
//cv::absdiff(gray, blur_img, diff_img);
//diff_img = gray - blur_img;
diff_img = blur_img - gray;
cv::imwrite("D:/work/vision/OpenCVDemo/image/diff.png", diff_img);
cv::threshold(diff_img, binary_img, 20, 255, cv::THRESH_BINARY);
cv::Mat kernel1 = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3));
cv::Mat kernel2 = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(3, 3));
cv::morphologyEx(binary_img, morphology_img_open, cv::MORPH_OPEN, kernel1);
cv::morphologyEx(morphology_img_open, morphology_img_close, cv::MORPH_CLOSE, kernel2);
std::vector<std::vector<cv::Point>> contours;
cv::findContours(morphology_img_close, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
std::sort(contours.begin(), contours.end(), [](const std::vector<cv::Point> &a, const std::vector<cv::Point> &b) {
return cv::contourArea(a) > cv::contourArea(b);
});
cv::drawContours(m_srcImg, contours, 0, cv::Scalar(0, 0, 255));
记录:
kernel_size =199的中值滤波结果:

最终结果:

kernel_size = 99:

二值化

