Python 2.7.3 + OpenCV 2.4 после поворота не подходит Изображение

Я пытаюсь повернуть изображение на несколько градусов, а затем показать его в окне. моя идея – повернуть, а затем показать его в новом окне с новой шириной и высотой окна, рассчитанной по старой ширине и высоте:

new_width = x * cos angle + y * sin angle new_height = y * cos angle + x * sin angle 

Я ожидал, что результат будет выглядеть следующим образом:

введите описание изображения здесь

но получается, что результат выглядит следующим образом:

введите описание изображения здесь

и мой код здесь:

 #!/usr/bin/env python -tt #coding:utf-8 import sys import math import cv2 import numpy as np def rotateImage(image, angel):#parameter angel in degrees if len(image.shape) > 2:#check colorspace shape = image.shape[:2] else: shape = image.shape image_center = tuple(np.array(shape)/2)#rotation center radians = math.radians(angel) x, y = im.shape print 'x =',x print 'y =',y new_x = math.ceil(math.cos(radians)*x + math.sin(radians)*y) new_y = math.ceil(math.sin(radians)*x + math.cos(radians)*y) new_x = int(new_x) new_y = int(new_y) rot_mat = cv2.getRotationMatrix2D(image_center,angel,1.0) print 'rot_mat =', rot_mat result = cv2.warpAffine(image, rot_mat, shape, flags=cv2.INTER_LINEAR) return result, new_x, new_y def show_rotate(im, width, height): # width = width/2 # height = height/2 # win = cv2.cv.NamedWindow('ro_win',cv2.cv.CV_WINDOW_NORMAL) # cv2.cv.ResizeWindow('ro_win', width, height) win = cv2.namedWindow('ro_win') cv2.imshow('ro_win', im) if cv2.waitKey() == '\x1b': cv2.destroyWindow('ro_win') if __name__ == '__main__': try: im = cv2.imread(sys.argv[1],0) except: print '\n', "Can't open image, OpenCV or file missing." sys.exit() rot, width, height = rotateImage(im, 30.0) print width, height show_rotate(rot, width, height) 

Должны быть какие-то глупые ошибки в моем коде, приводят к этой проблеме, но я не могу понять это … и я знаю, что мой код недостаточно питоничен 🙁 .. для этого …

Может кто-нибудь мне помочь?

Лучший,

bearzk

3 Solutions collect form web for “Python 2.7.3 + OpenCV 2.4 после поворота не подходит Изображение”

Как сказал ответ cv2.warpAffine , cv2.warpAffine не автоцентрирует преобразованное изображение. Вместо этого он просто преобразует каждый пиксель с помощью матрицы преобразования. (Это может перемещать пиксели в любом месте в декартовом пространстве, в том числе из исходной области изображения.) Затем, когда вы указываете размер изображения назначения, он захватывает область этого размера, начиная с (0,0), то есть в верхнем левом углу оригинальная рамка. Любые части вашего преобразованного изображения, которые не лежат в этом регионе, будут обрезаны.

Вот код Python для поворота и масштабирования изображения, с результатом по центру:

 def rotateAndScale(img, scaleFactor = 0.5, degreesCCW = 30): (oldY,oldX) = img.shape #note: numpy uses (y,x) convention but most OpenCV functions use (x,y) M = cv2.getRotationMatrix2D(center=(oldX/2,oldY/2), angle=degreesCCW, scale=scaleFactor) #rotate about center of image. #choose a new image size. newX,newY = oldX*scaleFactor,oldY*scaleFactor #include this if you want to prevent corners being cut off r = np.deg2rad(degreesCCW) newX,newY = (abs(np.sin(r)*newY) + abs(np.cos(r)*newX),abs(np.sin(r)*newX) + abs(np.cos(r)*newY)) #the warpAffine function call, below, basically works like this: # 1. apply the M transformation on each pixel of the original image # 2. save everything that falls within the upper-left "dsize" portion of the resulting image. #So I will find the translation that moves the result to the center of that region. (tx,ty) = ((newX-oldX)/2,(newY-oldY)/2) M[0,2] += tx #third column of matrix holds translation, which takes effect after rotation. M[1,2] += ty rotatedImg = cv2.warpAffine(img, M, dsize=(int(newX),int(newY))) return rotatedImg 

введите описание изображения здесь

Когда вы получаете матрицу вращения следующим образом:

 rot_mat = cv2.getRotationMatrix2D(image_center,angel,1.0) 

Ваш параметр «scale» установлен в 1.0, поэтому, если вы используете его для преобразования матрицы изображений в матрицу результатов того же размера, она обязательно будет обрезана.

Вместо этого вы можете получить такую ​​матрицу вращения:

 rot_mat = cv2.getRotationMatrix2D(image_center,angel,0.5) 

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

Кроме того, похоже, что вы смешиваете обозначения numpy и OpenCV для размеров изображений. OpenCV использует (x, y) для размеров изображения и координат точек, а numpy использует (y, x). Вероятно, именно поэтому вы переходите от отношения портрета к ландшафтному.

Я обычно говорю об этом так:

 imageHeight = image.shape[0] imageWidth = image.shape[1] pointcenter = (imageHeight/2, imageWidth/2) 

и т.д…

В конечном счете, это отлично работает для меня:

 def rotateImage(image, angel):#parameter angel in degrees height = image.shape[0] width = image.shape[1] height_big = height * 2 width_big = width * 2 image_big = cv2.resize(image, (width_big, height_big)) image_center = (width_big/2, height_big/2)#rotation center rot_mat = cv2.getRotationMatrix2D(image_center,angel, 0.5) result = cv2.warpAffine(image_big, rot_mat, (width_big, height_big), flags=cv2.INTER_LINEAR) return result 

