关于OpenCV3使用距离变换的应用C++实现DEMO-数玉米粒个数
过程效果图
软件环境
VS2015,OpenCV341,C++
代码实现
#include<iostream>
#include<opencv2/opencv.hpp>
#include<math.h>
using namespace std;
using namespace cv;
int main(int argc, char** argv) {
//1.读取图,灰度图
Mat src = imread("G:\\opencv_trainning\\vs2015\\3\\statistical_count\\1.jpg",IMREAD_GRAYSCALE);
//判空
if (src.empty()) {
cout << "open fault" << endl;
return -1;
}
//显示
namedWindow("src");
imshow("src",src);
//2.二值化分割-获得白底黑字图
Mat dst;//灰度图
//参数:(原图,目标图,阈值,最大值,阈值标记)
threshold(src, dst, 100, 255,THRESH_BINARY|THRESH_TRIANGLE);//使用三角阈值,单峰
imshow("first",dst);
//3.形态学处理-膨胀去掉外围干扰
Mat element = getStructuringElement(MORPH_RECT,Size(3,3),Point(-1,-1));//定义结构元素,参数:(形状,核尺寸,锚点)
dilate(dst,dst,element);//膨胀,参数:(原图,目标图,结构元素变量)
imshow("second", dst);
//4.距离变换-获得距离高亮(黑底白字)->归一化
Mat dist;//
bitwise_not(dst,dst,Mat());//反色处理,黑底白字,参数:(原图,目标图,掩码)
distanceTransform(dst,dst,CV_DIST_L2,3);//距离变换,参数:(原图,目标图,距离变换类型,掩码(核)尺寸)
normalize(dst,dst,0,1.0,NORM_MINMAX);//归一化,参数:(原图,目标图,最小值,最大值,归一化类型)
imshow("third", dst);
//5.局部阈值--局部阈值得到分离的每个物体,回到0-255的图片上来
threshold(dst,dst,0.6,1.0,THRESH_BINARY);//再次二值分割,参数:(原图,目标图,阈值,最大值,阈值类型)
normalize(dst,dst,0,255,NORM_MINMAX);//归一化到0-255数据区间,参数:(原图,目标图,最小值,最大值,归一化类型)
Mat dst_8u;//定义8u变量
dst.convertTo(dst_8u,CV_8U);//转化到新图中
//参数:(原图,目标图,最大值,自适应方法(Gaussian/Mean),阈值类型,块尺寸,常量值),常量值给0即可,给正相当于反色效果
adaptiveThreshold(dst_8u,dst_8u,255,ADAPTIVE_THRESH_GAUSSIAN_C,THRESH_BINARY,85,0.0);//85位置给奇数,取图的1/4或1/6
//6.形态学操作-膨胀,使局部变大,白色部分单体连接为一个整体
dilate(dst_8u,dst_8u,element,Point(-1,-1),2);//参数:(原图,目标图,结构元素,锚点,迭代次数)
imshow("fourth", dst_8u);
//7.发现轮廓-获取轮廓信息
vector<vector<Point>> contours;//定义轮廓点向量的向量
vector<Vec4i> hierarchy;//定义拓扑结构向量
//参数:(二值化图,轮廓向量的向量,发现方法,检测方法),此处发现方法使用RETR_EXTERNAL,只发现最外层的轮廓
findContours(dst_8u, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
//画轮廓
Mat resultImg = Mat::zeros(src.size(),CV_8UC3);//创建结果图
RNG rng(123456);//定义随机颜色变量
for (int i = 0; i < contours.size(); i++) {//循环轮廓
//画轮廓,参数:(图,轮廓点向量的向量,位置id,颜色,线宽),线宽为-1表示整体填充颜色
drawContours(resultImg, contours, i, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), -1);
}
//8.统计计数
char str[100] = {0};//定义字符串数组
sprintf_s(str,"count=%d",contours.size());//打印轮廓个数
//放文本到图片,参数:(图,字符串,原点,字体,尺度值,颜色),其他参数默认
putText(resultImg,str,Point(10,30),FONT_HERSHEY_COMPLEX,1.0,Scalar(255,0,0));
imshow("resultImg", resultImg);
//显示
waitKey(0);//按键等待
return 0;
}
实现思路
1.灰度图:获得灰度图;
2.三角阈值二值化:获得白底黑字图;
3.图形学-膨胀:去掉外围小干扰;
4.反色、距离变换及归一化:获得黑底白字图后,再获得距离图,归一化(0~1)后得到统一数据范围;
5.局部阈值:二值化并更改数据为0~255;
6.形态学操作-膨胀,使局部变大,白色部分单体连接为一个整体;
7.发现轮廓:获得所有独立轮廓向量;
8.统计计数:获得轮廓个数;
我是Simon,在这里期待与您的交流。