OpenCvSharp 编写CircularCaliper找圆心函数 ,输入图像、Caliper个数,宽度、长度、 输入找圆扇形区域的最小半径和最大半径、设定扇形区域起始角度、扇形区域结束角度 输入从内到外找圆心、从黑到白找圆 中心圆可设定请编写函数
时间: 2023-07-10 15:07:54 浏览: 190
opencv找圆程序
下面是一个使用OpenCvSharp编写的找圆心函数,根据您的需求进行了相应的参数设置:
```c#
using OpenCvSharp;
public static Point2f FindCircleCenter(Mat src, int caliperCount, int caliperWidth, int caliperLength, int minRadius, int maxRadius, double startAngle, double endAngle, bool fromInside, bool fromBlackToWhite)
{
// 将图像转为灰度图
Mat gray = new Mat();
Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);
// 边缘检测
Mat edges = new Mat();
Cv2.Canny(gray, edges, 50, 150);
// 圆心坐标
Point2f center = new Point2f(-1, -1);
// 找圆心
for (int radius = minRadius; radius <= maxRadius; radius++)
{
for (double angle = startAngle; angle <= endAngle; angle += (endAngle - startAngle) / caliperCount)
{
double x1 = center.X + radius * Math.Cos(angle);
double y1 = center.Y + radius * Math.Sin(angle);
double x2 = center.X + (radius + caliperLength) * Math.Cos(angle);
double y2 = center.Y + (radius + caliperLength) * Math.Sin(angle);
// 计算卡尺线端点坐标
Point p1 = new Point((int)Math.Round(x1), (int)Math.Round(y1));
Point p2 = new Point((int)Math.Round(x2), (int)Math.Round(y2));
// 在扇形区域内选择卡尺线
if ((fromInside && radius >= minRadius) || (!fromInside && radius <= maxRadius))
{
double lineLength = Math.Sqrt(Math.Pow(x2 - x1, 2) + Math.Pow(y2 - y1, 2));
double dx = caliperWidth * (y2 - y1) / lineLength;
double dy = caliperWidth * (x2 - x1) / lineLength;
Point2f p1Left = new Point2f((float)(p1.X + dx), (float)(p1.Y + dy));
Point2f p1Right = new Point2f((float)(p1.X - dx), (float)(p1.Y - dy));
Point2f p2Left = new Point2f((float)(p2.X + dx), (float)(p2.Y + dy));
Point2f p2Right = new Point2f((float)(p2.X - dx), (float)(p2.Y - dy));
// 确定卡尺线方向
Point2f start, end;
if (fromBlackToWhite)
{
start = p1Left;
end = p1Right;
}
else
{
start = p1Right;
end = p1Left;
}
// 计算灰度差分
double graySum1 = 0, graySum2 = 0;
for (double t = 0; t < caliperWidth; t++)
{
Point2f pt1 = new Point2f((float)(start.X + t * (end.X - start.X) / caliperWidth), (float)(start.Y + t * (end.Y - start.Y) / caliperWidth));
Point2f pt2 = new Point2f((float)(pt1.X + (end.X - start.X) / caliperWidth), (float)(pt1.Y + (end.Y - start.Y) / caliperWidth));
double gray1 = gray.At<byte>((int)pt1.Y, (int)pt1.X);
double gray2 = gray.At<byte>((int)pt2.Y, (int)pt2.X);
graySum1 += gray1;
graySum2 += gray2;
}
// 判断是否找到圆心
if (fromBlackToWhite && graySum1 < graySum2 || !fromBlackToWhite && graySum1 > graySum2)
{
center = new Point2f((float)(center.X + radius * Math.Cos(angle)), (float)(center.Y + radius * Math.Sin(angle)));
}
}
}
}
return center;
}
```
使用方法:
```c#
// 读取图像
Mat src = Cv2.ImRead("image.jpg");
// 找圆心
Point2f center = FindCircleCenter(src, 20, 5, 50, 100, 200, 0, Math.PI * 2, true, true);
// 绘制圆心
Cv2.Circle(src, (int)center.X, (int)center.Y, 3, Scalar.Red, -1);
Cv2.ImShow("Result", src);
Cv2.WaitKey();
```
其中,`src`为输入图像,`caliperCount`为卡尺线数量,`caliperWidth`为卡尺线宽度,`caliperLength`为卡尺线长度,`minRadius`和`maxRadius`为扇形区域的最小半径和最大半径,`startAngle`和`endAngle`为扇形区域的起始角度和结束角度,`fromInside`为是否从内到外找圆心,`fromBlackToWhite`为是否从黑到白找圆心。函数返回找到的圆心坐标。
阅读全文