对象计数

一.问题描述
农业领域经常需要计算对象个数或者在其他领域进行拍照自动计数,可以提高效率,降低成本。
二.解决思路
二值分割+形态学处理+距离变换+连通区域计算
程序的思路:(对照运行结果理解)
【1】源图像载入
【2】首先将源图像进行二值化操作
【3】进行形态学膨胀操作,通过将高亮区域变大,使得原本紧挨着的各个计数对象变小一点(背景是白色,对象是黑色)
【4】通过距离变换,进行粘连物体的分离
【5】进行自定义阈值操作,即消除距离变换后连接各个计数区域的细线
【6】再次进行形态学膨胀操作,将将高亮区域变大,使得原本紧挨着的各个计数对象变大一点(因为用了取反操作,此时背景是黑色,对象是白色)
【7】为了美观,将各个计数区域进行上色处理
三.参考的博客
https://www.cnblogs.com/long5683/p/9750219.html

OpenCV之bitwise_and、bitwise_not等图像基本运算及掩膜
https://blog.csdn.net/u011028345/article/details/77278467

API:自适应阈值化操作:adaptiveThreshold()函数
https://www.cnblogs.com/GaloisY/p/11037350.html

API:OpenCV距离变换函数:distanceTransform()介绍
https://blog.csdn.net/liubing8609/article/details/78483667

四.源程序

#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
using namespace std;

int main(int argc, char** argv)
{
	Mat src = imread("E:\\pictures\\45.png");
 	//medianBlur(src, src,5);//中值滤波,去除椒盐噪声
 	imshow("【1】原图", src);

	Mat src_gray, binary;
 	cvtColor(src, src_gray, COLOR_BGR2GRAY);

	threshold(src_gray, binary, 0, 255, THRESH_BINARY | THRESH_TRIANGLE);//颜色单一时,使用THRESH_TRIANGLE比OTSU好
 	imshow("【2】二值化后", binary);

	//形态学操作
 	Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
 	//膨胀操作,对图像中的高亮部分进行膨胀,拥有比原图更大的高亮区域
 	dilate(binary, binary, kernel, Point(-1, -1), 4);
 	imshow("【3】膨胀后", binary);

	//距离变换
 	Mat dist;
 	bitwise_not(binary, binary);//取反
 	distanceTransform(binary, dist, DIST_L2, 3);
 	normalize(dist, dist, 0, 1.0, NORM_MINMAX);  //矩阵归一化
 	imshow("【4】距离变换后", dist);

	//阈值化二值分割
 	//threshold(dist, dist,0.7,1.0,THRESH_BINARY);//对距离进行筛选,去除边缘部分
 	//normalize(dist, dist, 0, 255, NORM_MINMAX);
 	Mat dist_8U;
 	dist.convertTo(dist_8U, CV_8U); //图像类型转换
 	// 高斯阈值 85  必须是奇数
 	adaptiveThreshold(dist_8U, dist_8U, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 85, 0.0);//自适应阈值,代替上面的阈值操作
 	//形态学操作,使得断开部分连接
 	imshow("【5】自适应阈值后", dist_8U);

	kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
 	dilate(dist_8U, dist_8U, kernel, Point(-1, -1), 3);
 	imshow("【6】形态学操作后", dist_8U);

	// 连通区域计数
 	vector<vector<Point>> contours;
 	findContours(dist_8U, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

	// 效果显示
 	Mat markers = Mat::zeros(src.size(), CV_8UC3);
 	RNG rng(12345);
 	for (size_t t = 0; t < contours.size(); t++) 
 	{
 		//对不同的区域进行上色
 		drawContours(markers, contours, static_cast<int>(t), Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)),-1, 8, Mat());
 	}

	printf("number of corns : %d", contours.size());
 	imshow("【7】效果图", markers);

	waitKey(0);
 	return 0;
}

运行结果:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

发布了25 篇原创文章 · 获赞 0 · 访问量 448

猜你喜欢

转载自blog.csdn.net/qq_45445740/article/details/103688809