opencv 拟合直线 采用一些过滤离散点方法 C++代码实现 RANSAC
时间: 2023-10-08 21:09:34 浏览: 114
好的,下面是使用 C++ 和 OpenCV 库实现 RANSAC 方法过滤离散点的拟合直线的代码:
```c++
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main()
{
// 读取图像
Mat img = imread("image.jpg", IMREAD_GRAYSCALE);
if (img.empty())
{
cout << "Failed to read image!" << endl;
return -1;
}
// 边缘检测
Mat edges;
Canny(img, edges, 50, 150);
// RANSAC 参数
int numIterations = 100; // 迭代次数
int numPoints = 2; // 每次迭代选取的点数
int threshold = 3; // 离线阈值
// 进行 RANSAC
int maxInliers = 0;
Vec4i bestLine;
for (int i = 0; i < numIterations; i++)
{
// 随机选取两个点
vector<Point> points;
points.resize(numPoints);
for (int j = 0; j < numPoints; j++)
{
int x = rand() % edges.cols;
int y = rand() % edges.rows;
points[j] = Point(x, y);
}
// 拟合直线
Vec4i line;
fitLine(points, line, DIST_L2, 0, 0.01, 0.01);
// 统计符合要求的点数
int numInliers = 0;
for (int j = 0; j < edges.rows; j++)
{
for (int k = 0; k < edges.cols; k++)
{
if (edges.at<uchar>(j, k) > 0)
{
int dist = abs((line[1] - line[3]) * k - (line[0] - line[2]) * j + line[0] * line[3] - line[1] * line[2]) / sqrt(pow(line[1] - line[3], 2) + pow(line[0] - line[2], 2));
if (dist < threshold)
{
numInliers++;
}
}
}
}
// 更新最佳直线
if (numInliers > maxInliers)
{
maxInliers = numInliers;
bestLine = line;
}
}
// 绘制直线
Point pt1(bestLine[2] - bestLine[0] * (bestLine[3] - 0) / bestLine[1], 0);
Point pt2(bestLine[2] + bestLine[0] * (img.rows - bestLine[3]) / bestLine[1], img.rows);
line(img, pt1, pt2, Scalar(0, 0, 255), 2);
// 显示图像
imshow("image", img);
waitKey(0);
return 0;
}
```
这段代码中,首先读取输入图像,然后进行边缘检测。然后定义 RANSAC 的相关参数,并进行迭代。在每次迭代中,随机选取两个点,拟合直线,并统计符合要求的点数。最终选择符合要求点数最多的直线作为最佳直线,并绘制在原图上。需要注意的是,这里的距离阈值 threshold 需要根据具体情况进行调整。
阅读全文