16

画像をある程度回転させてからウィンドウに表示しようとしています。私の考えは、回転して、古い幅と高さから計算されたウィンドウの新しい幅と高さで新しいウィンドウに表示することです。

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, angle):#parameter angle 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(angle)

    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,angle,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)

私のコードにはこの問題につながるいくつかの愚かな間違いがあるはずですが、私はそれを理解することができません...そして私は私のコードが十分にpythonicではないことを知っています:(..申し訳ありません..

誰か助けてもらえますか?

最高、</ p>

ベアズク

4

3 に答える 3

16

BloodyDの答えが言ったように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

ここに画像の説明を入力

于 2015-10-20T21:45:41.070 に答える
5

次のような回転行列を取得すると:

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

「スケール」パラメーターは 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", image) と 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__':実際にはそれほど多くはありません...そして、それがあなたが取り組んでいる実際のモジュールである場合、あなたは間違いなく使用するのが正しかったです.

于 2012-08-02T06:53:47.873 に答える