【问题标题】:OpenCV Probabilistic Hough Line Transform giving different results with C++ and Python?OpenCV 概率霍夫线变换使用 C++ 和 Python 给出不同的结果?
【发布时间】:2021-02-03 07:00:06
【问题描述】:

我正在使用 OpenCV 开发一个项目,Python 在项目的某些部分使用概率霍夫线变换函数“HoughLinesP”。我的代码工作得很好,没有问题。然后我想到了将相同的代码转换为 C++。

代码转换成C++后,输出与Python代码不一样。经过长时间的调试,我发现其他一切正常,但在 C++ 的情况下,“HoughLinesP”函数给出了不同的输出。两种语言中这个函数的输入是一样的,参数的值也是一样的,但是输出是不同的。

谁能解释一下为什么会发生这种情况以及任何可能的解决方法?

另外,我检查了两种语言的 OpenCV 版本,它是相同的: 4.5.0 dev 另外,我尝试过使用传递给 C++ 代码的值,但我无法获得类似的结果。

输入边缘图像:

Python HoughLinesP() 输出:

C++ HoughLinesP() 输出:

以下是每种语言的代码: 蟒蛇:

Lines = cv2.HoughLinesP(EdgeImage, 1, np.pi / 180, 50, 10, 15)

C++:

std::vector<cv::Vec4i> Lines;
cv::HoughLinesP(EdgeImage, Lines, 1, CV_PI / 180, 50, 10, 15);

如果有人能提出建议,那将是一个很大的帮助。

【问题讨论】:

    标签: python c++ opencv hough-transform houghlinesp


    【解决方案1】:

    解释与修正

    问题的出现是因为在 Python 版本中您没有设置您认为您正在设置的参数。与在 Python 接口中调整参数列表的其他一些函数相比,HoughLinesP 不仅返回行,而且还为行输出采用参数 lines。你可以在HoughLinesP的帮助中看到:

    import cv2
    help(cv2.HoughLinesP)
    

    这给了你(省略号我的):

    Help on built-in function HoughLinesP:
    
    HoughLinesP(...)
        HoughLinesP(image, rho, theta, threshold[, lines[, minLineLength[, maxLineGap]]]) -> lines
        .   @brief Finds line segments in a binary image using the probabilistic Hough transform.
        .   
    ...
        .   @param lines Output vector of lines. Each line is represented by a 4-element vector
        .   \f$(x_1, y_1, x_2, y_2)\f$ , where \f$(x_1,y_1)\f$ and \f$(x_2, y_2)\f$ are the ending points of each detected
        .   line segment.
    ...
    

    所以基本上,在您的 python 示例中,您将 10 传递为 lines 而不是 minLineLength。要解决此问题,您可以将空数组作为lines 传递,也可以将参数作为关键字参数传递:

    Lines = cv2.HoughLinesP(EdgeImage, rho=1, theta=np.pi/180,
                            threshold=50, minLineLength=10, maxLineGap=15)
    

    这样做应该使您的 Python 版本的输出与 C++ 版本的输出匹配。

    或者,如果您对 Python 版本的结果感到满意,则必须省略参数 lines(即仅将 minLineLength 设置为 15 并为 maxLineGap 使用默认值 0 [see docs] ):

    std::vector<cv::Vec4i> Lines;
    cv::HoughLinesP(EdgeImage, Lines, 1, CV_PI / 180, 50, 15);
    

    这应该会重现您的 Python 版本。

    示例

    使用openCV documentation of HoughLinesP 中列出的示例,您可以看到这解决了问题。

    C++ 版本

    (取自上面列出的 openCV 文档并改为保存图像。)

    #include <opencv2/imgproc.hpp>
    #include <opencv2/highgui.hpp>
    using namespace cv;
    using namespace std;
    int main(int argc, char** argv)
    {
        Mat src, dst, color_dst;
        if( argc != 3 || !(src=imread(argv[1], 0)).data)
            return -1;
        Canny( src, dst, 50, 200, 3 );
        cvtColor( dst, color_dst, COLOR_GRAY2BGR );
        vector<Vec4i> lines;
        HoughLinesP( dst, lines, 1, CV_PI/180, 80, 30, 10 );
        for( size_t i = 0; i < lines.size(); i++ )
        {
            line( color_dst, Point(lines[i][0], lines[i][1]),
            Point( lines[i][2], lines[i][3]), Scalar(0,0,255), 3, 8 );
        }
        imwrite( argv[2], color_dst );
        return 0;
    }
    

    如果你编译它并在文档中提供的示例图片上运行它,你会得到以下结果:

    Python 版本不正确

    (基本上,只是没有lines参数的翻译后的C++版本。)

    import argparse
    import cv2
    import numpy as np
    
    parser = argparse.ArgumentParser()
    parser.add_argument("input_file", type=str)
    parser.add_argument("output_file", type=str)
    args = parser.parse_args()
    
    src = cv2.imread(args.input_file, 0)
    dst = cv2.Canny(src, 50., 200., 3)
    color_dst = cv2.cvtColor(dst, cv2.COLOR_GRAY2BGR)
    lines = cv2.HoughLinesP(dst, 1., np.pi/180., 80, 30, 10.)
    for this_line in lines:
        cv2.line(color_dst,
                (this_line[0][0], this_line[0][1]),
                (this_line[0][2], this_line[0][3]),
                [0, 0, 255], 3, 8)
    cv2.imwrite(args.output_file, color_dst)
    

    运行它会产生以下(不同的)结果:

    修正了 python 版本

    (通过传递关键字参数来修复)

    import argparse
    import cv2
    import numpy as np
    
    parser = argparse.ArgumentParser()
    parser.add_argument("input_file", type=str)
    parser.add_argument("output_file", type=str)
    args = parser.parse_args()
    
    src = cv2.imread(args.input_file, 0)
    dst = cv2.Canny(src, 50., 200., 3)
    color_dst = cv2.cvtColor(dst, cv2.COLOR_GRAY2BGR)
    lines = cv2.HoughLinesP(dst, rho=1., theta=np.pi/180.,
                            threshold=80, minLineLength=30, maxLineGap=10.)
    for this_line in lines:
        cv2.line(color_dst,
                (this_line[0][0], this_line[0][1]),
                (this_line[0][2], this_line[0][3]),
                [0, 0, 255], 3, 8)
    cv2.imwrite(args.output_file, color_dst)
    

    这给出了正确的结果(即与 C++ 版本相同的结果):

    【讨论】:

    • 非常感谢@jotasi 的回答。你救了我。 :) ...我只是想知道当我从 C++ 中删除“10”时,结果与 python 的结果完全相同。那么Python中变量“10”(参数-“lines”)有什么用。为什么它甚至被当作输入?
    • @RahulKedia 我猜(虽然没有尝试过)你可以传入一个 numpy 数组,然后用这些行填充。否则,没有线索。
    • 好的,谢谢@jotasi,我刚刚完成了我的项目,C++ 和 Python 代码现在给出了相同的输出。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多