opencv检测细胞个数

之前做了个检测玉米颗粒的,就是检测细胞个数。原理差不多是下面这个。

原理

在这里插入图片描述

opencv3 代码

/*****************************************************************************************
玉米(或大米)颗粒图像计数系统设计与实现
*****************************************************************************************/
#include<opencv2/opencv.hpp>
#include<iostream>
#define PI 3.1415926

using namespace std;
using namespace cv;



//填充
void fillHole(const Mat srcBw, Mat &dstBw)
{
	Size m_Size = srcBw.size();
	Mat Temp = Mat::zeros(m_Size.height + 2, m_Size.width + 2, srcBw.type());//延展图像
	srcBw.copyTo(Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)));

	cv::floodFill(Temp, Point(0, 0), Scalar(255));//填充区域

	Mat cutImg;//裁剪延展的图像
	Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)).copyTo(cutImg);

	dstBw = srcBw | (~cutImg);
}

int main()
{





	Mat srcImg;
	Mat srcImage;

	srcImg = imread("1.jpg");//读取文件

		clock_t start = clock();
		//resize(srcImg, srcImg, Size(200, 200));//重定义图片大小
		namedWindow("原图", 0);
		imshow("原图", srcImg);
		waitKey(1);

		cvtColor(srcImg, srcImage, CV_BGR2GRAY);

	
		srcImage = srcImage >160;//二值化


		Mat vec_rgb = Mat::zeros(srcImage.size(), CV_8UC1);
		medianBlur(srcImage, vec_rgb, 3);//中值滤波
		namedWindow("中值滤波", 0);
		imshow("中值滤波", vec_rgb);
		waitKey(1);


		/// Reduce noise with a kernel 3x3
		//blur(srcImage, vec_rgb, Size(3, 3));

		/// Canny detector
		Canny(vec_rgb, vec_rgb, 3, 9, 3);

	
		namedWindow("边缘检测", 0);
		imshow("边缘检测", vec_rgb);



		Mat element = getStructuringElement(MORPH_ELLIPSE, Size(2 * 1 + 1, 2 * 1 + 1), Point(1, 1));
	//	Mat element1 = getStructuringElement(MORPH_ELLIPSE, Size(2 * 3 + 1, 2 * 3 + 1), Point(3, 3));
	//	dilate(vec_rgb, vec_rgb, element1);//膨胀
	//namedWindow("膨胀", 0);
	//	imshow("膨胀", vec_rgb);
	// 	waitKey(1);


		fillHole(vec_rgb, vec_rgb);//填充
		namedWindow("填充", 0);
		imshow("填充", vec_rgb);
		waitKey(1);

		erode(vec_rgb, vec_rgb, element);//腐蚀
		namedWindow("腐蚀", 0);
		imshow("腐蚀", vec_rgb);
		waitKey(1);
		


	

		vector<vector<Point>>contours; //轮廓
		vector<Vec4i> hierarchy;//分层

		Point  zhongdian; //红色灯的中点

		findContours(vec_rgb, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));//寻找轮廓

		vector<vector<Point>> contours_poly(contours.size());  //近似后的轮廓点集
		vector<Rect> boundRect(contours.size());  //包围点集的最小矩形vector
		vector<Point2f> center(contours.size());  //包围点集的最小圆形vector
		vector<float> radius(contours.size());  //包围点集的最小圆形半径vector
		
		for (int i = 0; i < contours.size(); i++)
		{
			approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true); //对多边形曲线做适当近似,contours_poly[i]是输出的近似点集
			boundRect[i] = boundingRect(Mat(contours_poly[i])); //计算并返回包围轮廓点集的最小矩形
			minEnclosingCircle(contours_poly[i], center[i], radius[i]);//计算并返回包围轮廓点集的最小圆形及其半径


			cout << "玉米(或大米)颗粒坐标" << center[i] << endl;
		}

		Mat drawing = Mat::zeros(vec_rgb.size(), CV_8UC3);
		for (int i = 0; i < contours.size(); i++)
		{
			Scalar color = (0, 0, 255);//蓝色线画轮廓
			drawContours(drawing, contours_poly, i, color, 1, 8, hierarchy, 0, Point());//根据轮廓点集contours_poly和轮廓结构hierarchy画出轮廓
			rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);//画矩形,tl矩形左上角,br右上角
			circle(drawing, center[i], (int)radius[i], color, 2, 8, 0);                                        //画圆形
		}

		/// 显示在一个窗口
		namedWindow("包围最小矩形和圆形", 0);
		imshow("包围最小矩形和圆形", drawing);
		waitKey(1);

		cout << "玉米(或大米)颗粒个数" << contours.size() << endl;


		clock_t ends = clock();
		cout << "Running Time : " << (double)(ends - start) / CLOCKS_PER_SEC << endl;

	waitKey();
	return 0;

}

