5 Effective Ways to Remove Horizontal Lines in Images Using OpenCV, Python, and Matplotlib

Efficient Techniques for Removing Horizontal Lines in Images Using OpenCV, Python, and Matplotlib

๐Ÿ’ก Problem Formulation: When processing images, removing horizontal lines is a common task, particularly in scenarios like removing lines from scanned documents or cleaning up graphical plots. For instance, in OCR preprocessing, horizontal lines in a scanned document can interfere with text detection. This article tackles the problem with several methods using OpenCV, Python, and Matplotlib. We’ll start with images containing horizontal lines and demonstrate how each method can effectively remove those lines to produce clean images.

Method 1: Morphological Operations

Morphological operations are a set of image processing techniques that process images based on shapes. In OpenCV, morphological operations can be used to emphasize or diminish specific structures within an image. Specifically for horizontal line removal, a combination of erosion and dilation operations, known as morphological opening, can be applied to remove horizontal lines while retaining other important features.

Here’s an example:

import cv2
import numpy as np

# Read image
image = cv2.imread('input_image.png', 0)
# Define a horizontal kernel
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (25,1))
# Perform morphological opening (erosion followed by dilation)
opened_image = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)

cv2.imwrite('output_image.png', opened_image)
    

Output: A processed image file ‘output_image.png’ with diminished horizontal lines.

We read the input image and define a horizontal kernel that dictates the shape and size of structures to be removed. An opening operation is then applied to the grayscale image, which effectively removes the horizontal lines. The result is an image that retains most of its original content with the horizontal lines significantly reduced or removed.

Method 2: Hough Line Transformation

The Hough Line Transformation is a feature extraction technique used in image analysis to detect straight lines. By implementing the Hough transform, we can identify the locations of horizontal lines in an image and then remove or alter them as required. It’s particularly useful when the lines to be removed are quite distinct from the background.

Here’s an example:

import cv2
import numpy as np

# Read image
image = cv2.imread('input_image.png', 0)
# Detect edges using Canny
edges = cv2.Canny(image, 50, 150)
# Detect lines using HoughLinesP
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, threshold=100, minLineLength=100, maxLineGap=10)

# Draw white lines on the detected coordinates
for line in lines:
    x1, y1, x2, y2 = line[0]
    if y1 == y2: # Horizontal line
        cv2.line(image, (x1, y1), (x2, y2), (255, 255, 255), 2)

cv2.imwrite('output_image.png', image)
    

Output: An image ‘output_image.png’ with the horizontal lines overwritten with white color, effectively removing them.

We first detect edges in the input image using the Canny detector. Then, we apply the HoughLinesP function to find lines, which returns an array of the endpoints of detected lines. Within a simple loop, we identify horizontal lines and draw over them in white, concealing them against a white background.

Method 3: Contour Detection and Removal

Contour detection is another technique that finds continuous lines and curves in binary images. After contours are detected, we can filter out the contours that have characteristics of horizontal linesโ€”mainly by analyzing their geometric propertiesโ€”and remove them from the image.

Here’s an example:

import cv2

# Read image
image = cv2.imread('input_image.png', 0)
# Threshold image to prepare for contour detection
_, thresh = cv2.threshold(image, 150, 255, cv2.THRESH_BINARY_INV)
# Find contours
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Filter and remove horizontal contours
for cnt in contours:
    x, y, w, h = cv2.boundingRect(cnt)
    if w > h:
        cv2.drawContours(image, [cnt], 0, (255, 255, 255), -1)

cv2.imwrite('output_image.png', image)
    

Output: An image file ‘output_image.png’ from which horizontal contours have been removed.

This code snippet begins by thresholding the image to a binary form suitable for contour detection. Upon finding contours, it filters for those with a wider width than height, indicating a likely horizontal element, and fills them with white pixels, effectively erasing the horizontal lines.

Method 4: Frequency Domain Filtering

Frequency domain filtering involves transforming the image into the frequency domain to analyze the frequency components of the image. Horizontal lines, which represent a certain frequency pattern, can be filtered out in this domain before converting the image back to the spatial domain.

Here’s an example:

import cv2
import numpy as np

# Read image
image = cv2.imread('input_image.png', 0)
# Fourier Transform the image
f = np.fft.fft2(image)
f_shift = np.fft.fftshift(f)

# Create a mask to remove high frequency components along the x-axis
rows, cols = image.shape
crow, ccol = rows//2 , cols//2
f_shift[crow-10:crow+10, :] = 0

# Inverse Fourier Transform
f_ishift = np.fft.ifftshift(f_shift)
img_back = np.fft.ifft2(f_ishift)
img_back = np.abs(img_back)

cv2.imwrite('output_image.png', img_back)
    

Output: A filtered image ‘output_image.png’ where horizontal line frequency components have been suppressed.

The Fast Fourier Transform (FFT) is applied to the image, and then a mask is created to nullify high-frequency components horizontally centered in the transformed image. An inverse FFT is then used to convert the image back, with the result being an image where horizontal line patterns have been significantly reduced.

Bonus One-Liner Method 5: SeamlessClone Blurring

Using the SeamlessClone function in OpenCV, it’s possible to blur horizontal lines by cloning a section of the image adjacent to the line over the line itself in a seamless manner, merging it with the surrounding pixels.

Here’s an example:

import cv2
import numpy as np

# Read image
image = cv2.imread('input_image.png')
mask = np.zeros(image.shape[:2], np.uint8)
# Assume the horizontal line coordinates are known and use them to define the mask
cv2.line(mask, (line_start, line_row), (line_end, line_row), 1, thickness)
# SeamlessClone with normal cloning
output = cv2.seamlessClone(image, image, mask, (line_end//2, line_row), cv2.NORMAL_CLONE)

cv2.imwrite('output_image.png', output)
    

Output: The horizontal lines are seamlessly merged into the surrounding area in ‘output_image.png’, making them disappear.

This code involves creating a mask where the horizontal lines are marked, and then using the SeamlessClone function to blend these areas with adjacent parts of the image. The lines are effectively blurred into the background with a smooth, seamless transition.

Summary/Discussion

  • Method 1: Morphological Operations. Well-suited for images with uniform horizontal lines. It’s quick and effective but can also affect non-linear structures if not tuned properly.
  • Method 2: Hough Line Transformation. Precise line detection method. Requires well-defined edges, so pre-processing is essential. Can be compute-intensive for larger images.
  • Method 3: Contour Detection and Removal. Good for defining and manipulating shapes but can be sensitive to image quality and noise, potentially leading to inaccurate contour detection.
  • Method 4: Frequency Domain Filtering. Targets the underlying patterns of lines, offering a comprehensive removal strategy. However, it’s complex compared to spatial domain methods and requires understanding of signal processing.
  • Bonus Method 5: SeamlessClone Blurring. Provides a visually appealing result without discernible alterations in most cases. Requires knowledge of the lines’ approximate locations and may be less automated compared to other methods.