I am trying to read information from documents in which the data fields are of the type where you can enter only one letter/digit in a box. I managed to segment box arrays for respective data fields, however I am having problem in segmenting individual boxes in these box arrays.
I have tried to use the cv2.approxPolyDP
and cv2.HoughLines
functions however both give unacceptable results. The sudoku question at one point uses the fact that the length of vertical/horizontal line is much bigger than individual numbers. In my case the numbers sometimes spill out of the boxes and almost always touch the boxes.
This function is not able to detect small boxes individually:
def detect_boxes(img):
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
sharp_img = cv2.filter2D(np.asarray(gray), -1, kernel)
ret,thresh = cv2.threshold(sharp_img,180,255,1)
edges = cv2.Canny(sharp_img,50,150,apertureSize = 3)
_,contours,h = cv2.findContours(thresh,1,2)
boxes = []
for cnt in contours:
approx = cv2.approxPolyDP(cnt,0.01*cv2.arcLength(cnt,True),True)
temp = img
if len(approx)==4:
boxes.append(cnt)
print(cnt.shape)
print(max(cnt[0])-min(cnt[0]),max(cnt[1])-min(cnt[1]))
cv2.drawContours(temp,[cnt],0,(0,0,255),-1)
cv2_imshow(temp)
return boxes
The approxPolyDP
result is:
The other function is:
def det_box(img):
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
sharp_img = cv2.filter2D(np.asarray(gray), -1, kernel)
ret,thresh = cv2.threshold(sharp_img,180,255,1)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
cv2_imshow(edges)
lines = cv2.HoughLines(edges,1,np.pi/180,200)
temp = img
for rho,theta in lines[0]:
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 1000*(-b))
y1 = int(y0 + 1000*(a))
x2 = int(x0 - 1000*(-b))
y2 = int(y0 - 1000*(a))
cv2.line(temp,(x1,y1),(x2,y2),(0,0,255),2)
cv2_imshow(temp)
return lines
The HoughLines
result is:
I was trying to get box points/contours of each individual small box in order. Any help will be appreciated. Even removing the horizontal and vertical lines in the boxes will be helpful.