我正在使用OpenCV来使用cvFitLine()
cvFitLine()
返回一个归一化向量,该向量与行和行上的点共线。
详情请见here
使用此信息如何获取线的等式以便我可以绘制线?
答案 0 :(得分:9)
如果cvFitLine()
返回标准化向量(vx,vy)
和点(x0,y0)
,那么该行的等式为
(x,y)=(x0,y0)+ t *(vx,vy)
其中t
从-∞到+∞。
这是你要求的,但可能不会立即有助于画线。您可能希望将其剪切到屏幕边界,或者可能是原始点集的边界框。要将线条剪切为矩形,只需求解线条穿过矩形边界的t
值。
答案 1 :(得分:9)
只需绘制一条大线而不是解决边界问题。例如:
cv.Line(img, (x0-m*vx[0], y0-m*vy[0]), (x0+m*vx[0], y0+m*vy[0]), (0,0,0))
将以例如..为m足够大:))
答案 2 :(得分:4)
我在那里使用了类似于Karpathy的策略但使用了额外的功能。正如您所看到的,我正在使用cvClipLine将线条修剪为图像的大小,这是不必要的,但确实增加了一点好处。
此处的乘数也被定义为theMult = 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);
}
答案 3 :(得分:3)
对于任何路人,这只会在python
中阐明@brainjam的答案。
使用单位向量(vx, vy)
和行(x0, y0)
上某点的直线的公式为:
(x, y) = (x0, y0) + t*(vx, vy)
cv2.fitLine()
的回报是:
np.array([vx, vy, x0, y0])
在示例情况下,我有一条线跨越图像的高度,因此我想找到与t0
和t1
相交的y=0
和y=img.shape[0]
(顶部/底部边界)。
# get the fitLine for your set of points in the array, `line`
fit_line = cv2.fitLine(line, cv2.DIST_L2, 0, 0.01, 0.01)
# compute t0 for y=0 and t1 for y=img.shape[0]: (y-y0)/vy
t0 = (0-fit_line[3])/fit_line[1]
t1 = (img.shape[0]-fit_line[3])/fit_line[1]
# plug into the line formula to find the two endpoints, p0 and p1
# to plot, we need pixel locations so convert to int
p0 = (fit_line[2:4] + (t0 * fit_line[0:2])).astype(np.uint32)
p1 = (fit_line[2:4] + (t1 * fit_line[0:2])).astype(np.uint32)
# draw the line. For my version of opencv, it wants tuples so we
# flatten the arrays and convert
# args: cv2.line(image, p0, p1, color, thickness)
cv2.line(img, tuple(p0.ravel()), tuple(p1.ravel()), (0, 255, 0), 10)
答案 4 :(得分:1)
添加到@brainjam答案:
要裁剪到原始点集的边界框,请执行以下操作:
.html()
要裁剪整个图像边界,请用https://stackoverflow.com/a/14192660/2380455替换// 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);
到minXP->x
和0
到maxXP->x
答案 5 :(得分:0)
我们使用“Vec4f fitedLine”;用于装配线 在fitLine中我们有4个参数 如果我们考虑线关系az bellow: Y - Y0 = M(X - X0)
我们有 Y0 = FitedLine [3]; X0 = FitedLine [2]; m = FitedLine [1] / FitedLine [0];所以我们有一个线方程,我们可以在其上找到其他点。