Мне потребовалось время, но я сам понял.
Фактическое изображение:
![Actual image:](https://i.ibb.co/zQ64jf0/actual.png)
if len(img.shape) != 2:
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
else:
gray = img
kernel = np.array([[-1,-1,-1],[-1,9,-1],[-1,-1,-1]])
sharp_img = cv2.filter2D(np.asarray(gray), -1, kernel)
gray = cv2.bitwise_not(gray)
ret,bw = cv2.threshold(sharp_img,200,255,1)
#### HORIZONTAL TRANSFORMATIONS #######
hz_kernel = np.array([[1,2,1],[0,0,0],[-1,-2,-1]])
vert_kernel = np.array([[-1,0,1],[-2,0,2],[-1,0,1]])
hz_img = cv2.filter2D(np.asarray(bw),-1,hz_kernel)
dilated = cv2.dilate(hz_img, np.ones((1, 5)),iterations = 2)
hz_img = cv2.erode(dilated,np.ones((1,5)),iterations = 4)
#cv2_imshow(bw)
print('after hz sobel->')
cv2_imshow(hz_img)
После горизонтального фильтра sobel:
![After horizontal sobel filter:](https://i.ibb.co/S6Q8qdk/hz-sobel.png)
_, contours, hierarchy = cv2.findContours(
hz_img,
cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
mask = np.ones(img.shape[:2], dtype="uint8") * 255
for cnt in contours:
x,y,w,h = cv2.boundingRect(cnt)
if w < (img.shape[1] - 10):
#print(w)
cv2.drawContours(mask, [cnt], -1, 0, -1)
hz_lines = cv2.bitwise_and(hz_img, hz_img, mask=mask)
if i == 0:
print("after removing noise")
cv2_imshow(hz_lines)
После горизонтального удаления шума:
![After horizontal noise removal:](https://i.ibb.co/0hymLGP/hz-remove-noise.png)
######## VERTICAL TRANSFORMATIONS #########
vert_img = cv2.filter2D(np.asarray(bw),-1,vert_kernel)
dilated = cv2.dilate(vert_img, np.ones((3, 1)),iterations = 1)
vert_img = cv2.erode(dilated,np.ones((3,1)),iterations = 1)
print("after vertical soble->")
cv2_imshow(vert_img)
После вертикального фильтра sobel:
![After vertical sobel filter:](https://i.ibb.co/ZcfrBBh/vert-sobel.png)
_, vert_contours, _ = cv2.findContours(
vert_img,
cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
vert_mask = np.ones(img.shape[:2], dtype="uint8") * 255
for cnt in vert_contours:
x,y,w,h = cv2.boundingRect(cnt)
if h<vert_img.shape[0]-10 or w > 5:
#print(w)
cv2.drawContours(vert_mask, [cnt], -1, 0, -1)
vert_lines = cv2.bitwise_and(vert_img, vert_img, mask=vert_mask)
print('after removing noise ->')
cv2_imshow(vert_lines)
После устранения вертикального шума:
![After vertical noise removal:](https://i.ibb.co/9nyXNN1/vert-remove-noise.png)
####### COMBINATION ##########
boxes_array = cv2.bitwise_or(vert_lines,hz_lines)
print('box array')
cv2_imshow(boxes_array)
Побит или из результатов:
![Bitwise or of results:](https://i.ibb.co/vst9G1r/box-array1.png)
dilated = cv2.dilate(boxes_array, np.ones((7, 7)),iterations = 3)
eroded = cv2.bitwise_not(cv2.erode(dilated,np.ones((7,7)),iterations = 3))
print('dilated and inverted->')
cv2_imshow(eroded)
После расширения, эрозии и инверсии:
![After dilation, erosion and inversion:](https://i.ibb.co/6b8nw1f/dilated.png)
# Finally find the contours and find the bounding boxes
imz,contours,_ = cv2.findContours(
eroded,
cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[::-1]
boxes = []
for cnt in contours:
rect = cv2.boundingRect(cnt)
if rect[2]/rect[3] < 0.6 or rect[3]/rect[2] < 0.6:
continue
boxes.append(rect)
num_img = img[rect[1]:rect[1]+rect[3],rect[0]:rect[0]+rect[2]]
cv2_imshow(num)
Коробка после обрезки:
![A box after cropping:](https://i.ibb.co/Wnd6r6J/number.png)