Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting vertical lines using Hough transforms in opencv

Tags:

python

opencv

I'm trying to remove the square boxes(vertical and horizontal lines) using Hough transform in opencv (Python). The problem is none of the vertical lines are being detected. I've tried looking through contours and hierarchy but there are too many contours in this image and I'm confused how to use them.

After looking through related posts, I've played with the threshold and rho parameters but that didn't help. I've attached the code for more details. Why does Hough transform not find the vertical lines in the image?. Any suggestions in solving this task are welcome. Thanks.

Input Image : enter image description here

Hough transformed Image: enter image description here

Drawing contours: enter image description here

import cv2
import numpy as np
import pdb


img = cv2.imread('/home/user/Downloads/cropped/robust_blaze_cpp-300-0000046A-02-HW.jpg')

gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 140, 255, 0)
im2, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (0,0,255), 2)

edges = cv2.Canny(gray,50,150,apertureSize = 3)
minLineLength = 5
maxLineGap = 100
lines = cv2.HoughLinesP(edges,rho=1,theta=np.pi/180,threshold=100,minLineLength=minLineLength,maxLineGap=maxLineGap)
for x1,y1,x2,y2 in lines[0]:
    cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)

cv2.imwrite('probHough.jpg',img)
like image 477
Dheeraj Peri Avatar asked Nov 28 '22 22:11

Dheeraj Peri


1 Answers

To be honest, rather than looking for the lines, I'd instead look for the white boxes.

  1. Preparation

    import cv2
    import numpy as np
    
  2. Load the image

    img = cv2.imread("digitbox.jpg", 0)
    
  3. Binarize it, so that both the boxes and the digits are black, rest is white

    _, thresh = cv2.threshold(img, 200, 255, cv2.THRESH_BINARY)
    cv2.imwrite('digitbox_step1.png', thresh)
    

    Step 1 -- thresholded input

  4. Find contours. In this example image, it's fine to just look for external contours.

    _, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
  5. Process the contours, filtering out any with too small an area. Find convex hull of each contour, create a mask of all areas outside the contour. Store the bounding boxes of each found contour, sorted by x coordinate.

    mask = np.ones_like(img) * 255
    
    boxes = []
    
    for contour in contours:
        if cv2.contourArea(contour) > 100:
            hull = cv2.convexHull(contour)
            cv2.drawContours(mask, [hull], -1, 0, -1)
            x,y,w,h = cv2.boundingRect(contour)
            boxes.append((x,y,w,h))
    
    boxes = sorted(boxes, key=lambda box: box[0])
    
    cv2.imwrite('digitbox_step2.png', mask)
    

    Step 2 -- the mask

  6. Dilate the mask (to shrink the black parts), to clip off any remains the the gray frames.

    mask = cv2.dilate(mask, np.ones((5,5),np.uint8))
    
    cv2.imwrite('digitbox_step3.png', mask)
    

    Step 3 -- dilated mask

  7. Fill all the masked pixels with white, to erase the frames.

    img[mask != 0] = 255
    
    cv2.imwrite('digitbox_step4.png', img)
    

    Step 4 - cleaned up input

  8. Process the digits as you desire -- i'll just draw the bounding boxes.

    result = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    
    for n,box in enumerate(boxes):
        x,y,w,h = box
        cv2.rectangle(result,(x,y),(x+w,y+h),(255,0,0),2)
        cv2.putText(result, str(n),(x+5,y+17), cv2.FONT_HERSHEY_SIMPLEX, 0.6,(255,0,0),2,cv2.LINE_AA)
    
    cv2.imwrite('digitbox_step5.png', result)
    

    Enumerated bounding boxes


The whole script in one piece:

import cv2
import numpy as np

img = cv2.imread("digitbox.jpg", 0)

_, thresh = cv2.threshold(img, 200, 255, cv2.THRESH_BINARY)
_, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

mask = np.ones_like(img) * 255
boxes = []

for contour in contours:
    if cv2.contourArea(contour) > 100:
        hull = cv2.convexHull(contour)
        cv2.drawContours(mask, [hull], -1, 0, -1)
        x,y,w,h = cv2.boundingRect(contour)
        boxes.append((x,y,w,h))

boxes = sorted(boxes, key=lambda box: box[0])

mask = cv2.dilate(mask, np.ones((5,5),np.uint8))

img[mask != 0] = 255

result = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

for n,box in enumerate(boxes):
    x,y,w,h = box
    cv2.rectangle(result,(x,y),(x+w,y+h),(255,0,0),2)
    cv2.putText(result, str(n),(x+5,y+17), cv2.FONT_HERSHEY_SIMPLEX, 0.6,(255,0,0),2,cv2.LINE_AA)

cv2.imwrite('digitbox_result.png', result)
like image 169
Dan Mašek Avatar answered Dec 22 '22 00:12

Dan Mašek