找到指向图像中单向的所有线条

时间:2018-01-23 23:11:11

标签: opencv image-processing filtering

我正试图想出一个过滤器,只显示指向一个方向的线条。

假设我们的原始图像如此: Original Image

我需要应用什么过滤器来仅选择垂直线。就像这里用红色突出显示的那些。 Red Highlight on Vertical lines

这个过滤器可以是通用的,允许我选择其他方向吗?例如,从左下角到右上角的对角线。

1 个答案:

答案 0 :(得分:1)

最简单(尽管不是最快)的解决方案是使用Hough变换来检测线条,然后测量线条的斜率并仅留下垂直线条。

请先查看本教程https://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/hough_lines/hough_lines.html

这是一个代码示例,可以或多或少地解决您的问题。您可能需要调整一些参数以获得更好的结果:

std::vector<cv::Vec4i> extractVerticalLines(const std::vector<cv::Vec4i>& lines, int tollerance)
{
    std::vector<cv::Vec4i> output;
    for(const auto& line : lines)
    {
        // subtract x0 and x1 component (horizontal beginning and horizontal end)
        if(std::abs(line[0] - line[2]) <= tollerance)
        {
            output.push_back(line);
        }
    }

    return output;
}

void drawLines(cv::Mat& inputImage, const std::vector<cv::Vec4i>& lines, const cv::Scalar& color, int thickness)
{
    for(const auto& line : lines)
    {
        cv::line(inputImage, cv::Point2i(line[0], line[1]), cv::Point2i(line[2], line[3]), color, thickness);
    }
}

std::vector<cv::Vec4i> extractAllLines(const cv::Mat& image, int threshold, double minLength = 100)
{
    std::vector<cv::Vec4i> lines;
    cv::HoughLinesP(image, lines, 1, CV_PI / 180, threshold, minLength);
    return lines;
}

int main()
{
    auto image = cv::imread("lines.png", cv::IMREAD_GRAYSCALE);
    auto output = cv::Mat(image.size(), image.type(), cv::Scalar::all(0));
    image = ~image; // invert colors because background should be black and lines white

    auto lines = extractAllLines(image, 50);
    auto verticalLines = extractVerticalLines(lines, 5);
    drawLines(output, verticalLines, cv::Scalar::all(255), 1);
    cv::imshow("Result", output);
    cv::waitKey(0);
}

这会产生以下结果: Result 请记住,在输出中有多行合并在一起。如果您希望垂直方向只有一条线,则必须首先对图像进行骨架化,以使所有内容都厚度为1px,或尝试对结果进行一些智能过滤。