Как уменьшить символы на изображении с помощью Open CV - PullRequest
0 голосов
/ 27 ноября 2018

Я пытаюсь использовать Open CV для уменьшения чисел на изображении.В настоящее время я могу определить контуры, но мне трудно понять, как уменьшить числа после их идентификации.

Вот пример изображения: numbers

Вот контуры, которые я определил:

Contours

Вот код, который я использую для достижения этой цели:

import cv2

image = cv2.imread("numbers.png")
edged = cv2.Canny(image, 10, 250)


# applying closing function
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))
closed = cv2.morphologyEx(edged, cv2.MORPH_CLOSE, kernel)



_, cnts,_ = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, 
cv2.CHAIN_APPROX_SIMPLE)
contours = []


for c in cnts:

    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)
    contours.append(approx)

    cv2.drawContours(image, [approx], -1, (0, 255, 0), 2)


cv2.imshow("Output", image)
cv2.waitKey(0)

Я хочу иметь возможность использовать контуры для уменьшения чисел, не влияя на размер изображения.Это возможно?Спасибо!

1 Ответ

0 голосов
/ 27 ноября 2018

Предполагается, что у вас есть входное изображение с именем "numbers.png".enter image description here

Прежде всего, импортируйте полезные библиотеки и загрузите входное изображение:

import cv2
import numpy as np

img = cv2.imread("./numbers.png", 1)
gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

Во-вторых, вам нужно преобразовать входное изображение в двоичную форму и найти внешнееконтуры чисел:

_, im_th = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
_, contours, _ = cv2.findContours(255-im_th, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

Таким образом, вы можете видеть, что обнаруженные контуры будут вокруг чисел.enter image description here

В-третьих, найдите относительные ограничивающие прямоугольники вокруг чисел и найдите координаты средней точки прямоугольников (я предполагаю, что числа должны быть изменены по размеру и помещены в центр нижней части).строка):

number_imgs = []
number_btm_mid_pos = []
for cnt in contours:
    (x, y, w, h) = cv2.boundingRect(cnt)
    number_imgs.append(img[y:y+h, x:x+w])
    number_btm_mid_pos.append((int(x+w/2), y+h))

Наконец, измените размеры чисел, верните их обратно к изображению и отобразите результат:

# resize images and put it back
output_img = np.ones_like(img) * 255
resize_ratio = 0.5
for (i, num_im) in enumerate(number_imgs):
    num_im = cv2.resize(num_im, (0,0), fx=resize_ratio, fy=resize_ratio)
    (img_h, img_w) = num_im.shape[:2]
    # x1, y1, x2, y2
    btm_x, btm_y = number_btm_mid_pos[i]
    x1 = btm_x - int(img_w / 2)
    y1 = btm_y - img_h
    x2 = x1 + img_w
    y2 = y1 + img_h
    output_img[y1:y2, x1:x2] = num_im

cv2.imshow("Output Image", output_img)
cv2.imshow("Original Input", img)
cv2.waitKey()

Вы можете настроить переменную "resize_ratio", чтобы убедиться, чтосоотношение то, что вы ожидали.Результат должен выглядеть примерно так: enter image description here

Вы можете заметить, что последнее число «10» разделяется.Это потому, что «1 0» был распознан как две отдельные цифры.Чтобы сделать его идеальным, можно написать некоторый код для проверки разрыва / расстояния между каждыми двумя цифрами.Однако это было бы не совсем уместно, и было бы немного сложно обобщить решение, основываясь на ограниченных результатах тестирования.Поэтому я останавливаюсь здесь.

В любом случае, удачи и веселья.

...