OpenCvSharp 编写多线程CircularCaliper找圆心函数 , 输入图像、找圆扇形区域的最小半径和最大半径、找圆扇形中心点、设定扇形区域起始角度、扇形区域结束角度 输入Caliper个数,宽度、长度、 输入从内到外找圆心、从黑到白找圆 输入canny参数 并行计Caliper区域,将Caliper区域所有canny点合并,拟合圆心 输出圆中心点、半径请编写函数
时间: 2023-07-10 08:07:27 浏览: 70
下面是一个使用OpenCvSharp编写多线程CircularCaliper找圆心函数的示例代码:
```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using OpenCvSharp;
public class CircularCaliperFinder
{
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 bool _innerToOuter;
private readonly bool _blackToWhite;
private readonly double _cannyThreshold1;
private readonly double _cannyThreshold2;
public CircularCaliperFinder(Mat image, int minRadius, int maxRadius, Point2f center, double startAngle, double endAngle,
int caliperCount, int caliperWidth, int caliperLength, bool innerToOuter, bool blackToWhite, double cannyThreshold1, double cannyThreshold2)
{
_image = image;
_minRadius = minRadius;
_maxRadius = maxRadius;
_center = center;
_startAngle = startAngle;
_endAngle = endAngle;
_caliperCount = caliperCount;
_caliperWidth = caliperWidth;
_caliperLength = caliperLength;
_innerToOuter = innerToOuter;
_blackToWhite = blackToWhite;
_cannyThreshold1 = cannyThreshold1;
_cannyThreshold2 = cannyThreshold2;
}
public (Point2f center, float radius) FindCircleCenter()
{
var caliperList = GetCaliperList();
var cannyPoints = GetCannyPoints(caliperList);
var circle = Cv2.MinEnclosingCircle(cannyPoints);
return (circle.Center, circle.Radius);
}
private List<Caliper> GetCaliperList()
{
var caliperList = new List<Caliper>();
var angleStep = (_endAngle - _startAngle) / (_caliperCount - 1);
for (var i = 0; i < _caliperCount; i++)
{
var angle = _startAngle + i * angleStep;
var caliper = new Caliper(_image, _center, angle, _minRadius, _maxRadius, _caliperWidth, _caliperLength, _innerToOuter);
caliperList.Add(caliper);
}
Parallel.ForEach(caliperList, caliper => caliper.FindEdge(_blackToWhite));
return caliperList;
}
private static Vec2i[] GetCannyPoints(IEnumerable<Caliper> caliperList)
{
var pointList = new List<Vec2i>();
foreach (var caliper in caliperList)
{
pointList.AddRange(caliper.CannyPoints);
}
return pointList.ToArray();
}
}
public class Caliper
{
private readonly Mat _image;
private readonly Point2f _center;
private readonly double _angle;
private readonly int _minRadius;
private readonly int _maxRadius;
private readonly int _width;
private readonly int _length;
private readonly bool _innerToOuter;
public Caliper(Mat image, Point2f center, double angle, int minRadius, int maxRadius, int width, int length, bool innerToOuter)
{
_image = image;
_center = center;
_angle = angle;
_minRadius = minRadius;
_maxRadius = maxRadius;
_width = width;
_length = length;
_innerToOuter = innerToOuter;
}
public Vec2i[] CannyPoints { get; private set; }
public void FindEdge(bool blackToWhite)
{
var radius = _minRadius;
var direction = _innerToOuter ? -1 : 1;
while (radius <= _maxRadius)
{
var p1 = new Point((int)(_center.X + radius * Math.Cos(_angle)), (int)(_center.Y + radius * Math.Sin(_angle)));
var p2 = new Point((int)(_center.X + (radius + _length) * Math.Cos(_angle)), (int)(_center.Y + (radius + _length) * Math.Sin(_angle)));
var line = _image.GetLineIterator(p1, p2);
var edgeFound = false;
var cannyList = new List<Vec2i>();
for (var i = 0; i < line.Count; i++)
{
var intensity = _image.At<byte>(line.Pos(i));
if ((blackToWhite && intensity < 128) || (!blackToWhite && intensity > 128))
{
if (!edgeFound)
{
edgeFound = true;
cannyList.Clear();
}
cannyList.Add(line.Pos(i));
}
else if (edgeFound)
{
break;
}
}
if (cannyList.Count > 0)
{
CannyPoints = cannyList.ToArray();
return;
}
radius += direction * _width;
}
CannyPoints = Array.Empty<Vec2i>();
}
}
```
这个类的构造函数接受许多参数,包括输入图像、最小和最大半径、圆心、扇形区域的起始和结束角度、Caliper个数、宽度和长度、从内到外或从外到内查找圆心、从黑到白或从白到黑查找边缘以及Canny参数。
在FindCircleCenter方法中,我们首先获取Caliper列表,然后获取所有的Canny点,最后使用OpenCV的MinEnclosingCircle函数拟合圆心并返回结果。GetCaliperList方法并行计算每个Caliper的边缘,而GetCannyPoints方法将所有Caliper的Canny点合并成一个数组。
Caliper类表示一个Caliper对象,其中包含计算其边缘的FindEdge方法。该方法以内向或外向的方向逐渐增加半径,并在每个半径上找到Caliper宽度内的第一个边缘。如果从黑到白或从白到黑的边缘被找到,则该函数将该边缘的所有Canny点保存在CannyPoints属性中。如果没有找到边缘,则该属性将设置为空数组。
请注意,这只是示例代码,您可能需要进行调整以适应您的具体需求。
阅读全文