使用 OpenCvSharp 4.6 编写完善以下函数bool b2w //从白往黑边找直线点 bool left2Right //从左往右搜索边沿点 public static Point[][] FindLines(Mat src,bool b2w,bool left2Right,bool subPixel) { Mat gray = new Mat(); Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY); Mat edges = new Mat(); Cv2.Canny(gray, edges, 50, 200); LineSegmentPoint[] lines = Cv2.HoughLinesP(edges, 1, Math.PI / 180, 50, 50, 10); Point[][] result = new Point[lines.Length][]; for (int i = 0; i < lines.Length; i++) { LineSegmentPoint line = lines[i]; Cv2.Line(src, line.P1, line.P2, Scalar.Red, 2); result[i] = new Point[] { line.P1, line.P2 }; } return result; }
时间: 2024-03-08 16:49:12 浏览: 79
好的,以下是完善后的函数,可以根据参数设置从白往黑或从黑往白搜索直线边缘,并且可以选择从左往右或从右往左搜索边缘点,并且可以选择是否使用亚像素级别的精度:
```csharp
public static Point[][] FindLines(Mat src, bool b2w, bool left2Right, bool subPixel)
{
Mat gray = new Mat();
Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY);
Mat edges = new Mat();
Cv2.Canny(gray, edges, 50, 200);
LineSegmentPoint[] lines = Cv2.HoughLinesP(edges, 1, Math.PI / 180, 50, 50, 10);
Point[][] result = new Point[lines.Length][];
for (int i = 0; i < lines.Length; i++)
{
LineSegmentPoint line = lines[i];
Point[] points;
if (b2w)
{
if (left2Right)
{
points = FindEdgePointsB2W(gray, line.P1, line.P2, true, subPixel);
}
else
{
points = FindEdgePointsB2W(gray, line.P2, line.P1, true, subPixel);
}
}
else
{
if (left2Right)
{
points = FindEdgePointsW2B(gray, line.P1, line.P2, true, subPixel);
}
else
{
points = FindEdgePointsW2B(gray, line.P2, line.P1, true, subPixel);
}
}
Cv2.Line(src, points[0], points[1], Scalar.Red, 2);
result[i] = points;
}
return result;
}
private static Point[] FindEdgePointsB2W(Mat image, Point startPt, Point endPt, bool firstEdge, bool subPixel)
{
int dx = endPt.X - startPt.X;
int dy = endPt.Y - startPt.Y;
if (Math.Abs(dx) > Math.Abs(dy))
{
if (dx < 0)
{
Point temp = startPt;
startPt = endPt;
endPt = temp;
dx = -dx;
dy = -dy;
}
double k = (double)dy / dx;
int y = startPt.Y;
if (firstEdge)
{
while (image.At<byte>(y, startPt.X) > 128 && startPt.X < endPt.X)
{
startPt.X++;
y = (int)Math.Round(startPt.Y + k * (startPt.X - startPt.X));
}
}
else
{
while (image.At<byte>(y, endPt.X) > 128 && endPt.X > startPt.X)
{
endPt.X--;
y = (int)Math.Round(endPt.Y - k * (endPt.X - startPt.X));
}
}
if (subPixel)
{
double sum = 0;
int count = 0;
for (int x = startPt.X; x <= endPt.X; x++)
{
y = (int)Math.Round(startPt.Y + k * (x - startPt.X));
sum += image.At<byte>(y, x);
count++;
}
int xCenter = (startPt.X + endPt.X) / 2;
int yCenter = (int)Math.Round(startPt.Y + k * (xCenter - startPt.X));
double gray = sum / count;
double peak = gray > 128 ? 255 : 0;
double slope = k > 0 ? 1 : -1;
double delta = Math.Abs(gray - peak) / 2;
double threshold = gray - delta;
int left = xCenter;
while (left > startPt.X && image.At<byte>(yCenter, left - 1) * slope < threshold)
{
left--;
}
int right = xCenter;
while (right < endPt.X && image.At<byte>(yCenter, right + 1) * slope < threshold)
{
right++;
}
return new Point[] { new Point(left, yCenter), new Point(right, yCenter) };
}
else
{
return new Point[] { new Point(startPt.X, y), new Point(endPt.X, y) };
}
}
else
{
if (dy < 0)
{
Point temp = startPt;
startPt = endPt;
endPt = temp;
dx = -dx;
dy = -dy;
}
double k = (double)dx / dy;
int x = startPt.X;
if (firstEdge)
{
while (image.At<byte>(startPt.Y, x) > 128 && startPt.Y < endPt.Y)
{
startPt.Y++;
x = (int)Math.Round(startPt.X + k * (startPt.Y - startPt.Y));
}
}
else
{
while (image.At<byte>(endPt.Y, x) > 128 && endPt.Y > startPt.Y)
{
endPt.Y--;
x = (int)Math.Round(endPt.X - k * (endPt.Y - startPt.Y));
}
}
if (subPixel)
{
double sum = 0;
int count = 0;
for (int y = startPt.Y; y <= endPt.Y; y++)
{
x = (int)Math.Round(startPt.X + k * (y - startPt.Y));
sum += image.At<byte>(y, x);
count++;
}
int yCenter = (startPt.Y + endPt.Y) / 2;
int xCenter = (int)Math.Round(startPt.X + k * (yCenter - startPt.Y));
double gray = sum / count;
double peak = gray > 128 ? 255 : 0;
double slope = k > 0 ? 1 : -1;
double delta = Math.Abs(gray - peak) / 2;
double threshold = gray - delta;
int top = yCenter;
while (top > startPt.Y && image.At<byte>(top - 1, xCenter) * slope < threshold)
{
top--;
}
int bottom = yCenter;
while (bottom < endPt.Y && image.At<byte>(bottom + 1, xCenter) * slope < threshold)
{
bottom++;
}
return new Point[] { new Point(xCenter, top), new Point(xCenter, bottom) };
}
else
{
return new Point[] { new Point(x, startPt.Y), new Point(x, endPt.Y) };
}
}
}
private static Point[] FindEdgePointsW2B(Mat image, Point startPt, Point endPt, bool firstEdge, bool subPixel)
{
return FindEdgePointsB2W(image.Not(), startPt, endPt, firstEdge, subPixel);
}
```
该函数根据参数设置从白往黑或从黑往白搜索直线边缘,从左往右或从右往左搜索边缘点,并可以选择是否使用亚像素级别的精度。其中,私有函数 `FindEdgePointsB2W` 和 `FindEdgePointsW2B` 分别用于从白往黑和从黑往白搜索直线边缘,这两个函数也可以单独使用。
阅读全文