Opencv实战4 对象计数

对象计数

4.1 题目

        如图数出下图的玉米种子的数量

在这里插入图片描述#### 4.2 思路
        这个案例的难点在于有的玉米粒是靠在一起的,不然的话直接轮廓查找就能搞定了。基本指导思想就是把玉米粒都分开,分成一粒一粒的再进行轮廓查找。
1、 二值化
2、 形态学操作
3、 距离变换
4、 二值化
5、 形态学操作
6、 轮廓查找
具体步骤和解释都在代码里了。

4.3 代码示例
#include <opencv2\opencv.hpp>
using namespace cv;

int main(int argc, char *argv[])
{
	Mat sorImg = imread("yumili.jpg", IMREAD_GRAYSCALE);
	//imshow("sorImg", sorImg);

	// 第一步:二值化,注意使用THRESH_TRIANGLE
	Mat binaryImg;
	threshold(sorImg, binaryImg, 0, 255, THRESH_BINARY | THRESH_TRIANGLE);
	
	// 第二步:形态学操作,稍微分离一下玉米粒
	Mat morphologyImg;
	Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
	dilate(binaryImg, morphologyImg, kernel,Point(-1,-1),2);
	imshow("dstImg1", morphologyImg);

	// 第三步:距离变换,查找出亮包
	Mat dist;
	bitwise_not(morphologyImg, morphologyImg);
	distanceTransform(morphologyImg, dist, DIST_L2, 3);
	normalize(dist, dist, 0, 255, NORM_MINMAX);
	

	// 第四步:再次二值化,局部二值化
	Mat dsit_8u;
	dist.convertTo(dsit_8u, CV_8U);
	adaptiveThreshold(dsit_8u, dsit_8u, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 205, 0.0);

	// 第五步:再次形态学操作,彻底分割玉米粒
	erode(dsit_8u, dsit_8u, kernel, Point(-1, -1), 18);

	// 第六步: 连通区域寻找计算
	std::vector<std::vector<Point>>contours;
	findContours(dsit_8u, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
	RNG rng(124345);
	Mat dstImg(dsit_8u.size(),CV_8UC3);
	for (int i = 0; i < contours.size(); ++i)
	{
		drawContours(dstImg, contours, i, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)),-1, 8, Mat());
	}

	imshow("dstImg", dstImg);
	std::cout << "num is:" << contours.size();
	waitKey();

	return 0;	
}

效果图;
在这里插入图片描述

4.4 关键API

distanceTransform:距离变换,找出物体的中心。
threshold :THRESH_TRIANGLE方式的二值化适用于直方图单峰的图像。
adaptiveThreshold:局部二值化。

4.5 总结

        对于此案例,二值化后直接对图像腐蚀可能会分隔大多数的玉米粒,但是有的总是不能分隔的,使用距离变换找出较明显的特征,在进行腐蚀效果更好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值