public void FindEdgesOUTCir(Mat srcImage, double edgeThreshold, ref List<Point2f> zeroPList) { // 定义图像边界矩形 Rect boundary = new Rect(0, 0, srcImage.Width, srcImage.Height); // 计算图像中心处的y坐标 float cenY = (boundary.Y + boundary.Height) / 2; // 对输入图像进行竖直方向的投影 Mat projectMat = VerticalLineGrayParallel(srcImage); // 应用Sobel算子,得到x方向上的导数 Mat sobelMat = new Mat(); Cv2.Sobel(projectMat, sobelMat, MatType.CV_32FC1, 1, 0, 1, 1, 0); // 设置阈值 float thresholdFloat = (float)edgeThreshold; int width = sobelMat.Width; var points = new ConcurrentBag<Point2f>(); // thread-safe collection to hold edge points Parallel.For(1, width, i => { float sdx1 = sobelMat.At<float>(0, i - 1); float sdx2 = sobelMat.At<float>(0, i); if (sdx1 < thresholdFloat && sdx2 >= thresholdFloat) { float a = (sdx2 - sdx1) / 1f; float b = sdx1 - a * (i - 1); float x = (thresholdFloat - b) / a; Point2f point = new Point2f(x, cenY); points.Add(point); } }); zeroPList = points.ToList(); // convert thread-safe collection to list } 提升鲁棒性请优化,进一步优化,以适应边沿对比度比较低的图像
时间: 2024-02-10 15:35:04 浏览: 66
针对边沿对比度比较低的情况,可以考虑以下优化:
1. 调整阈值:可以根据实际情况调整阈值,使其适应较低的对比度。
2. 应用高斯滤波:可以在进行Sobel算子处理之前,应用高斯滤波对图像进行平滑处理,以减少噪声的干扰和提升边缘检测的准确性。
3. 应用Canny算子:Canny算子是一种常用的边缘检测算法,可以检测出较弱的边缘,并且可以自适应调整阈值。可以在投影处理后,应用Canny算子进行边缘检测。
4. 使用多尺度边缘检测:可以使用多个尺度对图像进行边缘检测,以检测出不同尺度下的边缘信息,并且可以提高对低对比度边缘的检测能力。
5. 学习使用深度学习模型:可以使用深度学习模型进行边缘检测,例如使用卷积神经网络模型进行图像分割和边缘检测。这种方法需要大量的数据和计算资源,但可以获得更好的检测效果。
相关问题
OpenCvSharp 输入一张图,边缘阈值、投影方向 编写找边沿点 static public Mat FindEdges(Mat srcImage, double edgeThreshold, ref List<Point2f> zeroPList, int eumProjection_Direction)
好的,这是一个关于使用 OpenCvSharp 查找边缘点的问题。我会尽力回答。
首先,你需要导入以下命名空间:
```csharp
using OpenCvSharp;
using System.Collections.Generic;
```
然后,你可以使用以下代码来查找边缘点:
```csharp
static public Mat FindEdges(Mat srcImage, double edgeThreshold, ref List<Point2f> zeroPList, int eumProjection_Direction)
{
Mat grayImage = new Mat();
Cv2.CvtColor(srcImage, grayImage, ColorConversionCodes.BGR2GRAY);
Mat edges = new Mat();
Cv2.Canny(grayImage, edges, edgeThreshold, edgeThreshold * 3);
var edgePoints = new List<Point>();
for (int y = 0; y < edges.Rows; y++)
{
for (int x = 0; x < edges.Cols; x++)
{
if (edges.Get<byte>(y, x) != 0)
{
edgePoints.Add(new Point(x, y));
}
}
}
var zeroPoints = new List<Point2f>();
if (eumProjection_Direction == 0)
{
foreach (var point in edgePoints)
{
zeroPoints.Add(new Point2f(point.X, 0));
}
}
else if (eumProjection_Direction == 1)
{
foreach (var point in edgePoints)
{
zeroPoints.Add(new Point2f(0, point.Y));
}
}
zeroPList = zeroPoints;
return edges;
}
```
这个函数接受一个源图像 `srcImage`,一个边缘阈值 `edgeThreshold`,一个引用类型的空的 `List<Point2f>` 对象 `zeroPList` 和一个投影方向的枚举值 `eumProjection_Direction`。
函数首先将源图像转换为灰度图像,然后使用 `Canny` 函数查找边缘。接着,函数遍历边缘图像中的每一个像素,如果该像素的值不为零,就将其添加到一个 `List<Point>` 对象中。最后,根据投影方向将边缘点转换为 `Point2f` 类型的坐标,并将它们添加到 `zeroPoints` 列表中。
注意,这个函数返回的是边缘图像 `edges`,而不是边缘点列表。如果你需要边缘点列表,你可以使用传入的 `zeroPList` 参数获取它们。
希望我的回答能够帮助到你!
public void fitLine(Mat srcImage, List<Point2f> fitPList, ref Point p1,ref Point p2) { if (fitPList.Count < 2) return; //Cv2.FitLine(fitPList, DistanceTypes.L2, 0, 0.01, 0.01); var line = Cv2.FitLine(fitPList, DistanceTypes.L1, 0, 0, 0); line.FitSize(srcImage.Width, srcImage.Height, out p1, out p2); }优化亚像素
拟合直线时可以使用亚像素级别的精度来提高拟合的准确性。可以使用`Cv2.SubPixelLIne()`方法对拟合直线进行优化,示例如下:
```
var line = Cv2.FitLine(fitPList, DistanceTypes.L1, 0, 0, 0);
var p1 = new Point(line[2], line[3]);
var p2 = new Point(line[2] + line[0] * srcImage.Height, line[3] + line[1] * srcImage.Height);
Cv2.SubPixelLine(srcImage, line, out line, 20, 0.01, 0.01);
p1 = new Point(line[2], line[3]);
p2 = new Point(line[2] + line[0] * srcImage.Height, line[3] + line[1] * srcImage.Height);
```
其中`Cv2.SubPixelLine()`方法的参数含义如下:
- `srcImage`:输入图像;
- `line`:需要优化的直线;
- `maxIterations`:最大迭代次数;
- `precision`:优化精度;
- `lineLength`:优化范围。
使用`Cv2.SubPixelLine()`方法可以提高直线拟合的准确性,特别是在直线长度较短的情况下。
阅读全文