Rotate polygons without cutting edges

I am writing an augmentation code to rotate annotated polygons inside images. I wrote a code but it’s not working right. Just Copy paste the code and you can get the results. Thank you for helping me out.

Image:

enter image description here

Need to rotate the image as well as a polygon for respective angle. Currently, I am not able to rotate the polygon

enter image description here

The image is rotated but the polygon is still in its place.

I tried This code. It rotates the polygon but not at the right position

import math
from PIL import Image, ImageDraw
from PIL import ImagePath 
from PIL import Image
import matplotlib.pyplot as plt
from math import sin, cos, radians
import requests
from io import BytesIO

def rotatePolygon(polygon, degrees, height, width):
    """ 
    Description:
    
        Rotate polygon the given angle about its center. 
        
    Input:
        polygon (list of tuples)  : list of tuples with (x,y) cordinates 
                                    e.g [(1,2), (2,3), (4,5)]
        
        degrees int               : Rotation Degrees
    
    Output:
    
        polygon (list of tuples)  : Polygon rotated on angle(degrees)
                                e.g [(1,2), (2,3), (4,5)]
    
    """
    # Convert angle to radians
    theta = radians(degrees)  
    
    # Getting sin and cos with respect to theta
    cosang, sinang = cos(theta), sin(theta) 

    # find center point of Polygon to use as pivot
    y, x = [i for i in zip(*polygon)]
    
    # find center point of Polygon to use as pivot
    
    cx = width / 2
    cy = height / 2
    
    # Rotating every point
    new_points = []
    for x, y in zip(x, y):
        tx, ty = x-cx, y-cy
        new_x = (tx*cosang + ty*sinang) + cx
        new_y = (-tx*sinang + ty*cosang) + cy
        new_points.append((new_y, new_x))
    return new_points



# Polygon
xy = [(85, 384), (943, 374), (969, 474), (967, 527), (12, 540), (7, 490)]
degrees = 270


# Getting Image from URL
try:
    img = Image.open("polygon_image.png")
except:
    url = "https://github.com/SohaibAnwaar/Mask---RCNN-Polygons-/blob/main/2_image_augmentation/extras/problamatic_image.jpg?raw=true"
    response = requests.get(url)
    img = Image.open(BytesIO(response.content))
    img.save("polygon_image.png")



# Rotating Image
rotated_image = img.rotate(degrees,expand = True)
h, w = img.size

print("NotRotated", xy)
rotated_xy = rotatePolygon(xy, 360 - (degrees), h, w)



# Ploting Rotated Image
img1 = ImageDraw.Draw(rotated_image)  
img1.polygon(rotated_xy, fill ="#FFF000", outline ="blue") 


# Ploting Straight Image
img1 = ImageDraw.Draw(img)  
img1.polygon(xy, fill ="#FFF000", outline ="blue") 

plt.imshow(rotated_image)
plt.show()


plt.imshow(img)
plt.show()

Answer

Rotation equations are:

xnew = x * cos(theta) - y * sin(theta)
ynew = x * sin(theta) + y * cos(theta)

only mistake you are doing is this:

new_x = (tx*cosang - ty*sinang) + cy
new_y = (tx*sinang + ty*cosang) + cx

After rotating image, cx and cy should be changed

Your complete code is as below:

import math
import numpy as np
from PIL import Image, ImageDraw
from PIL import ImagePath 
from PIL import Image
import matplotlib.pyplot as plt
from math import sin, cos, radians
import requests
from io import BytesIO

def rotatePolygon(polygon, degrees, height, width):
    """ 
    Description:
    
        Rotate polygon the given angle about its center. 
        
    Input:
        polygon (list of tuples)  : list of tuples with (x,y) cordinates 
                                    e.g [(1,2), (2,3), (4,5)]
        
        degrees int               : Rotation Degrees
    
    Output:
    
        polygon (list of tuples)  : Polygon rotated on angle(degrees)
                                e.g [(1,2), (2,3), (4,5)]
    
    """
    # Convert angle to radians
    theta = radians(degrees)
    
    # Getting sin and cos with respect to theta
    cosang, sinang = cos(theta), sin(theta) 

    # find center point of Polygon to use as pivot
    y, x = [i for i in zip(*polygon)]
    
    # find center point of Polygon to use as pivot
    
    cx1 = width[0] / 2
    cy1 = height[0] / 2
    cx2 = width[1] / 2
    cy2 = height[1] / 2
    
    # Rotating every point
    new_points = []
    for x, y in zip(x, y):
        tx, ty = x-cx1, y-cy1
        new_x = (tx*cosang - ty*sinang) + cx2
        new_y = (tx*sinang + ty*cosang) + cy2
        new_points.append((new_y, new_x))
    return new_points



# Polygon
xy = [(85, 384), (943, 374), (969, 474), (967, 527), (12, 540), (7, 490)]
degrees = 270


# Getting Image from URL
try:
    img = Image.open("polygon_image.png")
except:
    url = "https://github.com/SohaibAnwaar/Mask---RCNN-Polygons-/blob/main/2_image_augmentation/extras/problamatic_image.jpg?raw=true"
    response = requests.get(url)
    img = Image.open(BytesIO(response.content))
    img.save("polygon_image.png")



# Rotating Image
rotated_image = img.rotate(degrees,expand = True)
h1, w1 = img.size
h2, w2 = rotated_image.size

print("NotRotated", xy)
rotated_xy = rotatePolygon(xy, degrees, [h1,h2], [w1,w2])



# Ploting Rotated Image
img1 = ImageDraw.Draw(rotated_image)  
img1.polygon(rotated_xy, fill ="#FFF000", outline ="blue") 


# Ploting Straight Image
img1 = ImageDraw.Draw(img)  
img1.polygon(xy, fill ="#FFF000", outline ="blue") 

plt.imshow(rotated_image)
plt.show()


plt.imshow(img)
plt.show()