from typing import Union
import cv2
from networkx.algorithms.isolate import is_isolate
"""
Modulo per ruotare un'immagine sfruttando openCV2.
"""
[documenti]
def rotate_image_and_label(image: cv2.typing.MatLike, labels: Union[list[str], str], angle: float) -> (
cv2.typing.MatLike, Union[list[str], str]):
"""
Questo metodo permette di ruotare l'immagine e la rispettiva label. La label deve essere nei seguenti formati
(class x_1 y_1 x_2 y_2 ... x_n y_n) oppure (class centro_x centro_y height width). Eccetto class ciascun valore
presente nella label deve essere normalizzato nell'intervallo [0, 1]. In base al formato della label verrà chiamato
il metodo corretto.
Args:
image: l'immagine da ruotare.
labels: la/le label da ruotare.
angle: l'angolo di rotazione dell'immagine.
Returns:
l'immagine e la label ruotate.
"""
parts = labels[0].strip().split()
coords = list(map(float, parts[1:]))
if len(coords) == 4:
return __rotate_image_and_label_bb(image, labels, angle)
else:
return __rotate_image_and_label_poly(image, labels, angle)
def __rotate_image_and_label_bb(image: cv2.typing.MatLike, labels: Union[list[str], str], angle: float) -> (
cv2.typing.MatLike, Union[list[str], str]):
"""
Questo metodo permette di ruotare le immagini che hanno una label quadrata o rettangolare, di conseguenza il formato
della label sarà: (class centro_x centro_y height width).
Parameters:
image: l'immagine da ruotare.
labels: la/le label da ruotare
angle: l'angolo di rotazione.
Returns:
l'immagine e la label ruotate.
"""
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0) # Matrice di rotazione
rotated_image = cv2.warpAffine(image, rotation_matrix, (w, h))
rotated_labels = []
for label in labels:
parts = label.strip().split()
if not parts:
continue
class_id = parts[0]
coords = list(map(float, parts[1:]))
x_n, y_n, w_n, h_n = coords
x = x_n * w
y = y_n * h
x_new_pixel = rotation_matrix[0, 0] * x + rotation_matrix[0, 1] * y + rotation_matrix[0, 2]
y_new_pixel = rotation_matrix[1, 0] * x + rotation_matrix[1, 1] * y + rotation_matrix[1, 2]
x_new = x_new_pixel / w
y_new = y_new_pixel / h
rotated_label = [class_id] + list(map(str, [x_new, y_new, w_n, h_n]))
rotated_labels.append(' '.join(rotated_label))
return rotated_image, rotated_labels
def __rotate_image_and_label_poly(image: cv2.typing.MatLike, labels: Union[list[str], str], angle: float) -> (
cv2.typing.MatLike, Union[list[str], str]):
"""
Questo metodo permette di ruotare le immagini che hanno una label quadrata o rettangolare, di conseguenza il formato
della label sarà: (class x_1 y_1 x_2 y_2 ... x_n y_n).
Parameters:
image: l'immagine da ruotare.
labels: la/le label da ruotare
angle: l'angolo di rotazione.
Returns:
l'immagine e la label ruotate.
"""
# cerco parametri rotazione
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0) # Matrice di rotazione
# applico all'immagine la matrice
rotated_image = cv2.warpAffine(image, rotation_matrix, (w, h))
# ruoto le possibili label
rotated_labels = []
for label in labels:
parts = label.strip().split()
if not parts:
continue
class_id = parts[0]
coords = list(map(float, parts[1:]))
x_coords = [coords[i] * w for i in range(0, len(coords), 2)]
y_coords = [coords[i + 1] * h for i in range(0, len(coords), 2)]
# applico rotazione a ogni coppia di coordinate
rotated_coords = []
for x, y in zip(x_coords, y_coords):
# applico matrice di rotazione alle coordinate della label in modo da ottenere la stessa rotazione
# dell'immagine
x_new_pixel = rotation_matrix[0, 0] * x + rotation_matrix[0, 1] * y + rotation_matrix[0, 2]
y_new_pixel = rotation_matrix[1, 0] * x + rotation_matrix[1, 1] * y + rotation_matrix[1, 2]
# rinormalizzo i punti
x_new = x_new_pixel / w
y_new = y_new_pixel / h
rotated_coords.extend([x_new, y_new])
rotated_label = [class_id] + list(map(str, rotated_coords))
rotated_labels.append(' '.join(rotated_label))
return rotated_image, rotated_labels