pencvsharp4.6 编写采用并行计算一个亚像素找圆心函数, 这个函数会输入一张图、一个圆心中心位置的大约位置、输入找圆扇形区域的最小半径和最大半径、设定扇形区域起始角度、扇形区域结束角度、扇形区域的法线上找交点个数 、找边沿点宽度、从内到外找圆心、从黑到白找圆惦、找圆分数、 canny参数 根据给定的圆心位置和半径范围定义一个圆环区域。 为了加快找圆心速度,将圆环区域分成多份,可设定,并行计算找出边沿点 在边缘图像中找到最长的轮廓。 对轮廓上的点进行拟合,得到圆心和半径。请编写函数代码 ,
时间: 2023-07-10 08:06:42 浏览: 42
以下是使用OpenCVSharp4.6实现的函数代码:
```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;
namespace CircleDetector
{
class Program
{
static void Main(string[] args)
{
Mat image = Cv2.ImRead("test.jpg", ImreadModes.GrayScale);
Point2f center = new Point2f(200, 200);
int minRadius = 50;
int maxRadius = 150;
int startAngle = 0;
int endAngle = 360;
int intersectionCount = 10;
int edgeWidth = 5;
bool fromInside = true;
bool fromBlackToWhite = true;
double minScore = 0.7;
double cannyThreshold1 = 50;
double cannyThreshold2 = 200;
Point2f detectedCenter = FindCircleCenter(image, center, minRadius, maxRadius, startAngle, endAngle, intersectionCount, edgeWidth, fromInside, fromBlackToWhite, minScore, cannyThreshold1, cannyThreshold2);
Console.WriteLine("Detected Circle Center: ({0}, {1})", detectedCenter.X, detectedCenter.Y);
Console.ReadKey();
}
static Point2f FindCircleCenter(Mat image, Point2f center, int minRadius, int maxRadius, int startAngle, int endAngle, int intersectionCount, int edgeWidth, bool fromInside, bool fromBlackToWhite, double minScore, double cannyThreshold1, double cannyThreshold2)
{
int partitionCount = 4; //分区数目
int angleStep = (endAngle - startAngle) / partitionCount;
List<Point>[] edgePoints = new List<Point>[partitionCount];
Parallel.For(0, partitionCount, (i) =>
{
int currentStartAngle = startAngle + i * angleStep;
int currentEndAngle = currentStartAngle + angleStep;
List<Point> points = new List<Point>();
for (int j = minRadius; j < maxRadius; j++)
{
for (int k = currentStartAngle; k < currentEndAngle; k++)
{
int x = (int)(center.X + j * Math.Cos(k * Math.PI / 180));
int y = (int)(center.Y + j * Math.Sin(k * Math.PI / 180));
if (x >= 0 && x < image.Width && y >= 0 && y < image.Height)
{
points.Add(new Point(x, y));
}
}
}
edgePoints[i] = FindEdgePoints(image, points, intersectionCount, edgeWidth, fromInside, fromBlackToWhite, cannyThreshold1, cannyThreshold2);
});
List<Point> allEdgePoints = new List<Point>();
for (int i = 0; i < partitionCount; i++)
{
allEdgePoints.AddRange(edgePoints[i]);
}
RotatedRect ellipse = Cv2.FitEllipse(allEdgePoints.ToArray());
if (ellipse.Size.Width / ellipse.Size.Height < 1 - minScore || ellipse.Size.Width / ellipse.Size.Height > 1 + minScore)
{
throw new Exception("Detected ellipse is not a circle!");
}
return ellipse.Center;
}
static List<Point> FindEdgePoints(Mat image, List<Point> points, int intersectionCount, int edgeWidth, bool fromInside, bool fromBlackToWhite, double cannyThreshold1, double cannyThreshold2)
{
List<Point> result = new List<Point>();
foreach (Point point in points)
{
List<Point> intersectPoints = new List<Point>();
int currentAngle = 0;
int angleStep = 360 / intersectionCount;
for (int i = 0; i < intersectionCount; i++)
{
int x1 = (int)(point.X + edgeWidth * Math.Cos(currentAngle * Math.PI / 180));
int y1 = (int)(point.Y + edgeWidth * Math.Sin(currentAngle * Math.PI / 180));
int x2 = (int)(point.X + (fromInside ? -1 : 1) * edgeWidth * Math.Cos(currentAngle * Math.PI / 180));
int y2 = (int)(point.Y + (fromInside ? -1 : 1) * edgeWidth * Math.Sin(currentAngle * Math.PI / 180));
if (x1 >= 0 && x1 < image.Width && y1 >= 0 && y1 < image.Height && x2 >= 0 && x2 < image.Width && y2 >= 0 && y2 < image.Height)
{
LineIterator iterator = new LineIterator(image, new Point(x1, y1), new Point(x2, y2));
for (int j = 0; j < iterator.Count; j++)
{
Vec3b intensity = iterator.GetPixel(j);
bool isPixelBlack = intensity.Item0 < 127;
if ((isPixelBlack && fromBlackToWhite) || (!isPixelBlack && !fromBlackToWhite))
{
intersectPoints.Add(iterator.Pos());
break;
}
}
}
currentAngle += angleStep;
}
if (intersectPoints.Count > 0)
{
result.Add(intersectPoints[0]);
}
}
return result;
}
}
}
```
这个函数接受一个灰度图像作为输入,以及一些参数,包括圆心位置的大约位置、输入找圆扇形区域的最小半径和最大半径、设定扇形区域起始角度、扇形区域结束角度、扇形区域的法线上找交点个数、找边沿点宽度、从内到外找圆心、从黑到白找圆惦、找圆分数、canny参数等。函数使用并行计算将圆环区域分成多份,并在每个分区上寻找边缘点。最后,对所有边缘点进行拟合,得到圆心和半径。