Removing long horizontal/vertical lines from edge image using OpenCV

前端 未结 5 1956
半阙折子戏
半阙折子戏 2020-12-31 12:45

How can I use standard image processing filters (from OpenCV) to remove long horizontal and vertical lines from an image?

The images are B&W so removing means si

相关标签:
5条回答
  • 2020-12-31 12:59

    if your lines are truly horizontal/vertical, try this

    import cv2
    import numpy as np
    img = cv2.imread('c:/data/test.png')
    gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    linek = np.zeros((11,11),dtype=np.uint8)
    linek[5,...]=1
    x=cv2.morphologyEx(gray, cv2.MORPH_OPEN, linek ,iterations=1)
    gray-=x
    cv2.imshow('gray',gray)
    cv2.waitKey(0)    
    

    result

    enter image description here

    You can refer OpenCV Morphological Transformations documentation for more details.

    0 讨论(0)
  • 2020-12-31 13:07

    To remove Horizontal Lines from an image you can use an edge detection algorithm to detect edges and then use Hough's Transform in OpenCV to detect lines and color them white:

    import cv2
    import numpy as np
    img = cv2.imread(img,0)
    laplacian = cv2.Laplacian(img,cv2.CV_8UC1) # Laplacian Edge Detection
    minLineLength = 900
    maxLineGap = 100
    lines = cv2.HoughLinesP(laplacian,1,np.pi/180,100,minLineLength,maxLineGap)
    for line in lines:
        for x1,y1,x2,y2 in line:
            cv2.line(img,(x1,y1),(x2,y2),(255,255,255),1)
    cv2.imwrite('Written_Back_Results.jpg',img)
    
    0 讨论(0)
  • 2020-12-31 13:14

    Another one.

    package com.test12;
    
    import org.opencv.core.*;
    import org.opencv.imgproc.Imgproc;
    import org.opencv.imgcodecs.Imgcodecs;
    
    public class ImageSubstrate {
    
        static{ System.loadLibrary(Core.NATIVE_LIBRARY_NAME); }
    
        public static void main(String[] args) {
    
               Mat source = Imgcodecs.imread("src//data//bill.jpg");
    
               Mat image_h = Mat.zeros(source.size(), CvType.CV_8UC1);
               Mat image_v = Mat.zeros(source.size(), CvType.CV_8UC1); 
    
               Mat output = new Mat();
               Core.bitwise_not(source, output);
               Mat output_result = new Mat();
    
               Mat kernel_h = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(20, 1));
               Imgproc.morphologyEx(output, image_h, Imgproc.MORPH_OPEN, kernel_h);
               Imgcodecs.imwrite("src//data//output.jpg", output);  
    
               Core.subtract(output, image_h, output_result);
               Imgcodecs.imwrite("src//data//output_result.jpg", output_result);    
    
    
               Mat kernel_v = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(1, 20));   
               Imgproc.morphologyEx(output_result, image_v, Imgproc.MORPH_OPEN, kernel_v);
               Mat output_result2 = new Mat();
    
               Core.subtract(output_result, image_v, output_result2);          
               Imgcodecs.imwrite("src//data//output_result2.jpg", output_result2);
        }
    }
    
    0 讨论(0)
  • 2020-12-31 13:16

    How long is "long". Long, as in, lines that run the length of the entire image, or just longer than n pixels?

    If the latter, then you could just use an n+1 X n+1 median or mode filter, and set the corner coefficients to zero, and you'd get the desired effect.

    If you're referring to just lines that run the width of the entire image, just use the memcmp() function against a row of data, and compare it to a pre-allocated array of zeros which is the same length as a row. If they are the same, you know you have a blank line that spans the horizontal length of the image, and that row can be deleted.

    This will be MUCH faster than the element-wise comparisons you are currently using, and is very well explained here:

    Why is memcpy() and memmove() faster than pointer increments?

    If you want to repeat the same operation for vertical lines, just transpose the image, and repeat the operation.

    I know this is more of a system-optimization level approach than an openCV filter like you requested, but it gets the job done fast and safely. You can speed up the calculation even more if you manage to force the image and your empty array to be 32-bit aligned in memory.

    0 讨论(0)
  • 2020-12-31 13:21

    This is for javacv.

    package com.test11;

    import org.opencv.core.*;
    import org.opencv.imgproc.Imgproc;
    import org.opencv.imgcodecs.Imgcodecs;
    
    public class GetVerticalOrHorizonalLines {
    
        static{ System.loadLibrary(Core.NATIVE_LIBRARY_NAME); }
    
        public static void main(String[] args) {
    
            //Canny process before HoughLine Recognition
    
            Mat source = Imgcodecs.imread("src//data//bill.jpg");
            Mat gray = new Mat(source.rows(),source.cols(),CvType.CV_8UC1);
            Imgproc.cvtColor(source, gray, Imgproc.COLOR_BGR2GRAY);
    
            Mat binary = new Mat();
            Imgproc.adaptiveThreshold(gray, binary, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 15, -2);
            Imgcodecs.imwrite("src//data//binary.jpg", binary);
    
            Mat horizontal = binary.clone();
            int horizontalsize = horizontal.cols() / 30;
            int verticalsize = horizontal.rows() / 30;
    
            Mat horizontal_element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(horizontalsize,1));
            //Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3,3));
            Imgcodecs.imwrite("src//data//horizontal_element.jpg", horizontal_element);
    
            Mat Linek = Mat.zeros(source.size(), CvType.CV_8UC1);
            //x =  Imgproc.morphologyEx(gray, dst, op, kernel, anchor, iterations);
            Imgproc.morphologyEx(gray, Linek,Imgproc.MORPH_BLACKHAT, horizontal_element);
            Imgcodecs.imwrite("src//data//bill_RECT_Blackhat.jpg", Linek);
    
            Mat vertical_element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(1,verticalsize));
            Imgcodecs.imwrite("src//data//vertical_element.jpg", vertical_element);
    
            Mat Linek2 = Mat.zeros(source.size(), CvType.CV_8UC1);
            //x =  Imgproc.morphologyEx(gray, dst, op, kernel, anchor, iterations);
            Imgproc.morphologyEx(gray, Linek2,Imgproc.MORPH_CLOSE, vertical_element);
            Imgcodecs.imwrite("src//data//bill_RECT_Blackhat2.jpg", Linek2);
    
                }
        }
    
    0 讨论(0)
提交回复
热议问题