python opencv旋转图片_OpenCV python3无法正确旋转图像

I want to use python3 with OpenCV packages to rotate an image in a degree 15 and rotate it back. However, the code below seem does not work but I think there no logic error in the codes. In the "NEAREST" window, the image is rotated correctly but in the "NEAREST-OK-RESTORE" window the image is not rotate back to its original position ( showed in "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)

The test image is here:

解决方案

The reason why this is happening is because when you are performing the rotation, this is doing it within the span of the original image dimensions, so this results in image clipping if you are rotating the image and the resulting corner points extend beyond the original image dimensions.

What you have to do is zero pad the image so that the rotated image is fully contained within it, rotate this image then when you rotate back, you will have to crop the result.

To figure out how much to zero pad your image by, note that the largest possible dimensions of your image will be when the image is at a 45 degree rotation. This means that the diagonal of the image would now be the number of rows in the image. Therefore, zero pad your image so that we can at least store the image when subject to a 45 degree rotation, rotate this image and when you rotate back you'll have to crop the result.

You can use numpy.pad to do this for you and when you're done you can simply crop the result:

I've made the following changes to your code to do this:

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()

I now get:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值