OpenCvSharp 编写多线程CircularCaliper找圆心函数 , 输入图像、找圆扇形区域的最小半径和最大半径、找圆扇形中心点、设定扇形区域起始角度、扇形区域结束角度 复制出扇形区域内图像作为找圆分析的图像 输入Caliper个数,宽度、长度、 将每个Caliper区域roi内从整体图像中复制成小图像来分析以提高速度,得到的点坐标转换到整体大图的坐标系中 输入从内到外找圆心、从黑到白找圆 输入canny参数 并行计Caliper区域,将Caliper区域所有canny点合并,拟合圆心 用out 输出圆中心点、半径请编写函数
时间: 2024-02-01 20:14:23 浏览: 109
以下是使用OpenCvSharp编写的多线程CircularCaliper找圆心函数的示例代码:
```csharp
public static void FindCircleCenter(Mat image, int minRadius, int maxRadius, out Point center, out int radius,
Point centerGuess = default(Point), double startAngle = 0, double endAngle = 360, int cannyThreshold1 = 100,
int cannyThreshold2 = 200, int numCalipers = 20, int caliperWidth = 10, int caliperLength = 100, bool fromInside = true)
{
// Convert the image to grayscale
Mat grayImage = new Mat();
Cv2.CvtColor(image, grayImage, ColorConversionCodes.BGR2GRAY);
// Apply canny edge detection to the gray image
Mat edges = new Mat();
Cv2.Canny(grayImage, edges, cannyThreshold1, cannyThreshold2);
// Create a mask for the circular sector
Mat mask = new Mat(image.Size(), MatType.CV_8UC1, Scalar.All(0));
Cv2.Circle(mask, centerGuess != default(Point) ? centerGuess : new Point(image.Width / 2, image.Height / 2),
(minRadius + maxRadius) / 2, Scalar.All(255), -1);
Mat sectorMask = new Mat(image.Size(), MatType.CV_8UC1, Scalar.All(0));
Cv2.Ellipse(sectorMask, centerGuess != default(Point) ? centerGuess : new Point(image.Width / 2, image.Height / 2),
new Size((maxRadius - minRadius) / 2, (maxRadius - minRadius) / 2), 0, startAngle, endAngle, Scalar.All(255), -1);
mask &= sectorMask;
// Find the contour of the mask
Point[][] contours;
HierarchyIndex[] hierarchy;
Cv2.FindContours(mask, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxNone);
// Split the contour into segments
List<Point[]> segments = new List<Point[]>();
int numSegments = (int)Math.Round((endAngle - startAngle) / 360 * contours[0].Length);
for (int i = 0; i < numSegments; i++)
{
int startIndex = (int)Math.Round((double)i / numSegments * contours[0].Length);
int endIndex = (int)Math.Round((double)(i + 1) / numSegments * contours[0].Length);
if (endIndex == startIndex)
{
endIndex++;
}
if (endIndex > contours[0].Length)
{
endIndex -= contours[0].Length;
}
if (startIndex < endIndex)
{
segments.Add(contours[0].Skip(startIndex).Take(endIndex - startIndex).ToArray());
}
else
{
segments.Add(contours[0].Skip(startIndex).Concat(contours[0].Take(endIndex)).ToArray());
}
}
// Create a list of caliper regions
List<Rect[]> caliperRegions = new List<Rect[]>();
for (int i = 0; i < segments.Count; i++)
{
Point[] segment = segments[i];
Point[] nextSegment = segments[(i + 1) % segments.Count];
Point centerPoint = new Point(segment.Sum(p => p.X) / segment.Length, segment.Sum(p => p.Y) / segment.Length);
double angle = Math.Atan2(nextSegment[0].Y - segment[segment.Length - 1].Y, nextSegment[0].X - segment[segment.Length - 1].X);
double normalAngle = angle + Math.PI / 2;
Point[] caliperPoints = new Point[numCalipers * 2];
for (int j = 0; j < numCalipers; j++)
{
double caliperAngle = normalAngle + j * 2 * Math.PI / numCalipers;
Point caliperStart = new Point(centerPoint.X + (int)Math.Round(caliperWidth / 2 * Math.Cos(caliperAngle)),
centerPoint.Y + (int)Math.Round(caliperWidth / 2 * Math.Sin(caliperAngle)));
Point caliperEnd = new Point(centerPoint.X - (int)Math.Round(caliperWidth / 2 * Math.Cos(caliperAngle)),
centerPoint.Y - (int)Math.Round(caliperWidth / 2 * Math.Sin(caliperAngle)));
caliperPoints[j * 2] = caliperStart;
caliperPoints[j * 2 + 1] = caliperEnd;
}
Point[] hull = Cv2.ConvexHull(caliperPoints);
Rect boundingRect = Cv2.BoundingRect(hull);
Rect[] calipers = new Rect[numCalipers];
int caliperOffset = (int)Math.Round(caliperLength / 2 * (fromInside ? -1 : 1));
for (int j = 0; j < numCalipers; j++)
{
double caliperAngle = normalAngle + j * 2 * Math.PI / numCalipers;
Point caliperStart = new Point(centerPoint.X + (int)Math.Round(caliperWidth / 2 * Math.Cos(caliperAngle)),
centerPoint.Y + (int)Math.Round(caliperWidth / 2 * Math.Sin(caliperAngle)));
Point caliperEnd = new Point(centerPoint.X - (int)Math.Round(caliperWidth / 2 * Math.Cos(caliperAngle)),
centerPoint.Y - (int)Math.Round(caliperWidth / 2 * Math.Sin(caliperAngle)));
Point caliperOffsetStart = new Point(caliperStart.X + (int)Math.Round(caliperOffset * Math.Cos(caliperAngle)),
caliperStart.Y + (int)Math.Round(caliperOffset * Math.Sin(caliperAngle)));
Point caliperOffsetEnd = new Point(caliperEnd.X + (int)Math.Round(caliperOffset * Math.Cos(caliperAngle)),
caliperEnd.Y + (int)Math.Round(caliperOffset * Math.Sin(caliperAngle)));
calipers[j] = new Rect(caliperOffsetStart.X, caliperOffsetStart.Y, caliperOffsetEnd.X - caliperOffsetStart.X,
caliperOffsetEnd.Y - caliperOffsetStart.Y);
}
caliperRegions.Add(calipers);
}
// Analyze each caliper region in parallel
ConcurrentBag<Point>[] cannyPoints = new ConcurrentBag<Point>[caliperRegions.Sum(r => r.Length)];
Parallel.For(0, caliperRegions.Count, i =>
{
Rect[] calipers = caliperRegions[i];
Point[] segment = segments[i];
Mat regionImage = edges.SubMat(new Rect(boundingRect.X + segment.Min(p => p.X) - caliperLength / 2,
boundingRect.Y + segment.Min(p => p.Y) - caliperLength / 2, boundingRect.Width + caliperLength,
boundingRect.Height + caliperLength));
for (int j = 0; j < calipers.Length; j++)
{
Rect caliper = calipers[j];
Mat caliperRegion = regionImage.SubMat(caliper);
Point[] caliperPoints = Cv2.FindNonZero(caliperRegion).Select(p => new Point(p.X + caliper.X, p.Y + caliper.Y)).ToArray();
cannyPoints[i * numCalipers + j] = new ConcurrentBag<Point>(caliperPoints);
}
});
// Combine all canny points
List<Point> allCannyPoints = new List<Point>();
foreach (ConcurrentBag<Point> bag in cannyPoints)
{
allCannyPoints.AddRange(bag);
}
// Fit a circle to the canny points
Cv2.FitCircle(allCannyPoints.ToArray(), out center, out radius);
// Convert the center point to the original image coordinates
center.X += boundingRect.X - (image.Width - grayImage.Width) / 2;
center.Y += boundingRect.Y - (image.Height - grayImage.Height) / 2;
}
```
可以使用以下代码调用上述函数:
```csharp
Point center;
int radius;
FindCircleCenter(image, minRadius, maxRadius, out center, out radius, centerGuess, startAngle, endAngle,
cannyThreshold1, cannyThreshold2, numCalipers, caliperWidth, caliperLength, fromInside);
```
阅读全文