Affine Transformation from FairMOT official repository
| 147 | return NotImplemented |
| 148 | |
| 149 | class FairAffineTransform(Transform): |
| 150 | """ |
| 151 | Affine Transformation from FairMOT official repository |
| 152 | """ |
| 153 | def __init__(self, width, height, border_value, M, a): |
| 154 | super().__init__() |
| 155 | self._set_attributes(locals()) |
| 156 | |
| 157 | def apply_image(self, img: np.ndarray) -> np.ndarray: |
| 158 | return cv2.warpPerspective(img, self.M, dsize=(self.width, self.height), flags=cv2.INTER_LINEAR, borderValue=self.border_value) # BGR order borderValue |
| 159 | |
| 160 | def apply_coords(self, coords: np.ndarray) -> np.ndarray: |
| 161 | return coords |
| 162 | |
| 163 | def apply_box(self, coords: np.ndarray) -> np.ndarray: |
| 164 | if len(coords) > 0: |
| 165 | n = coords.shape[0] |
| 166 | points = coords.copy() |
| 167 | area0 = (points[:, 2] - points[:, 0]) * (points[:, 3] - points[:, 1]) |
| 168 | |
| 169 | # warp points |
| 170 | xy = np.ones((n * 4, 3)) |
| 171 | xy[:, :2] = points[:, [0, 1, 2, 3, 0, 3, 2, 1]].reshape(n * 4, 2) # x1y1, x2y2, x1y2, x2y1 |
| 172 | xy = (xy @ self.M.T)[:, :2].reshape(n, 8) |
| 173 | |
| 174 | # create new boxes |
| 175 | x = xy[:, [0, 2, 4, 6]] |
| 176 | y = xy[:, [1, 3, 5, 7]] |
| 177 | xy = np.concatenate((x.min(1), y.min(1), x.max(1), y.max(1))).reshape(4, n).T |
| 178 | |
| 179 | # apply angle-based reduction |
| 180 | radians = self.a * math.pi / 180 |
| 181 | reduction = max(abs(math.sin(radians)), abs(math.cos(radians))) ** 0.5 |
| 182 | x = (xy[:, 2] + xy[:, 0]) / 2 |
| 183 | y = (xy[:, 3] + xy[:, 1]) / 2 |
| 184 | w = (xy[:, 2] - xy[:, 0]) * reduction |
| 185 | h = (xy[:, 3] - xy[:, 1]) * reduction |
| 186 | xy = np.concatenate((x - w / 2, y - h / 2, x + w / 2, y + h / 2)).reshape(4, n).T |
| 187 | |
| 188 | # reject warped points outside of image |
| 189 | #np.clip(xy[:, 0], 0, width, out=xy[:, 0]) |
| 190 | #np.clip(xy[:, 2], 0, width, out=xy[:, 2]) |
| 191 | #np.clip(xy[:, 1], 0, height, out=xy[:, 1]) |
| 192 | #np.clip(xy[:, 3], 0, height, out=xy[:, 3]) |
| 193 | w = xy[:, 2] - xy[:, 0] |
| 194 | h = xy[:, 3] - xy[:, 1] |
| 195 | area = w * h |
| 196 | ar = np.maximum(w / (h + 1e-16), h / (w + 1e-16)) |
| 197 | i = (w > 4) & (h > 4) & (area / (area0 + 1e-16) > 0.1) & (ar < 10) |
| 198 | |
| 199 | return xy[i] |
| 200 | else: |
| 201 | return coords |
| 202 | |
| 203 | def apply_segmentation(self, segmentation): |
| 204 | return NotImplemented |
| 205 | |
| 206 | def inverse(self): |