c++ opencv4.5.5 实现硬币计数

效果图

c++ opencv4.5.5 实现硬币计数_第1张图片

实现思路

  1. 先将图像进行灰度化再进行二值化处理
  2. 消除噪声,膨胀使物体变大消除硬币内部噪声,开操作消除部分高亮区域
  3. 据距离变换的性质,经过简单的运算,即可用于细化字符的轮廓和查找物体质心(中心)
  4. 轮廓查找

代码

#include 
#include 


int main()
{
	//初始化操作
	cv::Mat src = cv::imread("./1.png");
	cv::Mat img = src.clone();

	// 图像预处理-灰度化
	cv::Mat gray;
	cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);

	// 图像预处理-二值化
	cv::Mat thresh;
	cv::threshold(gray, thresh, 127, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);

	// 图像预处理-消除特有噪声(形态学变换)
	cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
	cv::Mat dilate;
	cv::morphologyEx(thresh, dilate, cv::MORPH_DILATE, kernel, cv::Point(-1, -1),  5); //膨胀
	cv::Mat opening;
	cv::morphologyEx(dilate, opening, cv::MORPH_OPEN, kernel, cv::Point(-1, -1), 3);   //开操作

	//根据距离变换的性质,经过简单的运算,即可用于细化字符的轮廓和查找物体质心(中心)
	//寻找前景区域-分离连接物体distanceTranform 参数含义:1)二值图像     2)距离变换类型   3)距离变换的掩膜模板'
	//DIST_L2:简单欧几里得距离 Δ = sqrt((x1 - x2)² + (y1 - y2)²)
	cv::Mat dist_transform;
	cv::distanceTransform(opening, dist_transform, cv::DIST_L2, 3);

	//找到未知区域
	cv::Mat sure_fg;
	double minValue, maxValue;    // 最大值,最小值
	cv::minMaxLoc(dist_transform, &minValue, &maxValue);

	cv::threshold(dist_transform, sure_fg, 0.5 * maxValue, 255, cv::THRESH_BINARY);
	
	//通道转换
	sure_fg.convertTo(sure_fg, CV_8UC1);

   //找到硬币中心(轮廓查找)
	std::vector <std::vector<cv::Point>> contours;
	std::vector <cv::Vec4i> hierarchy;
	cv::findContours(sure_fg, contours, hierarchy, cv::RETR_LIST, cv::CHAIN_APPROX_NONE);

	cv::drawContours(img, contours, -1, (0, 0, 255), 3);
	std::stringstream ss;
	std::string str;
	ss << "count:" << contours.size();
	ss >> str;
	cv::putText(img, str, cv::Point(0, 30), cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 255, 0), 1);

	cv::imshow("", img);
	cv::waitKey();


	return 0;

}

你可能感兴趣的:(opencv,学习笔记,opencv,计算机视觉,c++)