Improve HoughLines for horizontal lines detect (Python, OpenCV)

4.6k Views Asked by At

I have this source image:

src

My goal is to remove the bottom line while keep the letters/numbers untouched.

This is the code I use:

import cv2
import numpy as np

img = cv2.imread('src.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

edges = cv2.Canny(gray,100,200,apertureSize = 5)

minLineLength = 0
maxLineGap = 19
lines = cv2.HoughLinesP(edges,1,np.pi/180,15,minLineLength,maxLineGap)
for x in range(0, len(lines)):
    for x1,y1,x2,y2 in lines[x]:
        cv2.line(img,(x1,y1),(x2,y2),(255,255,255),2)

cv2.imshow('hough',img)
cv2.waitKey(0)

The best result I achieved by now is this:

out

How can I improve it more, to clean the image as much as possible ? For example, all the debris all around the image, points and (still) lines under the words, how can I remove them ?

Thank you.

OT: is there a way to create a trackbar of this which change the parameters (apertureSize, minLineLength, maxLineGap, etc) to see results in real time ?

2

There are 2 best solutions below

0
On BEST ANSWER

As per @Link 's request:

I have limited experience in python so I don't know how thread safe this code is, but this should show you the basics of creating trackbars in python OpenCV.

def onChange(pos):
    global img
    global gray
    global dst

    dst = np.copy(img)

    apertureSize = cv2.getTrackbarPos("ApertureSize", "Result")
    minLineLength = cv2.getTrackbarPos("LineLength", "Result")
    maxLineGap = cv2.getTrackbarPos("LineGap", "Result")

    # according to OpenCV, aperture size must be odd and between 3 and 7
    if apertureSize % 2 == 0:
        apertureSize += 1
    if apertureSize < 3:
        apertureSize = 3

    edges = cv2.Canny(gray,100,200,apertureSize = apertureSize)

    lines = cv2.HoughLinesP(edges,1,np.pi/180,15,minLineLength,maxLineGap)
    for x in range(0, len(lines)):
        for x1,y1,x2,y2 in lines[x]:
            cv2.line(dst,(x1,y1),(x2,y2),(255,255,255),2)

#Run Main
if __name__ == "__main__" :

    img = cv2.imread("image.png", -1)
    dst = np.copy(img)

    cv2.namedWindow("Result", cv2.WINDOW_NORMAL)

    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    #default values for trackbars
    defaultApertureSize = 5
    minLineLength = 0
    maxLineGap = 19

    # according to OpenCV, aperture size must be odd and between 3 and 7
    # the aperture size range is (0 - 6)
    cv2.createTrackbar("ApertureSize", "Result", defaultApertureSize, 6, onChange)

    # line length range is (0 - 10)
    cv2.createTrackbar("LineLength", "Result", minLineLength, 10, onChange)

    # line gap range is (0 - 19)
    cv2.createTrackbar("LineGap", "Result", maxLineGap, 19, onChange)

    while True:
        cv2.imshow("Result", dst)
        key = cv2.waitKey(1)
        if key == ord('q'):
            break

    cv2.destroyAllWindows()
1
On

Once you have the line segments from Hough you could search them to find the ones likely to be part of the bottom line (ie correct angle and intercept) then remove all black dots along this predicted line rather than just the segments found by hough.

Another tip, try cv::adaptivethreshold rather than canny and try doing a small Gaussian blur first to remove background specks.

Edit: You are using HoughP which finds each lien segment individually. You are looking for a single (broken) line so would probably be better using regular Hough and from the results select the strongest horizontal line in the bottom half of the image - then erase all dots along that direction.

ot: the cv::namedWindow can have a trackbar where you can easily get back the value