2
A
回答
2
1
RANSAC不是最高效的,但對大量異常值更好。下面是如何使用OpenCV的做到這一點:
一個有用的結構 -
struct SLine
{
SLine():
numOfValidPoints(0),
params(-1.f, -1.f, -1.f, -1.f)
{}
cv::Vec4f params;//(cos(t), sin(t), X0, Y0)
int numOfValidPoints;
};
總用來製作適合成功對
cv::Vec4f TotalLeastSquares(
std::vector<cv::Point>& nzPoints,
std::vector<int> ptOnLine)
{
//if there are enough inliers calculate model
float x = 0, y = 0, x2 = 0, y2 = 0, xy = 0, w = 0;
float dx2, dy2, dxy;
float t;
for(size_t i = 0; i < nzPoints.size(); ++i)
{
x += ptOnLine[i] * nzPoints[i].x;
y += ptOnLine[i] * nzPoints[i].y;
x2 += ptOnLine[i] * nzPoints[i].x * nzPoints[i].x;
y2 += ptOnLine[i] * nzPoints[i].y * nzPoints[i].y;
xy += ptOnLine[i] * nzPoints[i].x * nzPoints[i].y;
w += ptOnLine[i];
}
x /= w;
y /= w;
x2 /= w;
y2 /= w;
xy /= w;
//Covariance matrix
dx2 = x2 - x * x;
dy2 = y2 - y * y;
dxy = xy - x * y;
t = (float) atan2(2 * dxy, dx2 - dy2)/2;
cv::Vec4f line;
line[0] = (float) cos(t);
line[1] = (float) sin(t);
line[2] = (float) x;
line[3] = (float) y;
return line;
}
實際RANSAC最小二乘
SLine LineFitRANSAC(
float t,//distance from main line
float p,//chance of hitting a valid pair
float e,//percentage of outliers
int T,//number of expected minimum inliers
std::vector<cv::Point>& nzPoints)
{
int s = 2;//number of points required by the model
int N = (int)ceilf(log(1-p)/log(1 - pow(1-e, s)));//number of independent trials
std::vector<SLine> lineCandidates;
std::vector<int> ptOnLine(nzPoints.size());//is inlier
RNG rng((uint64)-1);
SLine line;
for (int i = 0; i < N; i++)
{
//pick two points
int idx1 = (int)rng.uniform(0, (int)nzPoints.size());
int idx2 = (int)rng.uniform(0, (int)nzPoints.size());
cv::Point p1 = nzPoints[idx1];
cv::Point p2 = nzPoints[idx2];
//points too close - discard
if (cv::norm(p1- p2) < t)
{
continue;
}
//line equation -> (y1 - y2)X + (x2 - x1)Y + x1y2 - x2y1 = 0
float a = static_cast<float>(p1.y - p2.y);
float b = static_cast<float>(p2.x - p1.x);
float c = static_cast<float>(p1.x*p2.y - p2.x*p1.y);
//normalize them
float scale = 1.f/sqrt(a*a + b*b);
a *= scale;
b *= scale;
c *= scale;
//count inliers
int numOfInliers = 0;
for (size_t i = 0; i < nzPoints.size(); ++i)
{
cv::Point& p0 = nzPoints[i];
float rho = abs(a*p0.x + b*p0.y + c);
bool isInlier = rho < t;
if (isInlier) numOfInliers++;
ptOnLine[i] = isInlier;
}
if (numOfInliers < T)
{
continue;
}
line.params = TotalLeastSquares(nzPoints, ptOnLine);
line.numOfValidPoints = numOfInliers;
lineCandidates.push_back(line);
}
int bestLineIdx = 0;
int bestLineScore = 0;
for (size_t i = 0; i < lineCandidates.size(); i++)
{
if (lineCandidates[i].numOfValidPoints > bestLineScore)
{
bestLineIdx = i;
bestLineScore = lineCandidates[i].numOfValidPoints;
}
}
if (lineCandidates.empty())
{
return SLine();
}
else
{
return lineCandidates[bestLineIdx];
}
}
相關問題
- 1. 使用RANSAC進行線條擬合
- 2. RANSAC線性迴歸(魯棒線配合)
- 3. 線擬合算法OpenCV
- 4. OpenCV中的曲線擬合
- 5. OpenCV高斯曲線擬合
- 6. OpenCV線擬合算法
- 7. 2D平面擬合,ransac,matlab,鏈接
- 8. 用於樣條擬合的Ransac
- 9. MLESAC不是RANSAC與OpenCV
- 10. OpenCV的 - 曲線擬合到一組點
- 11. 找到RANSAC的OpenCV源文件
- 12. RANSAC區分線和麪
- 13. 曲線擬合
- 14. 如何通過點雲擬合曲線? OpenCV/C++
- 15. OpenCV - 從圖像中刪除「白色」僞影並擬合曲線
- 16. 使用OpenCV C++的樓梯檢測線路擬合
- 17. 擬合曲線 - 擬合參數
- 18. 曲線擬合耦合ODEs
- 19. 曲線擬合scipy
- 20. scipy.optimize曲線擬合
- 21. Spotfire曲線擬合
- 22. python曲線擬合
- 23. Python曲線擬合
- 24. 用lsq曲線擬合加權曲線擬合
- 25. 沿着明像素的擬合線
- 26. Opencv - 多項式函數擬合
- 27. 公制爲橢圓OpenCV中擬合
- 28. 獲取RANSAC在findHomography(OpenCV for Android)中使用的5個點
- 29. 擬合線 - MatLab不同意OpenCV
- 30. RANSAC算法
哦,非常感謝。我認爲最小均方將不起作用,因爲我有一組點,我想要最佳線條具有一些屬性,例如距圖像中心x角和x米。 – DualSim