OpenCvSharp4.6 编写多线程CircularCaliper找圆心函数 , 输入图像、找圆扇形区域的最小半径和最大半径、找圆扇形中心点、设定扇形区域起始角度、扇形区域结束角度 复制出扇形区域内图像作为找圆分析的图像 输入Caliper个数,宽度、长度、 将每个Caliper区域roi内从整体图像中复制成小图像来分析以提高速度,得到的点坐标转换到整体大图的坐标系中 输入从内到外找圆心、从黑到白找圆 输入canny参数 并行计Caliper区域,将Caliper区域所有canny点合并,拟合圆心 输出圆中心点、半径请编写函数
时间: 2024-02-01 07:14:25 浏览: 81
以下是一个基本的多线程CircularCaliper找圆心的示例代码,你可以根据自己的需求进行修改和优化:
```csharp
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using OpenCvSharp;
using OpenCvSharp.Extensions;
public class CircularCaliper
{
private Mat inputImage;
private int minRadius;
private int maxRadius;
private Point2f center;
private double startAngle;
private double endAngle;
private int caliperCount;
private int caliperWidth;
private int caliperLength;
private bool fromInside;
private int cannyThreshold1;
private int cannyThreshold2;
private double cannyApertureSize;
public CircularCaliper(Mat inputImage, int minRadius, int maxRadius, Point2f center, double startAngle, double endAngle, int caliperCount, int caliperWidth, int caliperLength, bool fromInside, int cannyThreshold1, int cannyThreshold2, double cannyApertureSize)
{
this.inputImage = inputImage;
this.minRadius = minRadius;
this.maxRadius = maxRadius;
this.center = center;
this.startAngle = startAngle;
this.endAngle = endAngle;
this.caliperCount = caliperCount;
this.caliperWidth = caliperWidth;
this.caliperLength = caliperLength;
this.fromInside = fromInside;
this.cannyThreshold1 = cannyThreshold1;
this.cannyThreshold2 = cannyThreshold2;
this.cannyApertureSize = cannyApertureSize;
}
public void FindCircleCenter(out Point2f center, out float radius)
{
center = new Point2f();
radius = 0;
// Step 1: Create circular mask
Mat mask = new Mat(inputImage.Size(), MatType.CV_8UC1, new Scalar(0));
Cv2.Circle(mask, center, maxRadius, new Scalar(255), -1);
Cv2.Circle(mask, center, minRadius, new Scalar(0), -1);
// Step 2: Create caliper ROIs
double angleStep = (endAngle - startAngle) / caliperCount;
ConcurrentBag<Mat> roiList = new ConcurrentBag<Mat>();
Parallel.For(0, caliperCount, i =>
{
double start = startAngle + i * angleStep;
double end = start + angleStep;
if (fromInside)
{
end = start - angleStep;
start = end - angleStep;
}
Point2f startPoint = new Point2f((float)(center.X + minRadius * Math.Cos(start)), (float)(center.Y + minRadius * Math.Sin(start)));
Point2f endPoint = new Point2f((float)(center.X + maxRadius * Math.Cos(end)), (float)(center.Y + maxRadius * Math.Sin(end)));
Point2f lineVector = endPoint - startPoint;
Point2f lineNormal = new Point2f(-lineVector.Y, lineVector.X);
lineNormal *= caliperWidth / (2 * lineNormal.DistanceTo(new Point2f(0, 0)));
Point2f point1 = startPoint + lineNormal;
Point2f point2 = endPoint + lineNormal;
Point2f point3 = endPoint - lineNormal;
Point2f point4 = startPoint - lineNormal;
Mat roi = new Mat();
using (var matrix = Cv2.GetAffineTransform(new[] { point1, point2, point3 }, new[] { new Point2f(0, 0), new Point2f(caliperLength, 0), new Point2f(caliperLength, caliperWidth) }))
{
Cv2.WarpAffine(inputImage, roi, matrix, new Size(caliperLength, caliperWidth), InterpolationFlags.Linear, BorderTypes.Constant, Scalar.Black);
}
roiList.Add(roi);
});
// Step 3: Find Canny edges in each ROI and merge them
Mat allEdges = new Mat(caliperWidth, caliperLength * caliperCount, MatType.CV_8UC1, new Scalar(0));
Parallel.ForEach(roiList, roi =>
{
Mat edges = new Mat();
Cv2.Canny(roi, edges, cannyThreshold1, cannyThreshold2, (int)cannyApertureSize);
edges.CopyTo(allEdges[new Rect(0, 0, caliperLength, caliperWidth)]);
allEdges.Move(new Point(caliperLength, 0), allEdges[new Rect(caliperLength, 0, caliperLength * (caliperCount - 1), caliperWidth)]);
});
// Step 4: Find circle center by fitting a circle to the merged edges
Cv2.HoughCircles(allEdges, out CircleSegment[] circles, HoughMethods.Gradient, 1, caliperWidth, cannyThreshold1, cannyThreshold2, minRadius, maxRadius);
if (circles.Length > 0)
{
center = circles[0].Center + new Point2f(caliperLength * (circles[0].Center.Y > caliperWidth / 2 ? caliperCount - 1 : 0), 0);
radius = circles[0].Radius;
}
}
}
```
你可以使用以下代码来测试这个类:
```csharp
using (var inputImage = new Mat("test.jpg"))
{
var caliper = new CircularCaliper(inputImage, 50, 150, new Point2f(200, 200), 0, 360, 36, 10, 50, true, 50, 150, 3);
caliper.FindCircleCenter(out Point2f center, out float radius);
Cv2.Circle(inputImage, center, (int)radius, new Scalar(0, 0, 255), 2);
Cv2.ImShow("Result", inputImage);
Cv2.WaitKey(0);
}
```
这个示例代码会在输入图像中找到一个半径为50到150的圆,并返回它的圆心和半径。你可以根据自己的需求修改输入参数,例如圆心位置、最小和最大半径、扇形区域起始角度和结束角度、Caliper个数、宽度和长度、从内到外找圆心或从黑到白找圆心等等。
阅读全文