#include #include <opencv2/opencv.hpp> #include #include #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* points = (vector*)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;

    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;

}

OpenCV C++ 实现图像中圆孔识别与测量

原文地址: https://www.cveoy.top/t/topic/jxNq 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录