opencv —— 重叠对象计数案例实践
4 人赞同了该文章
在图像中特征物体计数的需求中,可先对图像进行阈值分割 ,根据图像效果,可适当使用形态学操作来优化图像效果。如果在某一个光照环境下,物体表面的反光度不一样,导致图像中特征物体间的轮廓边界不明显,则可以通过距离变换函数distanceTransform(),勾勒出大致的骨架,注意需要规范(归一)化操作。提取出对应物体的大致连通区域 ,最后可通过形态学操作来分离特征,达到能计数的图像效果,通过查找轮廓就可以得到所需数据。
示例: 计算玉米的个数
源码:
#include "stdafx.h"
#include <opencv2/highgui/highgui_c.h>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
//#include <algorithm>
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat img;
img = imread("E:\\homework\\4\\test_opencv2\\yumi.png");
if (img.empty())
{
cout << "null" << endl;
return 0;
}
Mat imgGray;
cvtColor(img, imgGray, COLOR_RGB2GRAY);
imshow("img", img);
// 阈值分割
Mat imgTraiangle;
threshold(imgGray, imgTraiangle, 0, 255, THRESH_BINARY | THRESH_TRIANGLE);
imshow("imgTraiangle", imgTraiangle);
图像膨胀
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
Mat imgDilate;
dilate(imgTraiangle, imgDilate, kernel, Point(-1, -1),2);
//imshow("imgDilate", imgDilate);
// 距离变换,把这个大概的骨架给它整出来
Mat imgDist;
bitwise_not(imgTraiangle, imgDilate);
distanceTransform(imgDilate, imgDist, CV_DIST_L2, 3);
normalize(imgDist, imgDist, 0, 255, NORM_MINMAX);
Mat imgdst_8u;
imgDist.convertTo(imgdst_8u, CV_8U);
imshow("imgdst_8u", imgdst_8u);
// 通过阈值分割,生成区域
Mat imgThreld;
adaptiveThreshold(imgdst_8u, imgThreld, 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 105, 0);
imshow("imgthreld", imgThreld);
// 生成的区域,用腐蚀操作,分离连通区域
Mat imgErode;
Mat kernelErode = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
erode(imgThreld, imgErode, kernelErode, Point(-1, -1), 5);
imshow("imgErode", imgErode);
// 计数
vector<vector<Point>> contours;
vector<Vec4i> hieray;
findContours(imgErode, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point(-1, -1));
Mat draw = Mat::zeros(img.size(), CV_8UC3);
RNG rgb(12345);
for (int i = 0; i < contours.size(); i++)
{
drawContours(draw, contours, static_cast<int>(i), Scalar(rgb.uniform(0, 255), rgb.uniform(0, 255), rgb.uniform(0, 255)), 1, 8, hieray);
}
cout << "玉米数目 = " << contours.size() << endl;
imshow("draw", draw);
waitKey(0);
return 1;
}
输出结果:
编辑于 2022-11-12 23:33
・IP 属地江苏
赞同 4
添加评论
喜欢
收藏
申请转载
分享
赞同 4