【问题标题】:cv::gpu::HoughLines is not working properlycv::gpu::HoughLines 无法正常工作
【发布时间】:2013-12-05 22:52:51
【问题描述】:

我正在尝试在 cv::gpu::GpuMat 结构上使用 霍夫变换 检测一些行。我尝试过同时使用gpu::HoughLinesgpu::HoughLinesP,但即使阈值极低,我也没有得到任何结果。在调试过程中,我看到应该包含结果的容器 (houghLines) 里面只存储了零。我写的代码如下,

static cv::Mat drawHoughLinesOnMat (cv::gpu::GpuMat hough_Mat, cv::gpu::GpuMat houghLines)
{
    cv::Mat output_Mat;
    cv::cvtColor(cv::Mat(hough_Mat), output_Mat, CV_GRAY2BGR);

    std::vector<cv::Vec4i> lines_vector;
    if (!houghLines.empty())
    {
        lines_vector.resize(houghLines.cols);
        cv::Mat temp_Mat (1, houghLines.cols, CV_8UC3, &lines_vector[0]);
        houghLines.download (temp_Mat);
    }

    for (size_t i=0; i<lines_vector.size(); ++i)
    {
        cv::Vec4i l = lines_vector[i];
        cv::line(output_Mat, cv::Point(l[0], l[1]), cv::Point(l[2], l[3]), cv::Scalar(0, 0, 255), 1, 8);
    }

    return output_Mat;
}


int main()
{
    cv::Mat input = cv::imread(INPUT_DATA_1->c_str(), CV_LOAD_IMAGE_GRAYSCALE);
    std::string imageType = getImgType(input.type());

    cv::gpu::GpuMat mat_input(input), bil_out, mat_thresh, hough_lines;
    cv::gpu::HoughLinesBuf hough_buffer;

    int bilateral_thresh = 15; // 5 == 0.085s; 15 == 0.467s at run-time
    cv::gpu::bilateralFilter(mat_input, bil_out, bilateral_thresh, bilateral_thresh*2, bilateral_thresh/2);
    //cv::gpu::threshold(bil_out, mat_thresh, 10, 255, CV_THRESH_BINARY);
    cv::gpu::Canny(bil_out, mat_thresh, 10, 60, 5);

    cv::gpu::HoughLinesP(mat_thresh, hough_lines, hough_buffer, 1.0f, (float)(CV_PI/180.0f), 5, 1);
    //cv::Mat test_hough(hough_lines);
    cv::Mat hough_Mat = drawHoughLinesOnMat(mat_input, hough_lines);
    cv::gpu::HoughLines(mat_thresh, hough_lines,  1.0f, (float)(CV_PI/180.0f),   1, true);
    /*cv::Mat */hough_Mat = drawHoughLinesOnMat(mat_input, hough_lines);

    return EXIT_SUCCESS
}

我使用的图片是,

谁能告诉我我做错了什么......?提前致谢!

Canny 过滤器的输出是,

编辑:

我已经在 HoughLines 的 CPU 版本上进行了测试,它似乎工作得很好。

EDIT_2:

@jet47 发布的解决方案完美运行。

【问题讨论】:

  • 应用 Canny 滤镜后的图像效果如何?
  • 哦,等一下。我会发布它。它已经起来了。
  • 你使用的是什么版本的 OpenCv?
  • 我在 Windows x64 机器上使用 2.4.6。
  • 您可以尝试的一件事是使用cvtColor 创建一个Mask 并从那里获取您的gpuMat(如示例代码中所示)[github.com/Itseez/opencv/blob/2.4/samples/gpu/houghlines.cpp] 但这是一个很长的镜头......

标签: c++ opencv image-processing cuda gpu


【解决方案1】:

您使用错误的代码将结果从 GPU 下载回 CPU:

lines_vector.resize(houghLines.cols);
cv::Mat temp_Mat (1, houghLines.cols, CV_8UC3, &lines_vector[0]);
houghLines.download (temp_Mat);

temp_Mat - CV_8UC3 的类型不正确,它必须是 CV_32SC4

正确的代码是:

lines_vector.resize(houghLines.cols);
cv::Mat temp_Mat(1, houghLines.cols, CV_32SC4, &lines_vector[0]);
houghLines.download(temp_Mat);

【讨论】:

  • 您能否解释一下为什么它需要是CV_32SC4 而不是CV_8UC3..?老实说,我对此并不完全清楚..
  • lines_vectorcv::Vec4i 的向量。 cv::Vec4i 是 32 位整数值的 4 分量向量。所以它是一个CV_32SC4,而CV_8UC3 是一个3 通道8 位值。 GpuMat::download 方法检查输出矩阵的类型,如果类型不匹配则重新分配数据。
  • 太棒了,感谢您的解释。我已经试过了,效果很好。
【解决方案2】:

我的猜测是您使用的方法已经过时(但我不完全确定)。

我就是这样做的(如Example Code 所示):

//d_src filled with your image somewhere
GpuMat d_lines;
{
    Ptr<cuda::HoughSegmentDetector> hough = cuda::createHoughSegmentDetector(1.0f, (float) (CV_PI / 180.0f), 50, 5);

    hough->detect(d_src, d_lines);
}

vector<Vec4i> lines_gpu;
if (!d_lines.empty())
{
    lines_gpu.resize(d_lines.cols);
    Mat h_lines(1, d_lines.cols, CV_32SC4, &lines_gpu[0]);
    d_lines.download(h_lines);
}

for (size_t i = 0; i < lines_gpu.size(); ++i)
{
    Vec4i l = lines_gpu[i];
    line(dst_gpu, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, LINE_AA);
}

EDIT以上使用OpenCv 3.0接口

【讨论】:

  • 这是3.0的界面吧..?我需要让它在 2.4.x 接口上工作,因为这是使用 cv 2.4 的更大应用程序的一部分。我也遵循了相同的示例(但对于 2.4.6),但我没有得到任何东西..
  • 是的,我想是的,但我会将答案留给使用 3.0 的人。在你的情况下,这似乎是另一个问题。
  • 谢谢。我对正在发生的事情完全不知所措。起初我以为是因为 GPU 模块没有正确构建,但事实并非如此,因为其他东西都可以正常工作。