Spaces:
Running
Running
import numpy as np | |
class GraspCoder: | |
""" | |
This class is to encode grasp annotations similar to BoxCoder class | |
It is supposed to support the following functions: | |
1. Encode grasp annotations: | |
(x1, y1, x2, y2, x3, y3, x4, y4) -> (x_center, y_center, width, height, sine(theta)) | |
2. Decode grasp annotations: | |
(x_center, y_center, width, height, sine(theta)) -> (x1, y1, x2, y2, x3, y3, x4, y4) | |
3. Resize box grasp annotations when resizing image | |
4. Transform box according to various image augmentations | |
One GraspCoder class should encode annotations of one image only | |
""" | |
def __init__(self, height, width, grasp_annos, grasp_annos_reformat=None): | |
""" | |
Args: | |
height: height of image | |
width: width of image | |
grasp_annos: list of numpy.arrays, each of length 8, in format of (x1, y1, x2, y2, x3, y3, x4, y4) | |
""" | |
self.height = height | |
self.width = width | |
self.grasp_annos = grasp_annos | |
self.grasp_annos_reformat = grasp_annos_reformat | |
def __len__(self): | |
return len(self.grasp_annos) | |
def encode(self, normalize=True): | |
""" | |
(x1, y1, x2, y2, x3, y3, x4, y4) -> (x_center, y_center, width, height, sine(theta)) | |
Args: | |
normalize -> bool: return values normalized to 0~1 or not | |
Returns: | |
grasp_annos_reformat: List of numpy.array | |
""" | |
grasp_annos_reformat = [] | |
for grasp in self.grasp_annos: | |
x1, y1, x2, y2, x3, y3, x4, y4 = tuple(grasp) | |
if (x1 + x2) < (x3 + x4): | |
x1, y1, x2, y2, x3, y3, x4, y4 = x3, y3, x4, y4, x1, y1, x2, y2 | |
x_center = (x1 + x3)/2 | |
y_center = (y1 + y3)/2 | |
width = np.sqrt((x1 - x2)**2 + (y1 - y2)**2) | |
height = np.sqrt((x2 - x3)**2 + (y2 - y3)**2) | |
sine = ((y1 + y2)/2 - y_center) / (height / 2) | |
if normalize: | |
x_center /= self.width | |
y_center /= self.height | |
width /= self.width | |
height /= self.height | |
sine = (sine + 1) / 2 | |
grasp_annos_reformat.append(np.array([x_center, y_center, width, height, sine])) | |
self.grasp_annos_reformat = grasp_annos_reformat | |
return grasp_annos_reformat | |
def decode(self): | |
""" | |
Decode normalized grasp_annos_reformat, will overwrite self.grasp_annos, and return the overwritten value | |
(x1, y1, x2, y2, x3, y3, x4, y4) -> (x_center, y_center, width, height, sine(theta)) | |
Returns: | |
grasp_annos: List of numpy.array | |
""" | |
grasp_annos = [] | |
for grasp in self.grasp_annos_reformat: | |
x_center, y_center, width, height, sine = tuple(grasp) | |
x_center *= self.width | |
y_center *= self.height | |
width *= self.width | |
height *= self.height | |
sine = sine * 2 - 1 | |
cosine = np.sqrt(1 - sine ** 2) | |
angle = np.arcsin(sine) | |
x1 = x_center + cosine * height / 2 + sine * width / 2 | |
x2 = x_center + cosine * height / 2 - sine * width / 2 | |
y1 = y_center + sine * height / 2 - cosine * width / 2 | |
y2 = y_center + sine * height / 2 + cosine * width / 2 | |
x3 = x_center * 2 - x1 | |
x4 = x_center * 2 - x2 | |
y3 = y_center * 2 - y1 | |
y4 = y_center * 2 - y2 | |
grasp_annos.append(np.array([x1, y1, x2, y2, x3, y3, x4, y4])) | |
self.grasp_annos = grasp_annos | |
return grasp_annos | |
def resize(self, new_size): | |
""" | |
Resize the grasp annotations according to resized image | |
Args: | |
new_size -> Tuple: (new_width, new_height) | |
new_height: The resized image height | |
new_width: The resized image width | |
Returns: | |
self | |
""" | |
new_width, new_height = new_size | |
grasp_annos = self.grasp_annos | |
old_height, old_width = self.height, self.width | |
resized_grasp_annos = [] | |
for grasp in grasp_annos: | |
grasp[0::2] = grasp[0::2] / old_width * new_width | |
grasp[1::2] = grasp[1::2] / old_height * new_height | |
resized_grasp_annos.append(grasp) | |
self.grasp_annos = resized_grasp_annos | |
self.height, self.width = new_height, new_width | |
return self | |
def transpose(self, axis): | |
""" | |
For Horizontal/Vertical flip | |
Args: | |
axis: 0 represents X axis, 1 represnets Y axis | |
Returns: | |
self | |
""" | |
grasp_annos = self.grasp_annos | |
flipped_grasp_annos = [] | |
if axis == 0: | |
for grasp in grasp_annos: | |
grasp[0::2] = self.width - grasp[0::2] | |
flipped_grasp_annos.append(grasp) | |
elif axis == 1: | |
for grasp in grasp_annos: | |
grasp[1::2] = self.height - grasp[1::2] | |
flipped_grasp_annos.append(grasp) | |
self.grasp_annos = flipped_grasp_annos | |
return self |