效果图

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

opencv4 代码

/*****************************************************************************************
玉米(或大米)颗粒图像计数系统设计与实现
*****************************************************************************************/
#include<opencv2/opencv.hpp>
#include<iostream>
#define PI 3.1415926

using namespace std;
using namespace cv;



//填充
void fillHole(const Mat srcBw, Mat &dstBw)
{
	Size m_Size = srcBw.size();
	Mat Temp = Mat::zeros(m_Size.height + 2, m_Size.width + 2, srcBw.type());//延展图像
	srcBw.copyTo(Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)));

	cv::floodFill(Temp, Point(0, 0), Scalar(255));//填充区域

	Mat cutImg;//裁剪延展的图像
	Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)).copyTo(cutImg);

	dstBw = srcBw | (~cutImg);
}

int main()
{

	Mat srcImg;
	Mat srcImage;

	srcImg = imread("1.jpg");//读取文件

	clock_t start = clock();
	//resize(srcImg, srcImg, Size(200, 200));//重定义图片大小
	namedWindow("原图", 0);
	imshow("原图", srcImg);
	waitKey(1);

	cvtColor(srcImg, srcImage, COLOR_BGR2GRAY);


	srcImage = srcImage >160;//二值化


	Mat vec_rgb = Mat::zeros(srcImage.size(), CV_8UC1);
	medianBlur(srcImage, vec_rgb, 3);//中值滤波
	namedWindow("中值滤波", 0);
	imshow("中值滤波", vec_rgb);
	waitKey(1);


	/// Reduce noise with a kernel 3x3
	//blur(srcImage, vec_rgb, Size(3, 3));

	/// Canny detector
	Canny(vec_rgb, vec_rgb, 3, 9, 3);


	namedWindow("边缘检测", 0);
	imshow("边缘检测", vec_rgb);



	Mat element = getStructuringElement(MORPH_ELLIPSE, Size(2 * 1 + 1, 2 * 1 + 1), Point(1, 1));
	//	Mat element1 = getStructuringElement(MORPH_ELLIPSE, Size(2 * 3 + 1, 2 * 3 + 1), Point(3, 3));
	//	dilate(vec_rgb, vec_rgb, element1);//膨胀
	//namedWindow("膨胀", 0);
	//	imshow("膨胀", vec_rgb);
	// 	waitKey(1);


	fillHole(vec_rgb, vec_rgb);//填充
	namedWindow("填充", 0);
	imshow("填充", vec_rgb);
	waitKey(1);

	erode(vec_rgb, vec_rgb, element);//腐蚀
	namedWindow("腐蚀", 0);
	imshow("腐蚀", vec_rgb);
	waitKey(1);





	vector<vector<Point>>contours; //轮廓
	vector<Vec4i> hierarchy;//分层

	Point  zhongdian; //红色灯的中点

	findContours(vec_rgb, contours, hierarchy, RETR_LIST, CHAIN_APPROX_NONE, Point(0, 0));//寻找轮廓

	vector<vector<Point>> contours_poly(contours.size());  //近似后的轮廓点集
	vector<Rect> boundRect(contours.size());  //包围点集的最小矩形vector
	vector<Point2f> center(contours.size());  //包围点集的最小圆形vector
	vector<float> radius(contours.size());  //包围点集的最小圆形半径vector

	for (int i = 0; i < contours.size(); i++)
	{
		approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true); //对多边形曲线做适当近似,contours_poly[i]是输出的近似点集
		boundRect[i] = boundingRect(Mat(contours_poly[i])); //计算并返回包围轮廓点集的最小矩形
		minEnclosingCircle(contours_poly[i], center[i], radius[i]);//计算并返回包围轮廓点集的最小圆形及其半径


		cout << "玉米(或大米)颗粒坐标" << center[i] << endl;
	}

	Mat drawing = Mat::zeros(vec_rgb.size(), CV_8UC3);
	for (int i = 0; i < contours.size(); i++)
	{
		Scalar color = (0, 0, 255);//蓝色线画轮廓
		drawContours(drawing, contours_poly, i, color, 1, 8, hierarchy, 0, Point());//根据轮廓点集contours_poly和轮廓结构hierarchy画出轮廓
		rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);//画矩形,tl矩形左上角,br右上角
		circle(drawing, center[i], (int)radius[i], color, 2, 8, 0);                                        //画圆形
	}

	/// 显示在一个窗口
	namedWindow("包围最小矩形和圆形", 0);
	imshow("包围最小矩形和圆形", drawing);
	waitKey(1);

	cout << "玉米(或大米)颗粒个数" << contours.size() << endl;


	clock_t ends = clock();
	cout << "Running Time : " << (double)(ends - start) / CLOCKS_PER_SEC << endl;

	waitKey();
	return 0;

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

翟羽嚄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值