2

Using OpenCV (python) I am trying to remove the section of image which is above the border line (white area in this sample image where ORIGINAL is writtn) in the image shown below Invoice Image

Using horizontal and vertical kernels I am able to draw the wireframe, however that does not work many times because many times due to scanning quality few horizontal or vertical lines appear outside the wireframe which causes wrong contour detection. In this image also you can see on top right there is noise which I am detecting as topmost horizontal line.

What I want is, once I get the actual box then I can simply use x, y coordinates for OCR scanning of needed fields (like reference number, Issued In etc).

Following is what I have been able to extract using the code below. However not able to clip the outer extra section of image due to noisy horizontal or vertical lines outside this wireframe. Also tried filling outside section with black and then detecting the contours.
Suggestions please... Wireframe

    kernel_length = np.array(image).shape[1]//40 
# A verticle kernel of (1 X kernel_length), which will detect all the verticle lines from the image.
verticle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, kernel_length))
# A horizontal kernel of (kernel_length X 1), which will help to detect all the horizontal line from the image.
hori_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernel_length, 1))
# A kernel of (3 X 3) ones.
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# Morphological operation to detect verticle lines from an image
img_temp1 = cv2.erode(gray, verticle_kernel, iterations=3)
verticle_lines_img = cv2.dilate(img_temp1, verticle_kernel, iterations=3)
nathancy
  • 26,679
  • 11
  • 67
  • 86
Sandeep Bhutani
  • 346
  • 2
  • 16
  • The thing which you want is subtracting the part which is the above of rectangle(written ORIGINAL and 471330...) ? – Yunus Temurlenk Feb 01 '20 at 18:02
  • I dont want area which has ORIGINAL string – Sandeep Bhutani Feb 01 '20 at 18:11
  • 1- You can use *color difference* ( if always like this image). 2- You can check each column until detecting black pixels of the above line and when detected for each column. then you can find the y coordinate of the area which ll be removed – Yunus Temurlenk Feb 01 '20 at 18:21
  • color may not come in new samples. For color difference technique, it can fail if during scanning some random short lines are scanned.. just like in current image on top right is visible here too – Sandeep Bhutani Feb 01 '20 at 19:50
  • https://stackoverflow.com/a/8863060/176769 – karlphillip Feb 01 '20 at 23:26

1 Answers1

0

Instead of trying to find horizontal/vertical lines to detect the text document, a simple contour filtering approach should work here. The idea is to threshold the image to obtain a binary image then find contours and sort using contour area. The largest contour should be the text document. We can then apply a four point perspective transform to obtain a birds eye view of the image. Here's the results:

Input image:

Output:

Notice how the output image only has the desired text document and is aligned without a skewed angle.

Code

from imutils.perspective import four_point_transform
import cv2
import numpy

# Load image, grayscale, Gaussian blur, Otsu's threshold
image = cv2.imread("1.jpg")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (3,3), 0)
thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Find contours and sort for largest contour
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
displayCnt = None

for c in cnts:
    # Perform contour approximation
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)
    if len(approx) == 4:
        displayCnt = approx
        break

# Obtain birds' eye view of image
warped = four_point_transform(image, displayCnt.reshape(4, 2))

cv2.imshow("thresh", thresh)
cv2.imshow("warped", warped)
cv2.imshow("image", image)
cv2.waitKey()
nathancy
  • 26,679
  • 11
  • 67
  • 86
  • Hi @nathancy : Just like the magical four point trick, is there any other trick which can be used to extract the boxes correctly (bounding boxes or countours are not much reliable and difficult to interpret). I want to get the boxes of that vertical/horizontal lines image and to know which box is top left and which box is say 2nd from top – Sandeep Bhutani Feb 07 '20 at 16:47
  • I'm not sure what you mean, could you explain further? The solution above extracted the box ..no? You could open a new question for this – nathancy Feb 07 '20 at 21:34