图像处理------用于计算图像中某元素的个数
工具:deepin linux opencv3.2.0
我是用来帮人计算细菌菌落的个数,感觉有用发出来一起学习交流。具体使用过程见代码注释。
下面代码实现的是批量读取某文件夹下面的一组图片,然后对其某个特定的颜色进行识别,对个数做统计。
并且还可以对目标的面积做筛选,大于一定值的或者小于一定值的剔除。然后把结果自动保存到指定的文件夹下面。
保存格式为图片名称+统计个数。
对于做实验数据统计十分有帮助。当然,有问题可以联系博主,下方留言,第一时间回答您的问题 QAQ。
make文件如下:
FLAG =-L ./lib/ -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_videoio -lopencv_imgcodecs -lm -Wall
edit: main.o
g++ $(FLAG) -g -o edit main.o
main.o: main.cpp
g++ -c main.cpp
clean:
rm -f main.o
代码:
/**************************
菌落个数计算 ------opencv
********用法*********
在outfile.open()和string dir_path()
这俩函数的参数中分别加上你的结果储存路径和
你的将要被处理的图片路径运行即可。
***************************/
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
#include <unistd.h>
#include <fstream>
using namespace cv;
using namespace std;
int hmin = 0;
int hmin_Max = 180;
int hmax = 180;
int hmax_Max = 180;
//饱和度
int smin = 41;
int smin_Max = 255;
int smax = 47;
int smax_Max = 255;
//亮度
int vmin = 204;
int vmin_Max = 255;
int vmax = 255;
int vmax_Max = 255;
/**********************************
上面的变量是用来调整hsv阈值的
**********************************/
int cnt=0; //定义全局变量记录每次得到的轮廓个数
int err=0; //记录大菌落的总个数
int sum_jun; //所有的菌落的和
int main()
{
ofstream outfile; //创建一个文件操作类
outfile.open("/home/wwk/Desktop/result/4.22/result.txt"); //打开此目录下的txt文档,没有的话,则自动创建一个,不需要用户手创建
string dir_path = "/home/wwk/Desktop/4.22/*.jpg"; //图像存放路经。!!注意是文件夹,不是某个文件,用于批量读取
vector<String> fileNames;
glob(dir_path, fileNames); // 所有文件以具体路径方式,保存在video_list内
for (int i = 0; i < fileNames.size(); i++) //自动遍历文件夹下的每一张图片
{
Mat image;
Mat HSVimage;
Mat hsv_1Image;
image=imread(fileNames[i]);
//namedWindow("image",0);
//imshow("image", image);
cvtColor(image, HSVimage, CV_BGR2HSV);
inRange(HSVimage, Scalar(hmin, smin, vmin), Scalar(hmax, smax, vmax), hsv_1Image); //hsv颜色空间转化,通道分离。
/******************************************************
这是滑动条创建。可以用来动态调节你目标的hsv,利于目标和环境的区分,使用的时候请给整个程序加死循环,调节完成后取消,不然滑动条不起作用
******************************************************/
namedWindow("dst", WINDOW_GUI_EXPANDED);
//调节色相 H
createTrackbar("hmin", "dst", &hmin, hmin_Max);
createTrackbar("hmax", "dst", &hmax, hmax_Max);
//调节饱和度 S
createTrackbar("smin", "dst", &smin, smin_Max);
createTrackbar("smax", "dst", &smax, smax_Max);
//调节亮度
createTrackbar("vmin", "dst", &vmin, vmin_Max);
createTrackbar("vmax", "dst", &vmax, vmax_Max);
//namedWindow("image_3",0);
//imshow("image_3", hsv_1Image);
Mat element = getStructuringElement(MORPH_RECT, Size(9, 9));
//morphologyEx(hsv_1Image, hsv_1Image, MORPH_CLOSE, element);
morphologyEx(hsv_1Image, hsv_1Image, MORPH_DILATE, element); // 开运算后做膨胀操作
//namedWindow("DILATE",0);
//imshow("DILATE", hsv_1Image);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(hsv_1Image, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point(0, 0));
//第四个参数用于检测轮廓类型 ,可以自己搜索资料,这里,只检测外围轮廓
//第五个参数是轮廓相对于原始坐标的偏移量;很重要。
cnt=(int)contours.size(); //这里给count赋值,记录所有检测到的轮廓
for( int i = 0; i < contours.size(); i++ )
{
double ConArea = fabs(contourArea(contours[i], true));
//cout << "面" << i << "轮廓的面积为:" << ConArea << endl; ///计算面积
}
vector <vector<Point>>::iterator iter = contours.begin();
for (; iter != contours.end();)
{
double g_dConArea = fabs(contourArea(*iter)); //对目标进行筛选
if (g_dConArea>800)
{
iter = contours.erase(iter);
}
else
{
++iter;
}
}
// cout << "【筛选后总共轮廓个数为:" << (int)contours.size() << endl;
err=cnt-(int)contours.size(); //筛选后的轮廓数
cnt=(int)contours.size();
vector<Moments> mu(contours.size());
for (int i = 0; i < contours.size(); i++)
{
mu[i] = moments(contours[i], false);
}
//ŒÆËãÂÖÀªµÄÖÊÐÄ
vector<Point2f> mc(contours.size());
for (int i = 0; i < contours.size(); i++)
{
mc[i] = Point2d(mu[i].m10 / mu[i].m00, mu[i].m01 / mu[i].m00);
}
//计算中心距
Mat drawing = Mat::zeros(hsv_1Image.size(), CV_8UC3);
for (int i = 0; i < contours.size(); i++)
{
Scalar color = Scalar(255, 0, 0); //颜色通道赋值
drawContours(drawing, contours, i, color, 2, 8, hierarchy, 0, Point()); //绘制轮廓
circle( drawing, mc[i], 20, Scalar( 0, 0, 255), 2 );
}
sum_jun=err*10+cnt; //面积大于
cout<<sum_jun<<endl;
// namedWindow("result",0);
//imshow("result", drawing);
usleep(500);
cout<<"***********第"<<i<<"张读取完毕**********"<<endl;
cout<<"正在写入文件......"<<endl;
outfile<<fileNames[i]<<":"<<sum_jun << endl; //写入数据到txt文本
}
outfile.close(); //关闭txt文本
return 0;
}