OpenCV检测点是否位于线/平面上

时间:2011-04-08 14:46:05

标签: c++ opencv histogram

我正在研究一种目前手动执行的光学设备的自动校准形式。校准的第一部分是确定光束是否照亮了一组“校准”点。

我正在使用OpenCV并对图像进行阈值处理和裁剪,只留下可能的相关点。我知道想确定这些点是否位于直线(水平)线上;如果它们足够数量,光束是否处于正确的位置! (这些点位于一条直线上,但光束经常弯曲,因此点击大多数点就足够了,有21个点在阈值处显示为白色圆圈。)

我尝试使用直方图,但是在阈值图像上结果不正确,现在正在查看Hough线,但是如果检测到的点位于一条线上,我会检测边缘的直线。

这是我使用的门槛代码:

cvThreshold(output, output, 150, 256, CV_THRESH_BINARY);

直方图的结果是1到640个区间(图像宽度)是0线处的两条线和接近最大值的2/3线。不是没有阈值的预期或获得的分布。

有些照片试图弄明白点(请注意“嘈杂”的光点,这是系统设置的一个特征,无法克服):

12 points in a stright line next to one another (beam in correct position)

The sort of output wanted (for illistration, if the points are on the line this is all I need to know!)

非常感谢任何帮助。一种想法是提取点的坐标并进行比较,但我不知道如何做到这一点。

3 个答案:

答案 0 :(得分:4)

这可以帮助这里的任何人使用我所使用的一些简单的linaear回归代码的基本(初稿)。

    // Calculate the averages of arrays x and y
double xa = 0, ya = 0;

for(int i = 0; i < n; i++) 
{
    xa += x[i];
    ya += y[i];
}   
xa /= n;
ya /= n;

// Summation of all X and Y values
double sumX = 0;
double sumY = 0;
// Summation of all X*Y values
double sumXY = 0;
// Summation of all X^2 and Y^2 values
double sumXs = 0;
double sumYs = 0;

for(int i = 0; i < n; i++)
{
    sumX = sumX + x[i];
    sumY = sumY + y[i];

    sumXY = sumXY + (x[i] * y[i]);

    sumXs = sumXs + (x[i] * x[i]);
    sumYs = sumYs + (y[i] * y[i]);
}
// (X^2) and (Y^2) sqaured
double Xs = sumX * sumX;
double Ys = sumY * sumY;

// Calculate slope, m
slope = (n * sumXY - sumX * sumY) / (n* sumXs - Xs);    

// Calculate intercept
intercept = ceil((sumY - slope * sumX) / n);

// Calculate regression index, r^2
double r_top = (n * sumXY - sumX * sumY); 
double r_bottom = sqrt((n* sumXs - Xs) * (n* sumYs - Ys));
double r = 0;

// Check line is not perfectly vertical or horizontal
if(r_top == 0 || r_bottom == 0)
    r = 0;
else
    r = r_top/ r_bottom;

有更多的方法可以做到这一点(参见CodeCogs或AGLIB),但快速修复此代码似乎有用。

为了检测OpenCV中的Circles,我放弃了Hough变换并从这篇帖子中删除了codee: Detection of coins (and fit ellipses) on an image

然后是一个细化坐标(移除任何异常值等)以确定圆是否位于斜率的水平线上并截取回归值的情况。

答案 1 :(得分:2)

获取阈值点的x,y坐标,然后执行线性回归以找到最佳拟合线。使用该行,您可以确定r ^ 2值,从而有效地为您提供合适的质量。根据该适应度量,您可以确定校准成功。

Here是一个很好的讨论。

答案 2 :(得分:0)

你可以做这样的事情,虽然它是一个近似值:

var dw =决定以像素为单位的中等点宽度

maxdots = 0;
for each line of the image {
  var dots = 0;
  scan by incrementing x by dw {
     if (color==dotcolor) dots++;
  }
  if (dots>maxdots) maxdots=dots;
}

maxdots将是最好的结果......