OpenCV C++ 实现图像中圆孔识别与测量
#include
using namespace cv; using namespace std;
static void mouse_callback(int event, int x, int y, int flags, void* param)
{
if (event == EVENT_LBUTTONDOWN)
{
vector
int main() { Mat image = imread('1.jpg'); // 读取图片 if (image.empty()) { cout << 'Could not open or find the image' << endl; return -1; }
Mat hsv;
cvtColor(image, hsv, COLOR_BGR2HSV); // 转换为HSV颜色空间
// 定义红色范围
Scalar lower_red = Scalar(0, 100, 100);
Scalar upper_red = Scalar(10, 255, 255);
Scalar lower_red2 = Scalar(160, 100, 100);
Scalar upper_red2 = Scalar(179, 255, 255);
Mat mask1, mask2, mask;
inRange(hsv, lower_red, upper_red, mask1); // 获取红色区域掩码
inRange(hsv, lower_red2, upper_red2, mask2);
bitwise_or(mask1, mask2, mask);
vector<Point> red_pixels; // 存储红色像素点坐标
for (int i = 0; i < mask.rows; i++)
{
for (int j = 0; j < mask.cols; j++)
{
if (mask.at<uchar>(i, j) > 0) // 判断是否为红色像素点
{
red_pixels.push_back(Point(j, i)); // 存储红色像素点坐标
}
}
}
// 统计红色区块数量
vector<vector<Point>> red_blocks; // 存储红色区块
for (int i = 0; i < red_pixels.size(); i++)
{
bool found = false;
for (int j = 0; j < red_blocks.size(); j++)
{
// 判断当前像素点是否属于某个已有的红色区块
if (norm(red_pixels[i] - red_blocks[j][0]) < 50) // 假设红色区块之间的距离小于50个像素
{
red_blocks[j].push_back(red_pixels[i]);
found = true;
break;
}
}
if (!found) // 如果当前像素点不属于任何已有的红色区块,则新建一个红色区块
{
red_blocks.push_back(vector<Point>{red_pixels[i]});
}
}
double average_pixel_distance_between_red;
// 输出每个红色区块和距离最近的红色区块之间距离的平均值
for (int i = 0; i < red_blocks.size(); i++)
{
cout << 'Red block ' << i + 1 << ' has ' << red_blocks[i].size() << ' pixels' << endl;
double min_dist = DBL_MAX;
for (int j = 0; j < red_blocks.size(); j++)
{
if (i != j)
{
double dist = norm(red_blocks[i][0] - red_blocks[j][0]);
if (dist < min_dist)
{
min_dist = dist;
}
}
}
cout << 'Distance to nearest red block: ' << min_dist << ' pixels' << endl;
average_pixel_distance_between_red = min_dist;
}
//cout << average_pixel_distance_between_red << endl;
// 加载图像并将其转换为灰度图像
Mat img = imread('1.jpg');
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
//imshow('Gray Image', gray);
//waitKey(0);
// 使用高斯滤波器对图像进行平滑处理
Mat blur;
GaussianBlur(gray, blur, Size(5, 5), 0);
//imshow('Blurred Image', blur);
//waitKey(0);
// 对图像进行形态学操作
Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5));
Mat closing;
morphologyEx(blur, closing, MORPH_CLOSE, kernel);
//imshow('closing', closing);
//waitKey(0);
// 对图像进行边缘检测
Mat edges;
Canny(closing, edges, 10, 50);
//imshow('Edges', edges);
waitKey(0);
// 计算像素当量
double pixel_to_mm_ratio = average_pixel_distance_between_red / 10; // 10 mm
double pixel_equivalent = 1 / pixel_to_mm_ratio;
cout << '像素当量为1像素对应 ' << pixel_equivalent << endl;
// 应用Hough圆变换算法,以检测图像中的圆形
vector<Vec3f> circles;
HoughCircles(edges, circles, HOUGH_GRADIENT, 1, 20, 10, 24, 20, 100);
Mat output = gray.clone();
cvtColor(output, output, COLOR_GRAY2BGR);
for (size_t i = 0; i < circles.size(); i++) {
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
circle(output, center, radius, Scalar(0, 0, 255), 2, LINE_AA);
}
imshow('Output', output);
// 计算检测到的圆的数量
if (!circles.empty())
{
int num_circles = circles.size();
cout << '孔的数量: ' << num_circles << endl;
vector<double> diameters;
vector<Point2f> centers;
for (size_t i = 0; i < circles.size(); i++)
{
int radius = cvRound(circles[i][2]);
int diameter = 2 * radius;
double diameter_mm = diameter / pixel_to_mm_ratio;
diameters.push_back(diameter_mm);
centers.push_back(Point2f(cvRound(circles[i][0]), cvRound(circles[i][1])));
}
// 对圆直径进行排序
sort(diameters.begin(), diameters.end());
// 计算并输出前6个圆的圆心距离
if (diameters.size() >= 6)
{
for (size_t i = 0; i < 6; i++)
{
double min_dist = DBL_MAX;
for (size_t j = 0; j < 6; j++)
{
if (i != j)
{
double dist = norm(centers[i] - centers[j]);
if (dist < min_dist)
{
min_dist = dist;
}
}
}
cout << '直径排序前6的圆中,圆 ' << i + 1 << ' 到其他圆心的最短距离: ' << min_dist / pixel_to_mm_ratio << ' mm' << endl;
}
}
double max_distance = 0;
for (size_t i = 0; i < circles.size(); i++)
{
Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
int radius = cvRound(circles[i][2]);
circle(img, center, radius, Scalar(0, 255, 0), 2);
for (size_t j = i + 1; j < circles.size(); j++)
{
Point center2(cvRound(circles[j][0]), cvRound(circles[j][1]));
double distance = sqrt(pow(center.x - center2.x, 2) + pow(center.y - center2.y, 2));
max_distance = max(max_distance, distance);
}
}
double max_distance_mm = max_distance / pixel_to_mm_ratio;
cout << '外围孔圆心组成的圆的直径: ' << max_distance_mm << ' mm' << endl;
}
// 显示结果
namedWindow('Circle detection');
imshow('Circle detection', img);
waitKey(0);
destroyAllWindows();
return 0;
}
原文地址: https://www.cveoy.top/t/topic/jxNq 著作权归作者所有。请勿转载和采集!