之前做了个检测玉米颗粒的,就是检测细胞个数。原理差不多是下面这个。
/*****************************************************************************************
玉米(或大米)颗粒图像计数系统设计与实现
*****************************************************************************************/
#include
#include
#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>contours; //轮廓
vector hierarchy;//分层
Point zhongdian; //红色灯的中点
findContours(vec_rgb, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));//寻找轮廓
vector> contours_poly(contours.size()); //近似后的轮廓点集
vector boundRect(contours.size()); //包围点集的最小矩形vector
vector center(contours.size()); //包围点集的最小圆形vector
vector 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;
}
/*****************************************************************************************
玉米(或大米)颗粒图像计数系统设计与实现
*****************************************************************************************/
#include
#include
#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;
}