To find the X and Y Co-ordinate of the Printed area (text or Image) in document using openCV in python

Viewed 112

I have the input imageInput Image.I want to find the document layout of the Text area. I tried using "Convex Hull"

When I do "Convex Hull" and draw counter for it. The output is Output Image

It is NOT marking the document Printed area. How can we find the X and Y coordinates of it

Below is the code

import cv2
# Load the image
img1 = cv2.imread(r'TestImage.jpg')
# Convert it to greyscale
img = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
# Threshold the image
ret, thresh = cv2.threshold(img,50,255,0)
# Find the contours
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# For each contour, find the convex hull and draw it
# on the original image.
hull=[]
for i in range(len(contours)):
    hullv=cv2.convexHull(contours[i])
    hull.append(cv2.convexHull(contours[i]))
    # print(hull)
    cv2.drawContours(img1, [hullv], -1, (255, 0, 0), 2)

cv2.imwrite(r"contours1.png",img1)
1 Answers

If all of your documents have an image on the right hand corner and the rest of it is text, then one way you can do this is to convert the image into black and white, do some morphological closing to close some gaps with regards to the text and sum up each row. You can then find the point where there is a very large spike which denotes where the text starts. The reason why this works is because the text covers much of the columns in the image for each row whereas the image only covers a small portion of the columns. As you traverse down each row and calculate the total number of non-zero pixels in each row, you'll get relatively small sums up until you encounter the first line of text which will give you a very large change in the sum profile. Where this change occurs is where your text starts. You can crop from that point to the end of the document. One thing I'd like to point out is that your text is dark on a light background. When converting to binary, we need to invert this so white text is on a dark background for the row sum logic to work.

Something like this can work:

import cv2
import numpy as np

# Read in image, convert to grayscale, then convert to binary
im = cv2.imread('OghQo.jpg') # Downloaded from Stack Overflow and read offline
im_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
_, im_bw = cv2.threshold(im_gray, 5, 255, cv2.THRESH_BINARY_INV)

# Performing morphological closing
se = np.ones((20, 30), dtype=np.uint8)
im_bw2 = cv2.morphologyEx(im_bw, cv2.MORPH_CLOSE, se)

# Calculate row sums
row_sums = im_bw2.sum(axis=1)

# Find the row which exceeds the threshold
threshold_row = 80000
row_index = np.argmax(row_sums > threshold_row)

# Crop the image with a bit of breathing room
buffer_size = 10
crop = im[row_index - buffer_size:]

# Show the image
cv2.imshow("Cropped", crop)
cv2.waitKey(0)
cv2.destroyAllWindows()

The threshold I played around with until I got something reasonable. We now get:

enter image description here

Related