基于OpenCV的圆形孔检测与尺寸测量
基于OpenCV的圆形孔检测与尺寸测量
本文介绍如何使用OpenCV库编写程序,实现对图像中圆形孔的自动检测,并计算孔的数量、孔径以及外围孔圆心组成的圆的直径等尺寸信息。
代码示例:
#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>
#include <cmath>
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<Point>* points = (vector<Point>*)param;
points->push_back(Point(x, y));
}
}
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;
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);
int diameter = 2 * radius;
double diameter_mm = diameter / pixel_to_mm_ratio;
cout << '孔径: ' << diameter_mm << endl;
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 << endl;
}
// 显示结果
namedWindow('Circle detection');
imshow('Circle detection', img);
waitKey(0);
destroyAllWindows();
return 0;
}
程序说明:
该程序实现了以下功能:
- 读取图像并预处理: 读取输入图像,并将其转换为HSV颜色空间,以便进行颜色分割。
- 提取红色区域: 定义红色范围,使用
inRange函数获取红色区域的掩码,并存储红色像素点的坐标。 - 统计红色区块: 根据红色像素点的距离,将它们分组为不同的红色区块,并计算每个区块的大小和距离最近区块的距离。
- 图像预处理: 将原始图像转换为灰度图像,进行高斯滤波去噪,并使用形态学操作(闭运算)连接断开的边缘。
- 边缘检测: 使用Canny算子进行边缘检测,提取图像中的边缘信息。
- 计算像素当量: 根据红色区块之间的距离和实际距离,计算出像素当量,即每个像素代表的实际长度。
- 霍夫圆变换: 使用
HoughCircles函数进行霍夫圆变换,检测图像中的圆形孔。 - 计算尺寸信息: 计算检测到的圆的数量、每个圆的直径(孔径)以及外围孔圆心组成的圆的直径。
- 结果输出: 在图像中绘制检测到的圆,并输出计算得到的尺寸信息。
注意事项:
- 程序中的某些参数(例如红色范围、霍夫圆变换的参数)可能需要根据实际情况进行调整。
- 该程序假设图像中存在红色标记,用于计算像素当量。如果图像中没有红色标记,则需要使用其他方法来确定像素当量。
总结:
本文介绍了如何使用OpenCV库编写程序,实现对图像中圆形孔的自动检测和尺寸测量。该程序可以应用于各种需要进行圆形目标检测和测量的场景,例如工业自动化、医学影像分析等。
原文地址: https://www.cveoy.top/t/topic/jxMa 著作权归作者所有。请勿转载和采集!