C++ OpenCV实践:电容器件计数


前言

今天在51Halcon中看到一个有意思的帖子,是查找图片中电容器件的个数,觉得挺有意思,就用OpenCV实现了一下,这里分享给大家。

帖子链接:https://www.51halcon.com/thread-4670-1-5.html


1. OpenCV主要步骤

原图(引用帖子链接图片):
请添加图片描述
主要实现步骤:

  1. 读取原图并转为灰度图
  2. 提取ROI区域,主要是去除图片左边缘以及右下角水印的影响
  3. OTSU阈值化
  4. 执行2次开运算,分割每个电容器件
  5. 执行3次膨胀操作,连接每个电容器件
  6. 使用带统计信息的连通域计算方法
  7. 输出电容器件的个数以及定位每个电容器件的粗略位置

2. OpenCV C++实现

#include <iostream>
#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\\connected_domain.png";
	Mat mSrc = imread(strImgFile);
	CV_Assert(!mSrc.empty());

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

	Mat mRoi = mGray(Rect(6, 1, mGray.cols - 6, mGray.rows - 35));
	CV_Assert(!mRoi.empty());
	imshow("roi", mRoi);

	Mat mThresh;
	threshold(mRoi, mThresh, 128, 255, THRESH_BINARY | THRESH_OTSU);
	CV_Assert(!mThresh.empty());

	imshow("thresh", mThresh);



	Mat mKernel1 = getStructuringElement(MORPH_RECT, Size(5, 5));
	Mat mMorph;
	morphologyEx(mThresh, mMorph, MORPH_OPEN, mKernel1, Point(-1, -1), 2);
	CV_Assert(!mMorph.empty());

	imshow("open", mMorph);

	Mat mKernel2 = getStructuringElement(MORPH_RECT, Size(30, 3));
	morphologyEx(mMorph, mMorph, MORPH_DILATE, mKernel2, Point(-1, -1), 2);

	imshow("dilate", mMorph);

	//连通域信息统计
	Mat mLabel = Mat::zeros(mMorph.size(), CV_32S);
	CV_Assert(!mLabel.empty());

	Mat mStats;//记录外接矩形信息,左上角坐标,宽度、高度、面积
	Mat mCentroids;//记录外接矩形中心点

	//label 0: background
	int nLabelNums = connectedComponentsWithStats(mMorph, mLabel, mStats, mCentroids);
	std::cout << "电容器件总数:" << nLabelNums-1 << std::endl;

	Mat mResult = mSrc.clone();
	for (int i = 1; i < nLabelNums; i++)
	{
    
    
		Vec2d center = mCentroids.at<Vec2d>(i, 0);
		int x = mStats.at<int>(i, CC_STAT_LEFT);
		int y = mStats.at<int>(i, CC_STAT_TOP);
		int width = mStats.at<int>(i, CC_STAT_WIDTH);
		int height = mStats.at<int>(i, CC_STAT_HEIGHT);
		circle(mResult, Point(center[0], center[1]), 2, Scalar(0, 0, 255), -1);
		rectangle(mResult, Rect(x + 6, y + 1, width, height), Scalar(255, 0, 255));
	}

	imshow("Result", mResult);
	
	waitKey(0);
	destroyAllWindows();

	return 0;
}

3. 运行结果

在这里插入图片描述


总结

从结果可以看出,上文方法只能准确检测电容器件的个数,至于定位电容位置就不是很准确了,只能给出大致位置信息,如果有大神能给出更准确的定位方法,欢迎留言给出,谢谢!(深度学习需要大量图片,这里就没有考虑)

Guess you like

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