OpenCvSharp 编写多线程CircularCaliper找圆心函数 , 输入图像、找圆扇形区域的最小半径和最大半径、找圆扇形中心点、设定扇形区域起始角度、扇形区域结束角度 先剪出找圆扇形区域图像 输入Caliper个数,宽度、长度、 输入从内到外找圆心、从黑到白找圆 并行计Caliper区域 中心圆可设定请编写函数
时间: 2023-07-10 11:07:24 浏览: 131
以下是一个使用OpenCvSharp编写的多线程CircularCaliper找圆心函数的示例代码:
```csharp
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using OpenCvSharp;
public static class CircleDetector
{
public static Point2f FindCircleCenter(Mat image, float minRadius, float maxRadius, Point2f center, float startAngle, float endAngle, int caliperCount, int caliperWidth, int caliperLength, bool fromInside, bool fromBlackToWhite)
{
// Crop the circular region
Rect roi = new Rect((int)(center.X - maxRadius), (int)(center.Y - maxRadius), (int)(2 * maxRadius), (int)(2 * maxRadius));
Mat croppedImage = new Mat(image, roi);
// Preprocess the image
Mat grayImage = new Mat();
Cv2.CvtColor(croppedImage, grayImage, ColorConversionCodes.BGR2GRAY);
Cv2.GaussianBlur(grayImage, grayImage, new Size(7, 7), 0);
// Compute the step angle
float stepAngle = (endAngle - startAngle) / (caliperCount - 1);
// Initialize the result variables
Point2f bestCenter = new Point2f(center.X, center.Y);
float bestScore = float.MinValue;
// Create a list of calipers
List<Caliper> calipers = new List<Caliper>();
for (int i = 0; i < caliperCount; i++)
{
float angle = startAngle + i * stepAngle;
calipers.Add(new Caliper(center, angle, caliperWidth, caliperLength, fromInside, fromBlackToWhite));
}
// Process the calipers in parallel
Parallel.ForEach(calipers, caliper =>
{
// Compute the score for the current caliper
float score = caliper.ComputeScore(grayImage, minRadius, maxRadius);
// Update the result variables if the score is better than the current best score
lock (bestCenter)
{
if (score > bestScore)
{
bestScore = score;
bestCenter = caliper.Center;
}
}
});
// Shift the coordinates of the best center to the original image
bestCenter.X += roi.X;
bestCenter.Y += roi.Y;
return bestCenter;
}
private class Caliper
{
public Point2f Center { get; private set; }
public float Angle { get; private set; }
public int Width { get; private set; }
public int Length { get; private set; }
public bool FromInside { get; private set; }
public bool FromBlackToWhite { get; private set; }
public Caliper(Point2f center, float angle, int width, int length, bool fromInside, bool fromBlackToWhite)
{
Center = center;
Angle = angle;
Width = width;
Length = length;
FromInside = fromInside;
FromBlackToWhite = fromBlackToWhite;
}
public float ComputeScore(Mat image, float minRadius, float maxRadius)
{
float radius = (minRadius + maxRadius) / 2;
float x = Center.X + radius * (float)Math.Cos(Angle);
float y = Center.Y + radius * (float)Math.Sin(Angle);
Point2f point1 = new Point2f(x, y);
Point2f point2 = new Point2f(x + Length * (float)Math.Cos(Angle + Math.PI / 2), y + Length * (float)Math.Sin(Angle + Math.PI / 2));
Point2f point3 = new Point2f(x - Length * (float)Math.Cos(Angle), y - Length * (float)Math.Sin(Angle));
Point2f point4 = new Point2f(x + Length * (float)Math.Cos(Angle - Math.PI / 2), y + Length * (float)Math.Sin(Angle - Math.PI / 2));
float[] values1 = SampleLine(image, point1, point2, Width);
float[] values2 = SampleLine(image, point1, point3, Width);
float[] values3 = SampleLine(image, point1, point4, Width);
float score = ComputeScore(values1, values2, values3, FromInside, FromBlackToWhite);
return score;
}
private float[] SampleLine(Mat image, Point2f point1, Point2f point2, int width)
{
int count = (int)Math.Round(point1.DistanceTo(point2)) / width;
float[] values = new float[count];
for (int i = 0; i < count; i++)
{
float x = point1.X + (float)i / count * (point2.X - point1.X);
float y = point1.Y + (float)i / count * (point2.Y - point1.Y);
values[i] = image.At<float>((int)y, (int)x);
}
return values;
}
private float ComputeScore(float[] values1, float[] values2, float[] values3, bool fromInside, bool fromBlackToWhite)
{
float score = 0;
if (fromInside)
{
for (int i = 0; i < values1.Length; i++)
{
float value = values1[i] - values2[i];
score += fromBlackToWhite ? value : -value;
}
}
else
{
for (int i = 0; i < values1.Length; i++)
{
float value = values3[i] - values1[i];
score += fromBlackToWhite ? value : -value;
}
}
return score;
}
}
}
```
使用该函数时,需要传入以下参数:
- `image`:输入图像。
- `minRadius`:找圆扇形区域的最小半径。
- `maxRadius`:找圆扇形区域的最大半径。
- `center`:找圆扇形中心点。
- `startAngle`:扇形区域起始角度。
- `endAngle`:扇形区域结束角度。
- `caliperCount`:Caliper个数。
- `caliperWidth`:Caliper宽度。
- `caliperLength`:Caliper长度。
- `fromInside`:是否从内到外找圆心。
- `fromBlackToWhite`:是否从黑到白找圆心。
该函数返回找到的圆心坐标。
阅读全文