效果如下:
根据轮廓面积筛除了大轮廓和很小的轮廓,大家可以用其它方法实现自己想要的效果
#include <iostream> #include <opencv2/opencv.hpp> #include <vector> #include <string> using namespace cv; using namespace std; int main() { // 图像路径 std::string path = "/test_image/test.png"; // 提取文件名 // 1.查找最后一个斜杠的位置 size_t lastSlash = path.find_last_of('/'); // 2.查找文件名开始的位置 size_t start = lastSlash != std::string::npos ? lastSlash + 1 : 0; // 3.查找文件名结束的位置 size_t end = path.find_last_of('.'); // 4.完成文件名提取 std::string filename = path.substr(start, end - start); Mat image = imread(path, IMREAD_GRAYSCALE); if (image.empty()) { cout << "无法读取图像文件" << endl; return -1; } // 二值化图像 Mat binary; Mat colorImage; Mat colorImageBinary; threshold(image, binary, 240, 255, THRESH_BINARY); imshow("binary_image", binary); // 查找轮廓 vector<vector<Point>> contours; findContours(binary, contours, RETR_LIST, CHAIN_APPROX_SIMPLE); vector<Point> centerPoints; // 提取轮廓的中心点 for (size_t i = 0; i < contours.size(); i++) { double area_i = cv::contourArea(contours[i], false); if (area_i > 500 || area_i < 20) { continue; } // double area1 = cv::contourArea(contours[i]); // cout << "第" << i << "轮廓面积=" << area1 << endl; // 计算轮廓的矩 Moments moments = cv::moments(contours[i]); // 计算轮廓的中心点 Point center(moments.m10 / moments.m00, moments.m01 / moments.m00); centerPoints.push_back(center); } // 创建彩色图像,否则Scalar()函数只能描述灰度信息 cvtColor(image, colorImage, COLOR_GRAY2BGR); cvtColor(binary, colorImageBinary, COLOR_GRAY2BGR); for (size_t i = 0; i < centerPoints.size(); i++) { // 在图像上绘制中心点 circle(colorImage, centerPoints[i], 1, Scalar(0, 0, 255), -1); circle(colorImageBinary, centerPoints[i], 1, Scalar(0, 0, 255), -1); } // 显示结果 std::string image_name1 = filename + "_result1.png"; std::string image_name2 = filename + "_result2.png"; imshow("Contours1", colorImage); imshow("Contours2", colorImageBinary); imwrite(image_name1, colorImage); imwrite(image_name2, colorImageBinary); waitKey(0); return 0; }