Обновить:

Вот полный скрипт, который я выполнил. Просто cv2.imshow («winname», изображение) и cv2.waitkey () без аргументов, чтобы держать его открытым:

 import cv2 def rotateImage(image, angel):#parameter angel in degrees height = image.shape[0] width = image.shape[1] height_big = height * 2 width_big = width * 2 image_big = cv2.resize(image, (width_big, height_big)) image_center = (width_big/2, height_big/2)#rotation center rot_mat = cv2.getRotationMatrix2D(image_center,angel, 0.5) result = cv2.warpAffine(image_big, rot_mat, (width_big, height_big), flags=cv2.INTER_LINEAR) return result imageOriginal = cv2.imread("/Path/To/Image.jpg") # this was an iPhone image that I wanted to resize to something manageable to view # so I knew beforehand that this is an appropriate size imageOriginal = cv2.resize(imageOriginal, (600,800)) imageRotated= rotateImage(imageOriginal, 45) cv2.imshow("Rotated", imageRotated) cv2.waitKey() 

На самом деле не так много … И вы определенно были правы в использовании, if __name__ == '__main__': если это настоящий модуль, над которым вы работаете.

Ну, этот вопрос кажется несовременным, но у меня была такая же проблема и потребовалось некоторое время, чтобы решить проблему без масштабирования исходного изображения вверх и вниз. Я просто опубликую свое решение (к сожалению, код на C ++, но при необходимости он может быть легко перенесен на python):

 #include <math.h> #define PI 3.14159265 #define SIN(angle) sin(angle * PI / 180) #define COS(angle) cos(angle * PI / 180) void rotate(const Mat src, Mat &dest, double angle, int borderMode, const Scalar &borderValue){ int w = src.size().width, h = src.size().height; // resize the destination image Size2d new_size = Size2d(abs(w * COS((int)angle % 180)) + abs(h * SIN((int)angle % 180)), abs(w * SIN((int)angle % 180)) + abs(h * COS((int)angle % 180))); dest = Mat(new_size, src.type()); // this is our rotation point Size2d old_size = src.size(); Point2d rot_point = Point2d(old_size.width / 2.0, old_size.height / 2.0); // and this is the rotation matrix // same as in the opencv docs, but in 3x3 form double a = COS(angle), b = SIN(angle); Mat rot_mat = (Mat_<double>(3,3) << a, b, (1 - a) * rot_point.x - b * rot_point.y, -1 * b, a, b * rot_point.x + (1 - a) * rot_point.y, 0, 0, 1); // next the translation matrix double offsetx = (new_size.width - old_size.width) / 2, offsety = (new_size.height - old_size.height) / 2; Mat trans_mat = (Mat_<double>(3,3) << 1, 0, offsetx , 0, 1, offsety, 0, 0, 1); // multiply them: we rotate first, then translate, so the order is important! // inverse order, so that the transformations done right Mat affine_mat = Mat(trans_mat * rot_mat).rowRange(0, 2); // now just apply the affine transformation matrix warpAffine(src, dest, affine_mat, new_size, INTER_LINEAR, borderMode, borderValue); } 

Общее решение состоит в том, чтобы повернуть и перевести повернутое изображение в нужное положение. Итак, мы создаем две матрицы преобразования (сначала для вращения, второе для перевода) и умножаем их на окончательное аффинное преобразование. Так как матрица, возвращаемая opRevator's getRotationMatrix2D, равна только 2×3, мне пришлось создавать матрицы вручную в формате 3×3, чтобы они могли умножаться. Затем просто возьмите первые два ряда и примените аффинную трансформацию.

EDIT : Я создал Gist, потому что мне нужна эта функция слишком часто в разных проектах. Существует также версия Python: https://gist.github.com/BloodyD/97917b79beb332a65758

  • Python: Любой способ заставить один процесс иметь блокировку записи, а другие - просто читать параллельно?
  • Исключить столбцы из pandas, где ()
  • добавлять и печатать не-ASCII-символы в list-python
  • Обнаруженное исключение - None
  • Не удается найти lpython2.7
  • pip не удалось установить код ошибки numpy 1
  • Ввод пользователя с таймаутом, в цикле
  • Перестановка x длиной 2 символа
  •  
    Interesting Posts for Van-Lav

    Получить текущее значение списка env.hosts с помощью библиотеки Fabric Fabric

    Расширение загрузки Python – SQLite JSON1

    синтаксическая ошибка для нелокального оператора в Python

    Панды: добавление столбца с вычислениями из других столбцов

    Преобразование задней широты из данных Hex GREENTEL

    Преобразование входных данных для ALS в pyspark

    Каков наилучший способ инициализации диктофона в Python?

    Почему я получаю разные результаты при использовании понимания списка с сопрограммами с asyncio?

    Как я могу использовать executeemany для вставки в MySQL списка словарей в Python

    Невозможно загрузить пакеты из-за ошибки «Без модуля с именем wx»

    Python: удалить несколько символов в списке строк

    Отправлять сообщения журнала из всех задач сельдерея в один файл

    один-ко-многим встроенный выбор с django admin

    Как создать программу, которая использует графический интерфейс?

    Как использовать другое представление для регистрации django?

    Python - лучший язык программирования в мире.