# Rotating an Image using own algorithm in python

For an uni assignment I have been giving the task of making my own rotating algorithm in python. This is my code so far.

import cv2
import math
import numpy as np

class rotator:

angle = 20.0
x = 330
y = 330

width,height = img.shape

def showImg(name, self):
cv2.imshow(name, self.img)
self.img = np.pad(self.img, (self.height) ,'constant', constant_values=0)
self.width,self.height = self.img.shape

def printWH(self):
print(self.width)
print(self.height)

def rotate(self):
emptyF = np.zeros((self.width,self.height),dtype="uint8")
emptyB = np.zeros((self.width,self.height),dtype="uint8")
emptyBB = np.zeros((self.width,self.height),dtype="uint8")

for i in range(self.width):
for j in range(self.height):
temp = self.img[i,j]
#forward mapping
#backward mapping should change the forward mapping to the original image
xbb = int(xbb)
ybb = int(ybb)
if xf < 660 and yf < 660 and xf>0 and yf > 0:
emptyF[int(xf),int(yf)] = temp
else:
pass
if xbb < 660 and ybb < 660 and xbb>0 and ybb > 0:
emptyBB[(xbb),(ybb)] = temp
else:
pass
cv2.imshow('Forward', emptyF)
cv2.imshow('Backward', emptyBB)
def main():
rotator.showImg('normal', rotator)
rotator.printWH(rotator)
rotator.rotate(rotator)
cv2.waitKey(0)
cv2.destroyAllWindows

if __name__ == '__main__':
main()


Is there any way to improve this code or my algorithm? Any advise would be awesome.

NB. I also hav a problem with my backwards mapping. The output image has a lot of small black dots. Any suggestions to what that might be?

• I suspect that the black dots might be due to integer rounding of trigonometric results. – 200_success Nov 21 '18 at 1:25
• Why have you removed the code? You are not allowed do change it after receiving answers. I rolledback the changes. – t3chb0t Dec 10 '18 at 10:39

The most common method for getting rid of the black dots is to paint over each pixel of the entire destination image with pixels copied from computed positions in the source image, instead of painting the source image pixels into computed positions in the destination image.

for i in range(660):
for j in range(660):
xb = int(...)
yb = int(...)
if xb in range(self.width) and yb in range(self.height):
emptyF[i, j] = self.img[xb, yb]


Computing destination pixels positions from the source pixel positions may result in tiny areas unpainted in the destination due to numeric errors/limits.

Computing source pixels positions from the destination pixel position may result in a pixel value being copied to two adjacent locations, and other pixels never being copied from, but this is usually/often unnoticeable.

• Well that worked! Thanks man. How can you apply this method for both the forward and backwards mapping? – ACommonDane01 Nov 21 '18 at 11:41
• However, I can't seem to get the range(660) right instead of my range(self.width). Any suggestions to that? – ACommonDane01 Nov 21 '18 at 11:47
• Apply the same technique for both forward & reverse rotations. Ie, duplicate the last 4 lines and change xb/xf/emptyF to xf/yf/emptyBB. I don’t know what you mean by “get range(660) right” Even 660 is a magic number whose origin is a mystery. If code does not work properly, StackOverflow is a more appropriate forum to get help fixing code. – AJNeufeld Nov 21 '18 at 14:37
• Going from destination pixels to source pixels is the right idea, so that each destination pixel is painted just once. But looping in native Python over the individual pixels is going to be slow — better to use numpy.meshgrid to generate the coordinates and then transform them all at once. See §2 of this answer for details. – Gareth Rees Nov 21 '18 at 16:59