как написать скрипт для расчета степени угла изображения?

У меня есть более 100 изображений, каждое из которых находится под разным углом. Я написал базовый код Python для поворота каждого изображения по одному с любого угла до нуля градусов (я имею в виду, чтобы сделать их плоскими). Код Python, который я приложил, представляет собой простой код, и, к сожалению, он не находит угол автоматически и не делает его точным нулем. В любое время для любого изображения я должен найти угол и запустить код много раз, чтобы сделать его равным нулю (иногда я не могу сделать его точно плоским или то, что мы установили в нулевой градус). Согласно изображениям, которые я прикрепил, image1 является одним из образцов изображения в качестве входных данных, а image_2 — это повернутое изображение, которое я хочу получить в конце в качестве вывода. Я хотел бы попросить любого, кто может помочь мне изменить текущий код или предоставить мне новый код Python (который я предпочитаю новому коду), чтобы я мог поворачивать свои изображения под любым углом до нуля градусов. Пожалуйста, не стесняйтесь спрашивать меня о дополнительных объяснениях, если хотите.

мой код opencv-python:

import cv2
import numpy as np
img = cv2.imread('image1.tif')
num_rows, num_cols = img.shape[:2]
rotation_matrix = cv2.getRotationMatrix2D((num_cols/2, num_rows/2),69.4, 1)
img_rotation = cv2.warpAffine(img, rotation_matrix, (num_cols, num_rows))
cv2.imshow('Rotation', img_rotation)
cv2.imwrite('image_2.tif',img_rotation)
cv2.waitKey()

Примечание: входные и выходные изображения удалены.


person Arashk    schedule 23.05.2017    source источник


Ответы (2)


это определенно не самый надежный метод, но, возможно, можно было бы:

  1. предположим, что граница вся черная
  2. определить самые верхние (x0,y0)/самые правые (x1,y1) углы изображения
  3. вычислить угол поворота как alpha = math.atan2(x1-x0,y1-y0)

Я скачал вашу фигуру (она была преобразована в png на imgur) и протестировал процедуру с помощью:

#!/usr/bin/env python
import cv2
import math

import numpy as np

img = cv2.imread('test.png')
H, W = img.shape[:2]

x0,y0 = None,None
x1,y1 = None,None

#scan all rows starting with the first
for i in range(0, H):
    row = img[i].sum(axis=1)
    s = np.sum(row)
    if s:
        #if there is at least one non-black pixel, mark
        #its position
        x0 = np.max(np.where(row>0))
        y0 = i
        break

#scan all columns starting with the right-most one
for j in range(W-1,-1,-1):
    col = img[:,j,:].sum(axis=1)
    s = np.sum(col)
    if s:
        #mark the position of the first non-black pixel
        x1 = j
        y1 = np.min(np.where(col>0))
        break

dx = x1 - x0
dy = y1 - y0

alpha = math.atan2(dx, dy) / math.pi * 180

rotation_matrix = cv2.getRotationMatrix2D((W/2, H/2), -alpha, 1)
img_rotation = cv2.warpAffine(img, rotation_matrix, (W, H))
cv2.imwrite('image_2.tif',img_rotation)

РЕДАКТИРОВАТЬ:

Предыдущий метод может быть неточным, если «угловой» пиксель также черный, поэтому вычисленный угол затем смещается. Чуть более точный подход может быть следующим:

  1. определить «верхнюю» границу прямоугольника (т. е. координаты пикселей, определяющие края)
  2. взять то ребро, проекция которого на ось абсцисс длиннее
  3. подогнать координаты, чтобы рассчитать наклон линии, определяющей ребро

Реализация:

#!/usr/bin/env python
import cv2
import math

import numpy as np

img = cv2.imread('test.png')
H, W = img.shape[:2]

data = []
for j in range(0, W):
    col = img[:,j,:].sum(axis=1)
    s = np.sum(col)
    if not s:
        continue

    for i in range(0, H):
        if col[i] > 0:
            data.append((j, i))
            break

y_min, min_pos = None, None
for idx, (x, y) in enumerate(data):
    if y_min is None or y < y_min:
        y_min = y
        min_pos = idx

N = len(data)
if min_pos > N - min_pos:
    data = data[:min_pos]
else:
    data = data[min_pos:]

data = np.asarray(data).T
coeffs = np.polyfit(data[0], data[1], 1)
alpha = math.atan(coeffs[0]) / math.pi * 180

print(alpha)

rotation_matrix = cv2.getRotationMatrix2D((W/2, H/2), alpha, 1)
img_rotation = cv2.warpAffine(img, rotation_matrix, (W, H))
cv2.imwrite('image_2.tif',img_rotation)
person ewcz    schedule 23.05.2017
comment
ewcz@ Спасибо за ваши комментарии и код. Я пробовал ваш код, но похоже, что повернутое изображение не совсем на 0 градусов. не могли бы вы сообщить мне, есть ли что-нибудь, что мне нужно сделать, чтобы сделать его точным нулем. Благодарность - person Arashk; 25.05.2017
comment
@FredGrahambel Я включил немного другой подход (вычисление угла по наклону самого длинного края), он может быть более точным ... - person ewcz; 25.05.2017
comment
@ewcz Большое спасибо за быстрый ответ. Функция работает нормально. Я ценю ваше время. - person Arashk; 27.05.2017

другой способ найти угол (при условии, что изображение находится на черном фоне):

  1. Преобразование изображения в оттенки серого
  2. Сегментируйте изображение с помощью порога
  3. Найдите контуры изображения
  4. Найдите параметры эллипса, соответствующие контуру

    import cv2
    import numpy as np
    
    image = cv2.imread("DlYEa.png")
    
    gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
    
    num_rows, num_cols = image.shape[:2]
    _, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)
    
    img, contours, hier = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    
    cnt = contours[0]
    (x, y), (Ma, ma), angle = cv2.fitEllipse(cnt)
    
    angle = int(angle - 90)
    
    rotation_matrix = cv2.getRotationMatrix2D((num_cols/2, num_rows/2), angle, 1)
    img_rotation = cv2.warpAffine(image, rotation_matrix, (num_cols, num_rows))
    
    cv2.imshow("rotation", img_rotation)
    cv2.waitKey()
    cv2.destroyAllWindows()
    
person Once    schedule 23.05.2017
comment
Once@ Спасибо, что ответили на мой вопрос. Я попробовал ваш код и столкнулся с ошибкой, так как я не очень хорошо разбираюсь в python, чтобы исправить ошибку. не могли бы вы взглянуть на следующую ошибку, которую я получил недавно, и помочь мне исправить ее. Спасибо. error:Traceback (последний последний вызов): файл ImageRotation.py, строка 11, в ‹модуле› img, контуры, hier = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) ValueError: требуется более 2 значений для распаковывать - person Arashk; 25.05.2017