Math 绘制装配线(OpenCV)

Math 绘制装配线(OpenCV),math,geometry,opencv,Math,Geometry,Opencv,我正在使用OpenCV通过cvFitLine() cvFitLine()。 详见 使用这些信息,我怎样才能得到一条直线的方程,以便我能画出这条直线?如果cvFitLine()返回标准化向量(vx,vy)和点(x0,y0),那么直线的方程为 (x,y)=(x0,y0)+t*(vx,vy) 其中t从−∞ 到+∞. 这是您要求的,但可能不会立即有助于划清界限。您可能希望将其剪裁到屏幕边界,或者原始点集的边界框。要将直线剪裁到矩形,只需在直线穿过矩形边界的位置求解值t。只需绘制一条大直线,而不是求解边界

我正在使用OpenCV通过
cvFitLine()

cvFitLine()。
详见

使用这些信息,我怎样才能得到一条直线的方程,以便我能画出这条直线?

如果
cvFitLine()
返回标准化向量
(vx,vy)
和点
(x0,y0)
,那么直线的方程为

(x,y)=(x0,y0)+t*(vx,vy)

其中
t
从−∞ 到+∞.


这是您要求的,但可能不会立即有助于划清界限。您可能希望将其剪裁到屏幕边界,或者原始点集的边界框。要将直线剪裁到矩形,只需在直线穿过矩形边界的位置求解值
t

只需绘制一条大直线,而不是求解边界。例如:

cv.Line(img, (x0-m*vx[0], y0-m*vy[0]), (x0+m*vx[0], y0+m*vy[0]), (0,0,0))

例如,我会做的。。对于足够大的m:)

我使用了一种类似于Karpath的策略,但使用了一个额外的功能。如您所见,我使用cvClipLine将线条修剪到图像的大小,这是不必要的,但确实增加了一点细节

此外,这里的乘数被定义为mult=max(img->height,img->width),所以我们不会得到可能有一天会溢出的数字

void drawLine(IplImage * img, float line[4], int thickness,CvScalar color)
{
    double theMult = max(img->height,img->width);
    // calculate start point
    CvPoint startPoint;
    startPoint.x = line[2]- theMult*line[0];// x0
    startPoint.y = line[3] - theMult*line[1];// y0
    // calculate end point
    CvPoint endPoint;
    endPoint.x = line[2]+ theMult*line[0];//x[1]
    endPoint.y = line[3] + theMult*line[1];//y[1]

    // draw overlay of bottom lines on image
    cvClipLine(cvGetSize(img), &startPoint, &endPoint);
    cvLine(img, startPoint, endPoint, color, thickness, 8, 0);
}
我们使用“Vec4f fitedLine;”作为装配线 在fitLine中,我们有4个参数 如果我们考虑线关系AZ贝娄: Y-Y0=M(X-X0)

我们有 Y0=装配线[3]; X0=装配线[2]; m=固定线路[1]/固定线路[0]


我们有一个直线方程,我们可以在上面找到其他点

添加到@brainjam答案:

要剪裁到原始点集的边界框,请执行以下操作:

// std::vector<Point2i> points = ...

//lineParams: [vx,vy, x0,y0]: (normalized vector, point on our contour)
Vec4f lineParams; fitLine(points, lineParams, CV_DIST_L2, 0, 0.01, 0.01);

// derive the bounding xs of points
decltype(points)::iterator minXP, maxXP;
std::tie(minXP, maxXP) = std::minmax_element(points.begin(), points.end(), [](const Point2i& p1, const Point2i& p2){ return p1.x < p2.x; });

// derive y coords of fitted line
float m = lineParams[1] / lineParams[0];
int y1 = ((minXP->x - lineParams[2]) * m) + lineParams[3];
int y2 = ((maxXP->x - lineParams[2]) * m) + lineParams[3];
line(clearTarget, Point(minXP->x, y1), Point(maxXP->x, y2), Scalar(255, 255, 255), 2);
//标准::向量点=。。。
//lineParams:[vx,vy,x0,y0]:(标准化向量,轮廓上的点)
Vec4f-lineParams;fitLine(点、线参数、CV_DIST_L2、0、0.01、0.01);
//导出点的边界X
decltype(points):迭代器minXP,maxXP;
std::tie(minXP,maxXP)=std::minmax_元素(points.begin(),points.end(),[](常量点2i&p1,常量点2i&p2){返回p1.xx-lineParams[2])*m)+lineParams[3];
inty2=((maxXP->x-lineParams[2])*m)+lineParams[3];
直线(clearTarget,点(minXP->x,y1),点(maxXP->x,y2),标量(255,255,255),2);

要剪切到整个图像边界,请将
minXP->x
替换为
0
并将
maxXP->x
替换为
image.cols-1
,这最初是在中回答的,这只是为任何路人在
python
中拼写出@brainjam的答案

使用单位向量
(vx,vy)
和线上某点
(x0,y0)
的直线公式为:

(x, y) = (x0, y0) + t*(vx, vy)
np.array([vx, vy, x0, y0])
cv2.fitLine()
的返回为:

(x, y) = (x0, y0) + t*(vx, vy)
np.array([vx, vy, x0, y0])
在本例中,我有一条线横跨图像的高度,因此我想找到与
y=0
y=img.shape[0]
相交的
t0
t1
(顶部/底部边界)


我认为这是分析上最正确的答案(与制作一条大线和剪辑相比)。我在下面的回答中对此进行了扩展,详细说明了如何在python中获取图像边界处的线条端点。是的,如果线条垂直或接近该边界,则交换x和y。这是唯一对我立即有用的答案。