OpenCV python3 无法正确旋转图像
OpenCV python3 cannot rotate image back correctly
我想将 python3 与 OpenCV 包一起使用,将图像旋转 15 度并旋转回来。但是,下面的代码似乎不起作用,但我认为代码中没有逻辑错误。在 "NEAREST" window 中,图像旋转正确,但在 "NEAREST-OK-RESTORE" window 中,图像未旋转回其原始位置(显示在 "original" window ).
#! /usr/bin/env python3
#! -*- coding:utf-8 -*-
import cv2
import numpy as np
imgmat = cv2.imread('./lena.jpg',255)
print(hex(id(imgmat)))
cv2.imshow('original',imgmat)
rows,cols = imgmat.shape
M = cv2.getRotationMatrix2D((cols/2,rows/2),-15,1)
dst = cv2.warpAffine(src=imgmat,M=M,dsize=(cols,rows),flags=cv2.INTER_NEAREST)
print(hex(id(dst)))
cv2.imshow('NEAREST',dst)
OKMM = cv2.invertAffineTransform(M)
dst = cv2.warpAffine(dst,OKMM,(cols,rows),flags = cv2.INTER_NEAREST)
print(hex(id(dst)))
cv2.imshow('NEAREST-OK-RESTORE',dst)
cv2.waitKey(0)
测试图片在这里:
发生这种情况的原因是因为当您执行旋转时,这是在原始图像尺寸的范围内进行的,因此如果您旋转图像和由此产生的角点,这会导致图像剪切超出原始图像尺寸。
您需要做的是对图像进行零填充,以便旋转后的图像完全包含在其中,旋转该图像,然后当您旋转回来时,您将不得不裁剪结果。
要计算图像的零填充量,请注意当图像旋转 45 度时图像的最大可能尺寸。这意味着图像的对角线现在将是图像中的行数。因此,零填充您的图像,以便我们至少可以在旋转 45 度时存储图像,旋转此图像,当您旋转回来时,您必须裁剪结果。
您可以使用 numpy.pad
为您完成此操作,完成后您可以简单地裁剪结果:
为此,我对您的代码进行了以下更改:
import cv2
import numpy as np
imgmat = cv2.imread('./lena.jpg',255)
print(hex(id(imgmat)))
cv2.imshow('original',imgmat)
rows,cols = imgmat.shape
# NEW - Determine the diagonal length of the image
diagonal = int(np.ceil(np.sqrt(rows**2.0 + cols**2.0)))
# NEW - Determine how many pixels we need to pad to the top/bottom and left/right
pp_r, pp_c = (diagonal - rows) // 2, (diagonal - cols) // 2
# NEW - Pad the image
imgmat_copy = np.pad(imgmat, ((pp_r, pp_r), (pp_c, pp_c)), 'constant', constant_values=(0,0))
### Your code as before - note we are rotating the zero padded image
rows,cols = imgmat_copy.shape
M = cv2.getRotationMatrix2D((cols/2,rows/2),-15,1)
dst = cv2.warpAffine(src=imgmat_copy,M=M,dsize=imgmat_copy.shape,flags=cv2.INTER_NEAREST)
print(hex(id(dst)))
cv2.imshow('NEAREST',dst)
OKMM = cv2.invertAffineTransform(M)
dst = cv2.warpAffine(dst,OKMM,(cols,rows),flags = cv2.INTER_NEAREST)
print(hex(id(dst)))
# NEW - Crop the image
dst = dst[pp_r:-pp_r+1,pp_c:-pp_c+1]
cv2.imshow('NEAREST-OK-RESTORE',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
我现在得到:
我想将 python3 与 OpenCV 包一起使用,将图像旋转 15 度并旋转回来。但是,下面的代码似乎不起作用,但我认为代码中没有逻辑错误。在 "NEAREST" window 中,图像旋转正确,但在 "NEAREST-OK-RESTORE" window 中,图像未旋转回其原始位置(显示在 "original" window ).
#! /usr/bin/env python3
#! -*- coding:utf-8 -*-
import cv2
import numpy as np
imgmat = cv2.imread('./lena.jpg',255)
print(hex(id(imgmat)))
cv2.imshow('original',imgmat)
rows,cols = imgmat.shape
M = cv2.getRotationMatrix2D((cols/2,rows/2),-15,1)
dst = cv2.warpAffine(src=imgmat,M=M,dsize=(cols,rows),flags=cv2.INTER_NEAREST)
print(hex(id(dst)))
cv2.imshow('NEAREST',dst)
OKMM = cv2.invertAffineTransform(M)
dst = cv2.warpAffine(dst,OKMM,(cols,rows),flags = cv2.INTER_NEAREST)
print(hex(id(dst)))
cv2.imshow('NEAREST-OK-RESTORE',dst)
cv2.waitKey(0)
测试图片在这里:
发生这种情况的原因是因为当您执行旋转时,这是在原始图像尺寸的范围内进行的,因此如果您旋转图像和由此产生的角点,这会导致图像剪切超出原始图像尺寸。
您需要做的是对图像进行零填充,以便旋转后的图像完全包含在其中,旋转该图像,然后当您旋转回来时,您将不得不裁剪结果。
要计算图像的零填充量,请注意当图像旋转 45 度时图像的最大可能尺寸。这意味着图像的对角线现在将是图像中的行数。因此,零填充您的图像,以便我们至少可以在旋转 45 度时存储图像,旋转此图像,当您旋转回来时,您必须裁剪结果。
您可以使用 numpy.pad
为您完成此操作,完成后您可以简单地裁剪结果:
为此,我对您的代码进行了以下更改:
import cv2
import numpy as np
imgmat = cv2.imread('./lena.jpg',255)
print(hex(id(imgmat)))
cv2.imshow('original',imgmat)
rows,cols = imgmat.shape
# NEW - Determine the diagonal length of the image
diagonal = int(np.ceil(np.sqrt(rows**2.0 + cols**2.0)))
# NEW - Determine how many pixels we need to pad to the top/bottom and left/right
pp_r, pp_c = (diagonal - rows) // 2, (diagonal - cols) // 2
# NEW - Pad the image
imgmat_copy = np.pad(imgmat, ((pp_r, pp_r), (pp_c, pp_c)), 'constant', constant_values=(0,0))
### Your code as before - note we are rotating the zero padded image
rows,cols = imgmat_copy.shape
M = cv2.getRotationMatrix2D((cols/2,rows/2),-15,1)
dst = cv2.warpAffine(src=imgmat_copy,M=M,dsize=imgmat_copy.shape,flags=cv2.INTER_NEAREST)
print(hex(id(dst)))
cv2.imshow('NEAREST',dst)
OKMM = cv2.invertAffineTransform(M)
dst = cv2.warpAffine(dst,OKMM,(cols,rows),flags = cv2.INTER_NEAREST)
print(hex(id(dst)))
# NEW - Crop the image
dst = dst[pp_r:-pp_r+1,pp_c:-pp_c+1]
cv2.imshow('NEAREST-OK-RESTORE',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
我现在得到: