如何去除精巧边缘图像中的长边缘?

Posted

技术标签:

【中文标题】如何去除精巧边缘图像中的长边缘?【英文标题】:How to remove long edges in a canny edge image? 【发布时间】:2016-10-19 09:23:10 【问题描述】:

处理精明边缘检测后,我得到边缘图像。 但我只想保持短边(边缘来自角色)。 并且有一些长边(这里我定义为超过图片高度的一半)。示例图片如下所示:

那么如何去除超过图片一半高度的边缘?

相关问题: remove horizontal/vertical long edges

【问题讨论】:

【参考方案1】:

您可以对包含边缘的minAreaRect 应用一些约束。 你可以找到一个例子here,但是由于你的边缘接触到了边框,你需要一个额外的技巧来让findContours正常工作,所以下面是改进的代码。

通过对纵横比的简单约束,您可以得到:

您删除了 红色 边缘的位置:

您可以添加额外的约束,例如在height 上,以满足您的特定目的。

代码如下:

#include<opencv2/opencv.hpp>
using namespace cv;


int main()

    // Load image
    Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);

    // Remove JPG artifacts
    img = img > 200;

    Mat1b result = img.clone();

    // Create output image
    Mat3b out;
    cvtColor(img, out, COLOR_GRAY2BGR);

    // Find contours
    Mat1b padded;
    copyMakeBorder(img, padded, 1, 1, 1, 1, BORDER_CONSTANT, Scalar(0));
    vector<vector<Point>> contours;
    findContours(padded, contours, RETR_LIST, CHAIN_APPROX_NONE, Point(-1, -1));

    for (const auto& contour : contours)
    
        // Find minimum area rectangle
        RotatedRect rr = minAreaRect(contour);

        // Compute aspect ratio
        float aspect_ratio = min(rr.size.width, rr.size.height) / max(rr.size.width, rr.size.height);

        // Define a threshold on the aspect ratio in [0, 1]
        float thresh_ar = 0.05f;

        // Define other constraints

        bool remove = false;
        if (aspect_ratio < thresh_ar) 
            remove = true;
        

        // if(some_other_constraint)  remove = true; 

        Vec3b color;
        if (remove) 
            // Almost straight line
            color = Vec3b(0, 0, 255); // RED

            // Delete edge
            for (const auto& pt : contour) 
                result(pt) = uchar(0);
            
        
        else 
            // Curved line
            color = Vec3b(0, 255, 0); // GREEN
        

        // Color output image
        for (const auto& pt : contour) 
            out(pt) = color;
        
    

    imshow("Out", out);
    imshow("Result", result);
    waitKey();

    return 0;

【讨论】:

太棒了!感谢您的解决方案。你能给我一些关于如何去除我不需要的其他边缘的建议(比如右边的边缘,但它们不够长)? 稍微增加thresh_ar,例如至 0.075 或 0.1。对字母的最大高度进行一些限制......像这样......它确实特定于您的上下文。只有边缘可以去除一些噪音,但你需要更强大的东西来去除除了你的字母之外的所有东西 非常感谢。我会试试看的!

以上是关于如何去除精巧边缘图像中的长边缘?的主要内容,如果未能解决你的问题,请参考以下文章

目标 C:如何在不损失边缘质量的情况下从 JPG 图像中去除白色背景

OpenCV - 计算图像的边缘强度

如何在 Python 中像 edge() Matlab 函数一样制作精巧的边缘检测器

PyQt5中的Matplotlib:如何去除边缘的小空间

六 OpenCV图像处理4 Canny 边缘检测

OpenCV Canny边缘检测 | 图像轮廓检测 | 直方图均衡化