OPCV数玉米案例
对于我们传统的数玉米,我看了网上的案例,大家都和贾志刚老师描述的一样,
即二值分割+形态学操作+距离变换+连通域计算。但是这个方法的偶然性太多,对于距离变换来说,我们需要不断的调参,换一张图就不适合。按照人眼的思维,还是把一个一个轮廓画出来分割开来更实用,也需要调参,但是相对用距离变换的方法来说,此方法调的参数相对来说少一点。
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>
#include <vector>
#include <format>
using namespace cv;
using namespace std;
Mat src, gray_src, dst,binary;
int t1_value = 50;
int max_value = 255;
const char* OUTPUT_TITLE = "Canny Result";
int main(int argc, char** argv) {
src = imread("./case4.2.png");
if (!src.data) {
printf("could not load image...\n");
return -1;
}
char INPUT_TITLE[] = "input image";
namedWindow(INPUT_TITLE, WINDOW_AUTOSIZE);
namedWindow(OUTPUT_TITLE, WINDOW_AUTOSIZE);
imshow(INPUT_TITLE, src);
//二值化
cvtColor(src, gray_src, COLOR_BGR2GRAY);
threshold(gray_src,binary, 0, 255, THRESH_BINARY | THRESH_TRIANGLE);
//提取轮廓
Mat edge_output;
GaussianBlur(gray_src, gray_src, Size(3, 3), BORDER_DEFAULT);
Canny(gray_src, edge_output, 50, 100, 3, false);//最小阈值与最大阈值,sobel算子
imshow("edge", edge_output);
//形态学操作
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3), Point(-1, -1));
dilate(binary, binary, kernel, Point(-1, -1));
imshow("dilate", binary);
bitwise_or(binary, edge_output, dst);//掩膜运算,将其分割
imshow(OUTPUT_TITLE, dst);
//闭操作,视图片处理具体情况来定
morphologyEx(dst, dst, MORPH_CLOSE, kernel, Point(-1, -1),1);
//寻找轮廓
vector<vector<Point>>contours;
vector<Vec4i> hierarchy;
findContours(dst, contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point());
//绘制轮廓
Mat con = Mat::zeros (src.size(),CV_8UC3);
int count = 0;
for (int t = 0; t < contours.size(); t++) {
double area = contourArea(contours[t]);
Rect rect = boundingRect(contours[t]);
if (area>1000.0&&rect.width<src.rows) {
count++;
drawContours(con, contours, t, Scalar(0, 0, 255), 1, 8, Mat(),0,Point());
cout << "area: " << contourArea(contours[t]) << " ";
cout << "Len: " << arcLength(contours[t],true) << endl;
}
}
imshow("con", con);
cout << count << endl;
waitKey(0);
return 0;
}
原图像
目标图像
利用面积将图片里的小轮廓给过滤掉