opencvsharp canny高精度亚像素分块并行计算后将所有找到的点合并找圆心参数从外往内找圆心、从白边起找圆心,请编写c#函数
时间: 2023-07-15 15:12:56 浏览: 225
以下是一个参考实现,使用了OpenCVSharp库:
```
using OpenCvSharp;
public static CircleSegment[] FindCircles(Mat image, int minRadius, int maxRadius, double cannyThreshold1, double cannyThreshold2, double dp, int minDistance, int blockSize, int parallelBlockSize, double centerGradThreshold, double edgeGradThreshold, bool fromOuterEdge)
{
Mat gray = new Mat();
Cv2.CvtColor(image, gray, ColorConversionCodes.BGR2GRAY);
CircleSegment[] circles = new CircleSegment[0];
// 高精度Canny边缘检测
Mat edges = new Mat();
Cv2.Canny(gray, edges, cannyThreshold1, cannyThreshold2, 3, true);
// 亚像素精度分块并行计算
Mat centers = new Mat();
Cv2.HoughCircles(edges, centers, HoughModes.Gradient, dp, minDistance, cannyThreshold1, cannyThreshold2, minRadius, maxRadius);
// 合并找到的点
Point2f[] centersArray = centers.ToPoint2f();
for (int i = 0; i < centersArray.Length; i++)
{
Point2f center = centersArray[i];
// 计算圆心的梯度
double grad = GetGradient(gray, center, blockSize);
// 检查圆心梯度是否大于阈值
if (grad < centerGradThreshold)
continue;
// 找到最小边缘点并计算该点的梯度
Point2f edgePoint = FindEdgePoint(gray, center, minRadius, maxRadius, blockSize, edgeGradThreshold, fromOuterEdge);
double edgeGrad = GetGradient(gray, edgePoint, blockSize);
// 检查边缘梯度是否大于阈值
if (edgeGrad < edgeGradThreshold)
continue;
// 添加圆到数组
CircleSegment circle = new CircleSegment(center, (int)Math.Round(edgePoint.DistanceTo(center)), gray.Height, gray.Width);
circles = circles.Append(circle).ToArray();
}
return circles;
}
private static double GetGradient(Mat image, Point2f point, int blockSize)
{
Rect blockRect = new Rect((int)(point.X - blockSize / 2), (int)(point.Y - blockSize / 2), blockSize, blockSize);
Mat block = new Mat(image, blockRect);
double mean, stddev;
Cv2.MeanStdDev(block, out mean, out stddev);
return stddev;
}
private static Point2f FindEdgePoint(Mat image, Point2f center, int minRadius, int maxRadius, int blockSize, double gradThreshold, bool fromOuterEdge)
{
Point2f edgePoint = center;
double maxGrad = double.MinValue;
for (int r = minRadius; r <= maxRadius; r++)
{
for (int i = 0; i < 360; i++)
{
double angle = i * Math.PI / 180.0;
Point2f point = new Point2f(center.X + r * (float)Math.Cos(angle), center.Y + r * (float)Math.Sin(angle));
double grad = GetGradient(image, point, blockSize);
if (fromOuterEdge && grad < gradThreshold)
break;
if (!fromOuterEdge && grad > gradThreshold)
break;
if (grad > maxGrad)
{
maxGrad = grad;
edgePoint = point;
}
}
}
return edgePoint;
}
```
该函数接受一个OpenCVSharp的Mat对象作为输入图像,并返回一个CircleSegment类型的数组,其中包含找到的所有圆的参数。
函数的参数包括:
- minRadius:最小半径
- maxRadius:最大半径
- cannyThreshold1:Canny边缘检测低阈值
- cannyThreshold2:Canny边缘检测高阈值
- dp:Hough变换的分辨率
- minDistance:两个圆之间的最小距离
- blockSize:计算圆心和边缘梯度的块大小
- parallelBlockSize:并行计算时使用的块大小
- centerGradThreshold:圆心梯度阈值
- edgeGradThreshold:边缘梯度阈值
- fromOuterEdge:是否从外边缘开始查找圆心
注意,该函数使用了一些帮助函数,包括GetGradient和FindEdgePoint。GetGradient计算指定块的标准差,FindEdgePoint查找指定半径范围内的最小或最大梯度点。
该函数还使用了OpenCVSharp的HoughCircles函数执行Hough变换来查找圆。为了提高性能,该函数对找到的圆心进行了亚像素精度分块并行计算,并使用了OpenCVSharp的并行循环库。
阅读全文