使用OpenCV在物体中检测线条

15

我有以下图像。我想检测将该对象分成两半的线。哪种方法是最好的?我已经尝试使用霍夫变换,但有时对象不够大以便它能够检测到它。有什么想法吗?

谢谢!

输入图像描述

1个回答

41

通常,霍夫变换用于线检测。

但如果它对您无效,拟合直线也是一个很好的替代方法。

请查看OpenCV的fitline函数以获取更多详细信息和参数。

由于您已经尝试过霍夫线,我将在此演示使用OpenCV-Python进行拟合直线:

# Load image, convert to grayscale, threshold and find contours
img = cv2.imread('lail.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
contours,hier = cv2.findContours(thresh,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]

# then apply fitline() function
[vx,vy,x,y] = cv2.fitLine(cnt,cv2.cv.CV_DIST_L2,0,0.01,0.01)

# Now find two extreme points on the line to draw line
lefty = int((-x*vy/vx) + y)
righty = int(((gray.shape[1]-x)*vy/vx)+y)

#Finally draw the line
cv2.line(img,(gray.shape[1]-1,righty),(0,lefty),255,2)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

以下是我得到的结果:

在此输入图片描述

在此输入图片描述

编辑:

如果您想找到将对象分成两部分的线,请先找到适合的线,然后找到与之垂直的线。

为此,在cv2.fitLine()函数下添加以下代码片段:

nx,ny = 1,-vx/vy
mag = np.sqrt((1+ny**2))
vx,vy = nx/mag,ny/mag

以下是我得到的结果:

enter image description here

enter image description here

希望这能帮助你!

更新:

以下是您要求的第一种情况的Python代码的C++代码。 该代码对我完美运行。 输出与上面给出的相同:

#include <iostream>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv/cv.h>

using namespace std;
using namespace cv;

int main()
{
    cv::Mat img, gray,thresh;
    vector<vector<Point>> contours;
    Vec4f lines;

    img = cv::imread("line.png");
    cv::cvtColor(img,gray,cv::COLOR_BGR2GRAY);
    cv::threshold(gray,thresh,127,255,cv::THRESH_BINARY);
    cv::findContours(thresh,contours,cv::RETR_LIST,cv::CHAIN_APPROX_SIMPLE);
    cv::fitLine(Mat(contours[0]),lines,2,0,0.01,0.01);

    //lefty = int((-x*vy/vx) + y)
    //righty = int(((gray.shape[1]-x)*vy/vx)+y)
    int lefty = (-lines[2]*lines[1]/lines[0])+lines[3];
    int righty = ((gray.cols-lines[2])*lines[1]/lines[0])+lines[3];

    cv::line(img,Point(gray.cols-1,righty),Point(0,lefty),Scalar(255,0,0),2);

    cv::imshow("img",img);
    cv::waitKey(0);
    cv::destroyAllWindows();
}

1
非常感谢,我今天会试试看 :D哦,我是你博客的粉丝 :) - Luis Carlos
1
大家好,所有的函数都是来自于OpenCV的标准函数。因此,如果您查看opencv文档,您可以找到我使用的每个python函数对应的C++函数。请尝试自己操作,如果您遇到任何困难,请在评论中提出。我会尽力帮助您... - Abid Rahman K
1
+1 - 谢谢,很高兴知道您从我的博客中受益。请继续访问,并在喜欢的情况下分享。 - Abid Rahman K
2
很抱歉让你等了这么久。我完成了,谢谢 :) 请查看我的最新项目:http://www.youtube.com/watch?v=zXHXusO8eGw - Luis Carlos
这确实也帮助了我!谢谢。 - Ivantha
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接