def __call__(self, results): """Call function to rotate image, semantic segmentation maps. Args: results (dict): Result dict from loading pipeline. Returns: dict: Rotated results. """ rotate = True if np.random.rand() < self.prob else False degree = np.random.uniform(min(*self.degree), max(*self.degree)) if rotate: # rotate image results['img'] = mmcv.imrotate(results['img'], angle=degree, border_value=self.pal_val, center=self.center, auto_bound=self.auto_bound) # rotate segs for key in results.get('seg_fields', []): results[key] = mmcv.imrotate(results[key], angle=degree, border_value=self.seg_pad_val, center=self.center, auto_bound=self.auto_bound, interpolation='nearest') return results
def __call__(self, results): """Call function to randomly rotate images, semantic segmentation maps. Args: results (dict): Result dict from loading pipeline. Returns: dict: Randomly rotated results. """ if 'rotation' not in results: rotation = True if np.random.rand( ) < self.rotation_ratio else False results['rotation'] = rotation if results['rotation']: img = results['img'] rotation_degree = self.get_rotation_degree() # rotate the image and semantic segmentation map img = mmcv.imrotate(img, rotation_degree) results['img'] = img for key in results.get('seg_fields', []): results[key] = self.rotate(results[key], rotation_degree, borderValue=255, interpolation='nearest') return results
def rotate(self, out_shape, angle, center=None, scale=1.0, fill_val=0): """Rotate the BitmapMasks. Args: out_shape (tuple[int]): Shape for output mask, format (h, w). angle (int | float): Rotation angle in degrees. Positive values mean counter-clockwise rotation. center (tuple[float], optional): Center point (w, h) of the rotation in source image. If not specified, the center of the image will be used. scale (int | float): Isotropic scale factor. fill_val (int | float): Border value. Default 0 for masks. Returns: BitmapMasks: Rotated BitmapMasks. """ if len(self.masks) == 0: rotated_masks = np.empty((0, *out_shape), dtype=self.masks.dtype) else: rotated_masks = mmcv.imrotate( self.masks.transpose((1, 2, 0)), angle, center=center, scale=scale, border_value=fill_val) if rotated_masks.ndim == 2: # case when only one mask, (h, w) rotated_masks = rotated_masks[:, :, None] # (h, w, 1) rotated_masks = rotated_masks.transpose( (2, 0, 1)).astype(self.masks.dtype) return BitmapMasks(rotated_masks, *out_shape)
def __call__(self, results): angle = random.uniform(self.degrees[0], self.degrees[1]) for k in self.keys: results[k] = mmcv.imrotate(results[k], angle) if results[k].ndim == 2: results[k] = np.expand_dims(results[k], axis=2) results['degrees'] = self.degrees return results
def _rotate_seg(self, results, angle, center=None, scale=1.0, fill_val=255): """Rotate the segmentation map.""" for key in results.get('seg_fields', []): seg = results[key].copy() results[key] = mmcv.imrotate( seg, angle, center, scale, border_value=fill_val).astype(seg.dtype)
def __call__(self, results): if np.random.rand() > self.prob: return results angle = random_negative(self.angle, self.random_negative_prob) for key in results.get('img_fields', ['img']): img = results[key] img_rotated = mmcv.imrotate(img, angle, center=self.center, scale=self.scale, border_value=self.pad_val, interpolation=self.interpolation) results[key] = img_rotated.astype(img.dtype) return results
def test_imrotate(self): img = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).astype(np.uint8) assert_array_equal(mmcv.imrotate(img, 0), img) img_r = np.array([[7, 4, 1], [8, 5, 2], [9, 6, 3]]) assert_array_equal(mmcv.imrotate(img, 90), img_r) img_r = np.array([[3, 6, 9], [2, 5, 8], [1, 4, 7]]) assert_array_equal(mmcv.imrotate(img, -90), img_r) img = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]).astype(np.uint8) img_r = np.array([[0, 6, 2, 0], [0, 7, 3, 0]]) assert_array_equal(mmcv.imrotate(img, 90), img_r) img_r = np.array([[1, 0, 0, 0], [2, 0, 0, 0]]) assert_array_equal(mmcv.imrotate(img, 90, center=(0, 0)), img_r) img_r = np.array([[255, 6, 2, 255], [255, 7, 3, 255]]) assert_array_equal(mmcv.imrotate(img, 90, border_value=255), img_r) img_r = np.array([[5, 1], [6, 2], [7, 3], [8, 4]]) assert_array_equal(mmcv.imrotate(img, 90, auto_bound=True), img_r) with pytest.raises(ValueError): mmcv.imrotate(img, 90, center=(0, 0), auto_bound=True)
def _rotate_img(self, results, angle, center=None, scale=1.0): """Rotate the image. Args: results (dict): Result dict from loading pipeline. angle (float): Rotation angle in degrees, positive values mean clockwise rotation. Same in ``mmcv.imrotate``. center (tuple[float], optional): Center point (w, h) of the rotation. Same in ``mmcv.imrotate``. scale (int | float): Isotropic scale factor. Same in ``mmcv.imrotate``. """ for key in results.get('img_fields', ['img']): img = results[key].copy() img_rotated = mmcv.imrotate( img, angle, center, scale, border_value=self.img_fill_val) results[key] = img_rotated.astype(img.dtype)
def __call__(self, results): if np.random.rand() > self.probablity: return results # if 'flip' not in results: # flip = True if np.random.rand() < self.flip_ratio else False # results['flip'] = flip # if results['flip']: else: angle = random.randint(1, 3) * 90 results['img'] = mmcv.imrotate(results['img'], angle) h, w = results['img_shape'][:2] center = (w - 1) * 0.5, (h - 1) * 0.5 mat = cv2.getRotationMatrix2D(center=center, angle=angle, scale=1.0) for key in results.get('bbox_fields', []): results[key] = self.bbox_rotate(results[key], results['img_shape'], mat) return results
def __call__(self, results): if 'rotate' not in results: rotate = True if np.random.rand() < self.rotate_ratio else False results['rotate'] = rotate if results['rotate']: # rotate image image = results['img'] h, w = image.shape[:2] rotated_image = mmcv.imrotate(image, angle=self.angle) results['img'] = rotated_image # rotate bboxes for key in results.get('bbox_fields', []): bboxes = results[key] corners = self.get_corners(bboxes) corners = np.hstack((corners, bboxes[:, 4:])) corners[:, :8] = self.bbox_rotate(corners[:, :8], results['img_shape']) new_bboxes = self.get_enclosing_box(corners) # new_bboxes = self.bbox_clip(new_bboxes, [0, 0, w, h]) results[key] = new_bboxes return results
def main(): bgr_img = mmcv.imread(image_path) h, w, _ = bgr_img.shape # convert color rgb_img = mmcv.bgr2rgb(bgr_img) # resize resize_img = mmcv.imresize(rgb_img, size=(256, 256)) # rotate rotate_img = mmcv.imrotate(rgb_img, angle=45) # flip flip_img = mmcv.imflip(rgb_img, direction='horizontal') # crop if h <= w: y_min, y_max = 0, h x_min = int((w - h) / 2) x_max = x_min + h else: x_min, x_max = 0, h y_min = int((h - w) / 2) y_max = y_min + w bbox = np.array([x_min, y_min, x_max, y_max]) crop_img = mmcv.imcrop(rgb_img, bbox) # padding max_size = max(h, w) pad_img = mmcv.impad(rgb_img, shape=(max_size, max_size), padding_mode='constant') mmcv.imshow(mmcv.rgb2bgr(pad_img))
def __call__(self, img_group, scale, crop_history=None, flip=False, rotate=None, keep_ratio=True, dropout_prob=None, div_255=False, transpose=True, stack=True): # 1. rescale if keep_ratio: tuple_list = [ mmcv.imrescale(img, scale, return_scale=True) for img in img_group ] img_group, scale_factors = list(zip(*tuple_list)) scale_factor = scale_factors[0] else: tuple_list = [ mmcv.imresize(img, scale, return_scale=True) for img in img_group ] img_group, w_scales, h_scales = list(zip(*tuple_list)) scale_factor = np.array( [w_scales[0], h_scales[0], w_scales[0], h_scales[0]], dtype=np.float32) # 2. rotate if rotate is not None: img_group = [mmcv.imrotate(img, rotate) for img in img_group] # 3. crop (if necessary) if crop_history is not None: self.op_crop = GroupCrop(crop_history) if self.op_crop is not None: img_group, crop_quadruple = self.op_crop(img_group) else: crop_quadruple = None img_shape = img_group[0].shape # 4. flip if flip: img_group = [mmcv.imflip(img) for img in img_group] # 5a. extra augmentation if self.extra_augm is not None: img_group = self.extra_augm(img_group) # 5b. coarse dropout if self.dropout_scale is not None and dropout_prob is not None and dropout_prob > 0.0: dropout_mask = self._coarse_dropout_mask(img_group[0].shape, dropout_prob, self.dropout_scale) img_group = [img * dropout_mask for img in img_group] # 6a. div_255 if div_255: img_group = [ mmcv.imnormalize(img, 0, 255, False) for img in img_group ] # 6b. normalize if self.mean is not None and self.std is not None: img_group = [ mmcv.imnormalize(img, self.mean, self.std, self.to_rgb) for img in img_group ] elif self.to_rgb: img_group = [mmcv.bgr2rgb(img) for img in img_group] # 7. pad if self.size_divisor is not None: img_group = [ mmcv.impad_to_multiple(img, self.size_divisor) for img in img_group ] pad_shape = img_group[0].shape else: pad_shape = img_shape # 8. transpose if transpose: img_group = [img.transpose((2, 0, 1)) for img in img_group] # 9. stack into numpy.array if stack: img_group = np.stack(img_group, axis=0) return img_group, img_shape, pad_shape, scale_factor, crop_quadruple
mmcv.imresize(img, (1000, 600), return_scale=True) # resize to the same size of another image mmcv.imresize_like(img, dst_img, return_scale=False) # resize by a ratio mmcv.imrescale(img, 0.5) # resize so that the max edge no longer than 1000, short edge no longer than 800 # without changing the aspect ratio mmcv.imrescale(img, (1000, 800)) # =============Rotate============== # rotate the image clockwise by 30 degrees. img_ = mmcv.imrotate(img, 30) # rotate the image counterclockwise by 90 degrees. img_ = mmcv.imrotate(img, -90) # rotate the image clockwise by 30 degrees, and rescale it by 1.5x at the same time. img_ = mmcv.imrotate(img, 30, scale=1.5) # rotate the image clockwise by 30 degrees, with (100, 100) as the center. img_ = mmcv.imrotate(img, 30, center=(100, 100)) # rotate the image clockwise by 30 degrees, and extend the image size. img_ = mmcv.imrotate(img, 30, auto_bound=True)
def __call__(self, results): img, gt_bboxes, gt_labels = [ results[k] for k in ('img', 'gt_bboxes', 'gt_labels') ] img_h, img_w, _ = results['img_shape'] if img_h > 1000: gt_lst = self.all_gt_bboxes() if np.random.rand() < self.keep_ratio: gt_bboxes_ = gt_bboxes.tolist() gt_labels_ = gt_labels.tolist() else: ind = np.random.randint(len(self.normal_imgs)) normal_path = self.normal_imgs[ind] normal_img = mmcv.imread(normal_path) normal_img = mmcv.imresize_like(normal_img, img) img = normal_img gt_bboxes_, gt_labels_ = [], [] defects = random.choices(gt_lst, k=self.max_per_img) defects = sorted(defects, key=(lambda x: x[-1] * x[-2]), reverse=True) for det in defects: defect_img = cv2.imread(os.path.join(self.img_path, det[0])) label = det[1] x, y, w, h = list(map(int, det[2:])) defect = defect_img[y:y + h, x:x + w, :] mode = np.random.randint(3) # scale if mode == 0: defect = self.bbox_scale(defect) h, w = defect.shape[:2] # rotate elif mode == 1: ctx = x + w * 0.5 cty = y + h * 0.5 corners = np.hstack( (x, y, x + w, y, x, y + h, x + w, y + h)) h, w, angle = self.bbox_rotate(corners, h, w) rotated_img = mmcv.imrotate(defect_img, -angle, center=(ctx, cty)) x1 = int(ctx - w * 0.5) y1 = int(cty - h * 0.5) x2 = x1 + w y2 = y1 + h defect = rotated_img[y1:y2, x1:x2, :] try: xmin = np.random.randint(self.left_border, img_w - self.right_border - w) ymin = np.random.randint(self.top_border, img_h - self.bottom_border - h) xmax = xmin + w ymax = ymin + h img[ymin:ymax, xmin:xmax, :] = cv2.addWeighted( defect, 1, img[ymin:ymax, xmin:xmax, :], 0, 0) gt_bboxes_.append([xmin, ymin, xmax, ymax]) gt_labels_.append(label) except: continue results['img'] = img results['gt_bboxes'] = np.array(gt_bboxes_, dtype=np.float32) results['gt_labels'] = np.array(gt_labels_, dtype=np.int64) return results
def rotate_lines_img(lines, img, angle, obj_rep, debug_rotation=0): ''' The img sizes of input and output are the same. angle in degree ''' assert obj_rep == 'XYXYSin2' assert img.ndim == 3 assert lines.ndim == 2 assert lines.shape[1] == 5 assert img.shape[2] == 4 img_shape = img.shape[:2] if debug_rotation: add_cross = 1 if add_cross: img[:,:,1:] = np.abs(img[:,:,1:])*255 lines = add_cross_in_lines(lines, img_shape) #_show_lines_ls_points_ls(img[:,:,0], [lines]) #_show_lines_ls_points_ls(img[:,:,1:], [lines]) #_show_lines_ls_points_ls(img[:,:,:3], [lines]) pass n = lines.shape[0] if n == 0: return lines, img lines_2endpts = OBJ_REPS_PARSE.encode_obj(lines, obj_rep, 'RoLine2D_2p').reshape(n,2,2) #lines_2endpts = decode_line_rep(lines, obj_rep).reshape(n,2,2) h, w = img_shape assert h%2 == 0 assert w%2 == 0 center = ((w - 1) * 0.5, (h - 1) * 0.5) scale = 1.0 matrix = cv2.getRotationMatrix2D(center, -angle, scale) ones = np.ones([n,2,1], dtype=lines.dtype) tmp = np.concatenate([lines_2endpts, ones], axis=2) lines_2pts_r = np.matmul( tmp, matrix.T ) # (1) rotate the lines lines_rotated = OBJ_REPS_PARSE.encode_obj(lines_2pts_r.reshape(-1,4), 'RoLine2D_2p', obj_rep) #lines_rotated = encode_line_rep(lines_2pts_r, obj_rep) #_show_lines_ls_points_ls(img[:,:,0], [lines_rotated]) # (3) scale the lines to fit the image size # Move before scaling can increase the scale ratio x_min_ = lines_rotated[:,[0,2]].min() x_max_ = lines_rotated[:,[0,2]].max() y_min_ = lines_rotated[:,[1,3]].min() y_max_ = lines_rotated[:,[1,3]].max() border_pad = 4 gap_x0 = 0 - x_min_ gap_y0 = 0 - y_min_ gap_x1 = x_max_ - (w-1) gap_y1 = y_max_ - (h-1) gap_x = np.ceil(np.array([gap_x0, gap_x1, 0]).max()) gap_y = np.ceil(np.array([gap_y0, gap_y1, 0]).max()) scale_x = (w-border_pad*2) / (w+gap_x*2.0) scale_y = (h-border_pad*2) / (h+gap_y*2.0) scale = min(scale_x, scale_y) scale = np.floor(scale * 100)/100.0 lines_rotated[:,:4] = ((lines_rotated[:,:4].reshape(-1,2) - center) * scale + center).reshape(-1,4) # (4) rotate the image (do not scale at this stage) if debug_rotation: if add_cross: add_cross_in_img(img) #_show_lines_ls_points_ls(img[:,:,:3], [lines]) img_big = np.pad(img, ( (h//2,h//2), (w//2,w//2), (0,0) ), 'constant', constant_values=0) img_r = mmcv.imrotate(img_big, angle, scale=scale) # (5) Move the image new_img = np.zeros([h,w], dtype=lines.dtype) h1,w1 = img_r.shape[:2] region = np.array([ w1/2-w/2, h1/2-h/2, w1/2+w/2-1, h1/2+h/2-1, ]) region_int = region.astype(np.int32) new_img = mmcv.imcrop(img_r, region_int) assert new_img.shape[:2] == img_shape # rotate the surface normal new_img[:,:,[1,2]] = np.matmul( new_img[:,:,[1,2]], matrix[:,:2].T ) lines_rotated = lines_rotated.astype(np.float32) new_img = new_img.astype(np.float32) assert lines_rotated[:,:4].min() > 0 if debug_rotation: print(f'\nscale: {scale}') #_show_lines_ls_points_ls(img[:,:,:3], [lines]) _show_lines_ls_points_ls(new_img[:,:,0], [lines_rotated]) #_show_img_with_norm(img) #_show_img_with_norm(new_img) if add_cross: lines_rotated = lines_rotated[:-4] pass return lines_rotated, new_img, scale
def rotate_lines_img(lines, img, angle, obj_rep, check_by_cross=False): assert img.ndim == 3 assert lines.ndim == 2 assert lines.shape[1] == 5 img_shape = img.shape[:2] if check_by_cross: lines = add_cross_in_lines(lines, img_shape) n = lines.shape[0] if n == 0: return lines, img lines_2endpts = decode_line_rep(lines, obj_rep).reshape(n, 2, 2) h, w = img_shape assert h % 2 == 0 assert w % 2 == 0 center = ((w - 1) * 0.5, (h - 1) * 0.5) scale = 1.0 matrix = cv2.getRotationMatrix2D(center, -angle, scale) ones = np.ones([n, 2, 1], dtype=lines.dtype) tmp = np.concatenate([lines_2endpts, ones], axis=2) lines_2pts_r = np.matmul(tmp, matrix.T) # (1) rotate the lines lines_rotated = encode_line_rep(lines_2pts_r, obj_rep) # (2) move the lines to center x_min = lines_rotated[:, [0, 2]].min() x_max = lines_rotated[:, [0, 2]].max() y_min = lines_rotated[:, [1, 3]].min() y_max = lines_rotated[:, [1, 3]].max() x_cen = (x_min + x_max) / 2 y_cen = (y_min + y_max) / 2 x_offset = np.floor(x_cen - (w - 1) / 2) * 1 y_offset = np.floor(y_cen - (h - 1) / 2) * 1 lines_rotated[:, [0, 2]] -= x_offset lines_rotated[:, [1, 3]] -= y_offset # (3) scale the lines to fit the image size # Move before scaling can increase the scale ratio x_min_ = lines_rotated[:, [0, 2]].min() x_max_ = lines_rotated[:, [0, 2]].max() y_min_ = lines_rotated[:, [1, 3]].min() y_max_ = lines_rotated[:, [1, 3]].max() gap_x0 = 0 - x_min_ gap_y0 = 0 - y_min_ gap_x1 = x_max_ - (w - 1) gap_y1 = y_max_ - (h - 1) gap_x = np.ceil(np.array([gap_x0, gap_x1, 0]).max()) gap_y = np.ceil(np.array([gap_y0, gap_y1, 0]).max()) scale_x = w / (w + gap_x * 2.0) scale_y = h / (h + gap_y * 2.0) scale = min(scale_x, scale_y) * 0.97 scale = np.floor(scale * 100) / 100.0 if scale < 1: scale = scale - 0.03 #print(f'scale: {scale}') center = np.repeat(center, 2) lines_rotated[:, :4] = (lines_rotated[:, :4] - center) * scale + center # (4) rotate the image (do not scale at this stage) if check_by_cross: add_cross_in_img(img) img_big = np.zeros([h * 2, w * 2, img.shape[2]], dtype=lines.dtype) img_big[int(h / 2):int(h / 2 * 3), int(w / 2):int(w / 2 * 3)] = img img_r = mmcv.imrotate(img_big, angle, scale=scale) # (5) Move the image new_img = np.zeros([h, w], dtype=lines.dtype) h1, w1 = img_r.shape[:2] region = np.array([(h1 - h) / 2 + x_offset * scale, (w1 - w) / 2 + y_offset * scale, (h1 - h) / 2 + h - 1 + x_offset * scale, (w1 - w) / 2 + w - 1 + y_offset * scale]) region_int = region.astype(np.int32) new_img = mmcv.imcrop(img_r, region_int) assert new_img.shape[:2] == img_shape # rotate the surface normal new_img[:, :, [1, 2]] = np.matmul(new_img[:, :, [1, 2]], matrix[:, :2].T) #_show_img_with_norm(img) #_show_img_with_norm(new_img) lines_rotated = lines_rotated.astype(np.float32) new_img = new_img.astype(np.float32) #_show_lines_ls_points_ls(img[:,:,:3]*255, lines) #_show_lines_ls_points_ls(new_img[:,:,:3], lines_rotated) return lines_rotated, new_img
import numpy as np import wwtool import mmcv if __name__ == '__main__': thetaobbs = [[400, 400, 300, 150, 45 * np.pi / 180], [600, 600, 300, 200, 135 * np.pi / 180]] pointobbs = [wwtool.thetaobb2pointobb(thetaobb) for thetaobb in thetaobbs] img = wwtool.generate_image(1024, 1024) img_origin = img.copy() wwtool.imshow_rbboxes(img, thetaobbs, win_name='origin') rotation_angle = 45 rotation_anchor = [img.shape[0] // 2, img.shape[1] // 2] rotated_img = mmcv.imrotate(img_origin, rotation_angle) rotated_pointobbs = [ wwtool.rotate_pointobb(pointobb, rotation_angle * np.pi / 180, rotation_anchor) for pointobb in pointobbs ] rotated_thetaobbs = [ wwtool.pointobb2thetaobb(rotated_pointobb) for rotated_pointobb in rotated_pointobbs ] wwtool.imshow_rbboxes(rotated_img, rotated_thetaobbs, win_name='rotated')