Reputation: 11363
I'm experimenting with OpenCV and Python's bindings. This code is intended to rotate an image with a command line argument value. However, it is saving as an exact copy of the input image, with no rotation whatsoever.
This code is adapted from this answer
import cv2 as cv
def rotateImage(self, image, angle):
print "Rotating image to angle: %s" % (angle)
print type(image) #image is numpy.ndarray
print type(angle) #angle is float
center = tuple(np.array(image.shape[0:2])/2)
matrix = cv.getRotationMatrix2D(center, angle, 1.0)
rotate = cv.warpAffine(image, matrix, image.shape[0:2], flags=cv.INTER_LINEAR)
fileList = self.filename.split(".")
newFile = fileList[0] + "_rotate_%s." % (int(angle)) + fileList[1]
print "Saving to %s" % (newFile)
cv.imwrite(newFile, rotate)
My issue is the image saved after rotation isn't the one being input.
Input image:
Output:
Given these input and output, how can I alter the image dimensions to allow for 30 and 45 degree rotations?
Upvotes: 1
Views: 875
Reputation: 113814
The issue is that, after rotation, your image extends out past the edges of the original shape. The solution is to extend the original image and then rotate. That way, important parts are not cut-off:
import cv2 as cv
import numpy as np
def extend(image):
nrow, ncol, ncolor = image.shape
n = int((nrow**2 + ncol**2)**.5//2 + 1)
new = np.zeros((2*n, 2*n, ncolor))
a = nrow//2
b = ncol//2
new[n-a:n-a+nrow, n-b:n-b+ncol, :] = image
return new
def rotateImage(fname, angle):
print "Rotating image to angle: %s" % (angle)
image = cv.imread(fname, -1)
print type(image) #image is numpy.ndarray
print type(angle) #angle is float
image = extend(image)
center = tuple(np.array(image.shape[0:2])/2)
matrix = cv.getRotationMatrix2D(center, angle, 1.0)
rotate = cv.warpAffine(image, matrix, image.shape[0:2], flags=cv.INTER_LINEAR)
fileList = fname.split(".")
newFile = fileList[0] + "_rotate_%s." % (int(angle)) + fileList[1]
print "Saving to %s" % (newFile)
cv.imwrite(newFile, rotate)
The extend function creates a larger array (size based on the diagonal of the original image) and puts the original image in the center. I created the larger image with np.zeros which means the image that extend returns has a large black border. This extension needs to be done before the image is rotated.
Your image, after 45 degree rotation, looks like:
Upvotes: 3