C++ OpenCV图像处理:圆形识别、刻度测量与距离计算
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
using namespace cv;
using namespace std;
int main()
{
Mat img = imread('circle.jpg');
if (img.empty())
{
cout << 'Could not open or find the image' << endl;
return -1;
}
Mat gray;
cvtColor(img, gray, COLOR_BGR2GRAY);
// 阈值化
Mat thresh;
threshold(gray, thresh, 0, 255, THRESH_BINARY_INV + THRESH_OTSU);
// 膨胀操作
Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(5, 5));
dilate(thresh, thresh, kernel);
// 寻找圆形轮廓
vector<vector<Point>> contours;
findContours(thresh, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
// 识别圆形
vector<Point2f> centers;
vector<float> radius;
for (size_t i = 0; i < contours.size(); i++)
{
// 计算轮廓的面积
double area = contourArea(contours[i]);
// 过滤掉面积太小的轮廓
if (area < 100)
continue;
// 拟合圆形
Point2f center;
float r;
minEnclosingCircle(contours[i], center, r);
// 判断圆心是否为黑色
Vec3b color = img.at<Vec3b>(center);
if (color[0] == 0 && color[1] == 0 && color[2] == 0)
{
centers.push_back(center);
radius.push_back(r);
}
}
// 绘制圆形和圆心
for (size_t i = 0; i < centers.size(); i++)
{
circle(img, centers[i], radius[i], Scalar(0, 0, 255), 2);
circle(img, centers[i], 3, Scalar(0, 255, 0), -1);
}
// 计算刻度线的长度
double scale = 0;
for (size_t i = 0; i < centers.size(); i++)
{
for (size_t j = i + 1; j < centers.size(); j++)
{
double dist = norm(centers[i] - centers[j]);
if (dist > scale)
scale = dist;
}
}
scale /= 5;
// 绘制刻度线
for (size_t i = 0; i < centers.size(); i++)
{
for (size_t j = i + 1; j < centers.size(); j++)
{
double dist = norm(centers[i] - centers[j]);
if (dist > scale * 0.9 && dist < scale * 1.1)
{
line(img, centers[i], centers[j], Scalar(255, 0, 0), 2);
double length = dist / scale;
putText(img, to_string(length) + 'cm', (centers[i] + centers[j]) / 2, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(255, 0, 0), 2);
}
}
}
// 计算面积最大的圆的心到其他每一个圆的圆心的距离
double max_area = 0;
Point2f max_center;
for (size_t i = 0; i < centers.size(); i++)
{
double area = CV_PI * pow(radius[i], 2);
if (area > max_area)
{
max_area = area;
max_center = centers[i];
}
}
for (size_t i = 0; i < centers.size(); i++)
{
if (centers[i] != max_center)
{
double dist = norm(max_center - centers[i]) / scale;
line(img, max_center, centers[i], Scalar(0, 255, 255), 2);
putText(img, to_string(dist) + 'cm', (max_center + centers[i]) / 2, FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 255, 255), 2);
}
}
// 输出圆心位置和半径大小
for (size_t i = 0; i < centers.size(); i++)
{
double r = radius[i] / scale;
cout << '圆心位置:' << centers[i] << ' 半径大小:' << r << 'cm' << endl;
}
imshow('Result', img);
waitKey(0);
return 0;
}
原文地址: https://www.cveoy.top/t/topic/jsM6 著作权归作者所有。请勿转载和采集!