Reputation: 105
I am trying to crop an image of dot matrix print into individual characters. I have dilated the characters, threhold and inverted them.
I have created an array that has the pixel values of the blank spaces in the image. (the red lines) in order to crop individual characters
I am trying to write a function that will return the pixels of the character eg
L - [0 62]
o - [74 137]
r - [149 199] etc.
I have tried a couple of methods of for loops but canot reach a solution to produce the required arrays. Any tips appreciated!
##dot matrix print
##import the required libraries
import cv2
import numpy as np
## import the image
image = cv2.imread('/home/pi/Downloads/dot-matrix-unknown-sample.png')
##create the kernal for the dilation
kernel = np.ones((4,4),np.uint8)
##crop the image to one line
cropped =image[0:101, 0:]
##crop the first letter 'l'
##l = cropped[0:101, 0:62]
## convert the image to gray and use the otsu threshold and invert
img=cv2.cvtColor(cropped,cv2.COLOR_BGR2GRAY)
ret3, th3 = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
inverted = cv2.bitwise_not(th3)
##dilate the dots in the matrixto take up the gaps between the dots.
dilation = cv2.dilate(inverted,kernel,iterations = 1)
##display the image
cv2.imshow('img',dilation)
cv2.waitKey(0)
cv2.destroyAllWindows()
##provides the location of spaces in the image in 2d arrray
vpp = np.sum(dilation, axis =0)
space= np.where(vpp == 0)
space= np.array(space)
##convert to a 1d array (as image)
space=space.ravel()
print(space)
p.s if there is a better way to do this please sugggest.
Upvotes: 0
Views: 358
Reputation: 435
I assume the output you want bounding box for each letter.
Steps:
1.Dilate the image to bring contours (dots) closer
2- Find the contours
3- Sort Contours According to the sizes of their bounding boxes
4- Remove Unwanted contours if any (I did this by taking only largest 2 contours, where 2 is number of letters in my test case.
5-Sort contours according to their X positions (left to right, I dont know if this is necessary for you)
6- Find bounding boxes for each coordinate, optionally draw it
Code:
# Dilate
dilated = cv2.dilate(gray, (5, 5), iterations=8)
# Find Contours
contours, hierarchy = cv2.findContours(dilated, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# Sort the contours descending according to their area
contours = sorted(contours, key=lambda x: cv2.contourArea(x), reverse=False)
NUMBER_OF_LETTERS = 2
# Delete the smalles contours to match len(contours) to number of letters.
del contours[len(contours) - NUMBER_OF_LETTERS]
# Sort the Contours According to their position (left to right)
contours = sorted(contours, key=lambda x: cv2.boundingRect(x)[0], reverse=True)
bboxes = []
# Find and draw bounding boxes, and append to bboxes list for future use.
for c in contours:
x, y, w, h = cv2.boundingRect(c)
bboxes.append((x, y, w, h))
cv2.rectangle(dot_matrix, (x, y), (x + w, y + h), (0, 0, 255), 2)
Output: (Original, Dilated, BoundingBoxes)
Upvotes: 2