Это немного другой подход, использующий pyvips .
Если изображение просто поворачивается (т. Е. Мало или вообще без перспективы), вы можете воспользоваться БПФ, чтобы найти угол поворота.Хорошая регулярная сетка символов создаст четкий набор линий на преобразовании.Это должно быть очень крепким.Это делает БПФ для всего изображения, но вы могли бы сначала немного его уменьшить, если хотите увеличить скорость.
import sys
import pyvips
image = pyvips.Image.new_from_file(sys.argv[1])
# to monochrome, take the fft, wrap the origin to the centre, get magnitude
fft = image.colourspace('b-w').fwfft().wrap().abs()
Создание:
![enter image description here](https://i.stack.imgur.com/cTpU5.png)
Чтобы найти угол линий, поверните полярные координаты в прямоугольные и найдите горизонтали:
def to_rectangular(image):
xy = pyvips.Image.xyz(image.width, image.height)
xy *= [1, 360.0 / image.height]
index = xy.rect()
scale = min(image.width, image.height) / float(image.width)
index *= scale / 2.0
index += [image.width / 2.0, image.height / 2.0]
return image.mapim(index)
# sum of columns, sum of rows
cols, rows = to_rectangular(fft).project()
Изготовление:
![enter image description here](https://i.stack.imgur.com/Epycd.png)
С проекцией:
![enter image description here](https://i.stack.imgur.com/V1inq.png)
Затем просто посмотрите на пик и поверните:
# blur the rows projection a bit, then get the maxpos
v, x, y = rows.gaussblur(10).maxpos()
# and turn to an angle in degrees we should counter-rotate by
angle = 270 - 360 * y / rows.height
image = image.rotate(angle)
![enter image description here](https://i.stack.imgur.com/5qGnb.png)
Чтобы обрезать, я взял горизонтальный иВертикальные проекции снова, затем поиск пиков с B> G.
cols, rows = image.project()
h = (cols[2] - cols[1]) > 10000
v = (rows[2] - rows[1]) > 10000
# search in from the edges for the first non-zero value
cols, rows = h.profile()
left = rows.avg()
cols, rows = h.fliphor().profile()
right = h.width - rows.avg()
width = right - left
cols, rows = v.profile()
top = cols.avg()
cols, rows = v.flipver().profile()
bottom = v.height - cols.avg()
height = bottom - top
# move the crop in by a margin
margin = 10
left += margin
top += margin
width -= 2 * margin
height -= 2 * margin
# and crop!
image = image.crop(left, top, width, height)
Чтобы сделать:
![enter image description here](https://i.stack.imgur.com/as0bR.png)
И, наконец, удалитьфон, размытие с большим радиусом и вычитание:
image = image.colourspace('b-w').gaussblur(70) - image
Чтобы сделать:
![enter image description here](https://i.stack.imgur.com/ED58P.jpg)