OpenCvSharp4.5 编写多线程CircularCaliper找圆心函数 , 输入图像、找圆扇形区域的最小半径和最大半径、找圆扇形中心点、设定扇形区域起始角度、扇形区域结束角度 复制出扇形区域内图像作为找圆分析的图像 输入Caliper个数,宽度、长度、 将每个Caliper区域roi内从整体图像中复制成小图像来分析以提高速度,得到的点坐标转换到整体大图的坐标系中 输入从内到外找圆心、从黑到白找圆 输入canny参数 并行计Caliper区域,将Caliper区域所有canny点合并,拟合圆心 输出圆中心点、半径请编写函数
时间: 2024-02-01 07:14:38 浏览: 116
以下是一个可能的实现,其中使用了OpenCvSharp4.5的一些函数和类:
```C#
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using OpenCvSharp;
public class CircularCaliper
{
private readonly Mat _image;
private readonly int _minRadius;
private readonly int _maxRadius;
private readonly Point2f _center;
private readonly double _startAngle;
private readonly double _endAngle;
private readonly int _caliperCount;
private readonly int _caliperWidth;
private readonly int _caliperLength;
private readonly int _cannyThreshold1;
private readonly int _cannyThreshold2;
private readonly bool _findInnerCircle;
private readonly bool _findBlackToWhite;
public CircularCaliper(Mat image, int minRadius, int maxRadius, Point2f center, double startAngle, double endAngle, int caliperCount, int caliperWidth, int caliperLength, int cannyThreshold1, int cannyThreshold2, bool findInnerCircle, bool findBlackToWhite)
{
_image = image;
_minRadius = minRadius;
_maxRadius = maxRadius;
_center = center;
_startAngle = startAngle;
_endAngle = endAngle;
_caliperCount = caliperCount;
_caliperWidth = caliperWidth;
_caliperLength = caliperLength;
_cannyThreshold1 = cannyThreshold1;
_cannyThreshold2 = cannyThreshold2;
_findInnerCircle = findInnerCircle;
_findBlackToWhite = findBlackToWhite;
}
public (Point2f center, float radius) FindCircleCenter()
{
var caliperAngles = DistributeCaliperAngles();
var cannyPoints = new List<Point>[caliperAngles.Length];
// Parallel loop over caliper angles
Parallel.For(0, caliperAngles.Length, i =>
{
var angle = caliperAngles[i];
var roi = CreateRoi(angle);
var roiImage = new Mat(_image, roi);
var canny = roiImage.Canny(_cannyThreshold1, _cannyThreshold2);
cannyPoints[i] = new List<Point>();
for (var j = 0; j < _caliperCount; j++)
{
var caliper = CreateCaliper(angle, j);
var caliperImage = new Mat(canny, caliper);
var points = new Mat();
Cv2.FindNonZero(caliperImage, points);
foreach (var point in points.ToEnumerable())
{
cannyPoints[i].Add(point + caliper.TopLeft);
}
}
});
// Merge all canny points
var mergedPoints = new List<Point>();
foreach (var points in cannyPoints)
{
mergedPoints.AddRange(points);
}
// Fit a circle to the canny points
var center = new Point2f();
var radius = new float[1];
Cv2.MinEnclosingCircle(mergedPoints.ToArray(), out center, out radius);
// If we're looking for the inner circle, flip the sign of the radius
if (_findInnerCircle)
{
radius[0] *= -1;
}
return (center + _center, radius[0]);
}
private double[] DistributeCaliperAngles()
{
var angles = new double[_caliperCount];
for (var i = 0; i < _caliperCount; i++)
{
var angle = _startAngle + i * (_endAngle - _startAngle) / (_caliperCount - 1);
angles[i] = angle;
}
return angles;
}
private Rect CreateRoi(double angle)
{
var radius = _minRadius + (_maxRadius - _minRadius) * (angle - _startAngle) / (_endAngle - _startAngle);
var size = new Size(_caliperLength, (int)(2 * radius));
var point = new Point((int)(_center.X - radius + 0.5), (int)(_center.Y - radius + 0.5));
return new Rect(point, size);
}
private Rect CreateCaliper(double angle, int index)
{
var radius = _minRadius + (_maxRadius - _minRadius) * (angle - _startAngle) / (_endAngle - _startAngle);
var halfWidth = _caliperWidth / 2.0;
var x = (int)(_center.X + radius * Math.Cos(angle * Math.PI / 180.0) - halfWidth * Math.Sin(angle * Math.PI / 180.0) + 0.5);
var y = (int)(_center.Y + radius * Math.Sin(angle * Math.PI / 180.0) + halfWidth * Math.Cos(angle * Math.PI / 180.0) + 0.5);
var length = (int)(_caliperLength + 2 * halfWidth);
var width = _caliperWidth;
// Flip the caliper if we're looking for a black-to-white transition
if (_findBlackToWhite && index % 2 == 1)
{
angle += 180;
}
var rect = new Rect(x, y, length, width);
// Crop the rect to fit inside the ROI
var roi = CreateRoi(angle);
var intersection = Rect.Intersect(rect, roi);
return new Rect(intersection.Left - x, intersection.Top - y, intersection.Width, intersection.Height);
}
}
```
使用示例:
```C#
var image = new Mat("input.png", ImreadModes.Grayscale);
var center = new Point2f(image.Width / 2.0f, image.Height / 2.0f);
var caliper = new CircularCaliper(image, 50, 150, center, 0, 360, 24, 10, 50, 50, 100, false, false);
var (circleCenter, circleRadius) = caliper.FindCircleCenter();
Console.WriteLine($"Center: ({circleCenter.X}, {circleCenter.Y}), Radius: {circleRadius}");
```
阅读全文