Как отменить перекос текстового изображения и получить новую ограничивающую рамку этого изображения? - PullRequest
2 голосов
/ 09 января 2020

Вот изображение чека, которое у меня есть, и я нанес его с помощью matplotlib. Если вы видите изображение, текст на нем не прямой. Как я могу снять перекос и исправить это?

from skimage import io
import cv2

# x1, y1, x2, y2, x3, y3, x4, y4
bbox_coords = [[20, 68], [336, 68], [336, 100], [20, 100]]

image = io.imread('https://i.ibb.co/3WCsVBc/test.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)

fig, ax = plt.subplots(figsize=(20, 20))
ax.imshow(gray, cmap='Greys_r')

# for plotting bounding box uncomment the two lines below
#rect = Polygon(bbox_coords, fill=False, linewidth=1, edgecolor='r')
#ax.add_patch(rect)
plt.show()

print(gray.shape)
(847, 486)

receipt image

Я думаю, что если мы хотим сначала снять перекос, мы должны найти края поэтому я попытался найти края с помощью алгоритма Кэнни, а затем получить контуры, как показано ниже.

from skimage import filters, feature, measure

def edge_detector(image):
    image = filters.gaussian(image, 2, mode='reflect')
    edges = feature.canny(image)
    contours = measure.find_contours(edges, 0.8)
    return edges, contours

fig, ax = plt.subplots(figsize=(20, 20))

ax.imshow(gray, cmap='Greys_r'); 
gray_image, contours = edge_detector(gray)

for n, contour in enumerate(contours):
    ax.plot(contour[:, 1], contour[:, 0], linewidth=2)

Края, которые я получил из кода выше, - это края каждого текста, но это не то, что мне нужно , Мне нужно правильно получить края квитанции?

Также мне нужен способ получить координаты новой ограничительной рамки после де-смещения изображения (т.е. выпрямления изображения)?

Если кто-то работал по аналогичной проблеме, пожалуйста, помогите мне? Спасибо.

1 Ответ

5 голосов
/ 10 января 2020

Вот модифицированная реализация метода профиля проекции для исправления искаженных изображений, как описано в Алгоритм оценки перекоса на основе профиля проекции для сжатых изображений JBIG . После получения двоичного изображения идея состоит в том, чтобы поворачивать изображение под различными углами и генерировать гистограмму пикселей в каждой итерации. Чтобы определить угол перекоса, мы сравниваем максимальную разницу между пиками и, используя этот угол перекоса, поворачиваем изображение, чтобы исправить перекос. Количество пиков, которые нужно определить, можно отрегулировать с помощью значения delta: чем меньше дельта, тем больше пиков будет проверено с учетом того, что процесс займет больше времени.


До -> После

image image

Код

import cv2
import numpy as np
from scipy.ndimage import interpolation as inter

def correct_skew(image, delta=.1, limit=5):
    def determine_score(arr, angle):
        data = inter.rotate(arr, angle, reshape=False, order=0)
        histogram = np.sum(data, axis=1)
        score = np.sum((histogram[1:] - histogram[:-1]) ** 2)
        return histogram, score

    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blur = cv2.medianBlur(gray, 3)
    thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1] 

    scores = []
    angles = np.arange(-limit, limit + delta, delta)
    for angle in angles:
        histogram, score = determine_score(thresh, angle)
        scores.append(score)

    best_angle = angles[scores.index(max(scores))]

    (h, w) = image.shape[:2]
    center = (w // 2, h // 2)
    M = cv2.getRotationMatrix2D(center, best_angle, 1.0)
    rotated = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, \
              borderMode=cv2.BORDER_REPLICATE)

    return best_angle, rotated

if __name__ == '__main__':
    image = cv2.imread('1.jpg')
    angle, rotated = correct_skew(image)
    print(angle)
    cv2.imshow('rotated', rotated)
    cv2.imwrite('rotated.png', rotated)
    cv2.waitKey()

Примечание: Также взгляните на повернутое перекошенное изображение в вертикальное положение для другого подхода

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...