In target detection in certain scenarios, the number of samples is small, resulting in relatively poor detected, then the data on the need for amplification. This article describes the common data class amplification mode 6, including cropping, pan, changing brightness, noise is added, and the rotation angle of the mirror.
Reference is also attached to each part presents the position code, we can refer.
Crop (need to change bbox): picture cropped need to include all the boxes, otherwise the original image annotation will cause damage.
_crop_img_bboxes DEF (Self, IMG, bboxes): '' ' post-crop images to include all block inputs: IMG: Image Array bboxes: boundingboxes all the images contained in a list, each element of [x_min, y_min, x_max, y_max] to ensure that the value is output: crop_img: cropped image array crop_bboxes: boundingbox coordinates after cutting, List '' ' # ------------------ cropped image - ----------------- W = img.shape [. 1] H = img.shape [0] x_min = W x_max = 0 y_min = H y_max = 0 for BBOX in bboxes: x_min = min (x_min, bbox [ 0]) y_min = min (y_min, BBOX [. 1]) x_max = max (x_max, BBOX [2]) y_max = max (x_max, BBOX [. 3]) name = BBOX [. 4] # contain all the target boxes minimum block to the respective side distance d_to_left = x_min d_to_right = W - x_max d_to_top = y_min d_to_bottom = H - y_max # random extend the minimum range crop_x_min = int (x_min - random.uniform (0, d_to_left)) crop_y_min = int (y_min - random.uniform (0 , d_to_top)) crop_x_max = int (x_max random.uniform + (0, d_to_right)) crop_y_max = int (y_max random.uniform + (0, d_to_bottom)) # ensure that no boundary crop_x_min = max (0, crop_x_min) crop_y_min = max (0, crop_y_min) crop_x_max = min (W, crop_x_max) crop_y_max = min(h, crop_y_max) crop_img = img[crop_y_min:crop_y_max, crop_x_min:crop_x_max] #------------------ 裁剪bounding boxes ------------------ crop_bboxes = list() for box in bboxes: crop_bboxes.append([bbox[0]-crop_x_min, bbox[1]-crop_y_min, bbox[2]-crop_x_max, bbox[3]-crop_y_max,name]) return crop_img, crop_bboxes
Translation (need to change bbox): picture after the translation needs to contain all the boxes, otherwise the original image annotation will cause damage.
_shift_pic_bboxes DEF (Self, IMG, bboxes): '' ' posterior translation needs to contain all of the block references: https: //blog.csdn.net/sty945/article/details/79387054 Input: IMG: Image Array bboxes: the image All boundingboxes contained a list, each element of [x_min, y_min, x_max, y_max ] to ensure that the value is output: shift_img: image array after translation shift_bboxes: coordinates of the translated boundingbox, List '' ' # - ---------------- translation image ------------------ W = img.shape [. 1] H = img.shape [ 0] x_min = W x_max = 0 y_min = H y_max = 0 for BBOX in bboxes: x_min = min (x_min, BBOX [0]) y_min = min (y_min, BBOX [. 1]) x_max = max (x_max, BBOX [2]) y_max = max (x_max, BBOX [. 3]) name = BBOX [. 4] # target box contains all of a minimum distance to each side frame, i.e. the maximum distance of movement in each direction d_to_left = x_min d_to_right = W - x_max d_to_top = y_min d_to_bottom = H - y_max # shown in the first row of the matrix is [1 , 0, x], where x represents the image distance to the left or right, if x is a positive value, then move to the right, if it is negative, then moves to the left. # In the second row of the matrix is represented by [0,1, y], where y represents the image distance moved up or down, if y is positive, then moved downwardly, if it is negative, then up mobile. random.uniform = X (- (d_to_left /. 3), d_to_right /. 3) Y = random.uniform (- (d_to_top /. 3), d_to_bottom /. 3) M = np.float32 ([[. 1, 0, X], [ 0, 1, y]]) # Affine transformation shift_img = cv2.warpAffine (img, M, (img.shape [1], img.shape [0])) # The first parameter that we want to perform image transformation, the second parameter is our translation matrix, a third wanted to show the size of the resulting image # translate boundingbox ---------------- ------------------ - shift_bboxes = List () for BBOX in bboxes: shift_bboxes.append ([BBOX [0] + X, BBOX [. 1] + Y, BBOX [2] + X, BBOX [. 3] + Y, name]) return shift_img , shift_bboxes
Brightness change: change the brightness is relatively simple, does not require processing bounding boxes
_changeLight DEF (Self, IMG): '' ' adjust_gamma (Image, Gamma = 1, GAIN = 1) Function: Gamma> 1, the output image becomes darker, less than 1, an output image becomes brighter input: IMG: image array output : IMG: the changed luminance image Array '' ' in Flag = random.uniform (0.5, for 1.5) ## in Flag> is a dim, is less than 1 lighten return exposure.adjust_gamma (img, flag)
Add Noise: Add noise is relatively simple, does not require processing bounding boxes
_addNoise DEF (Self, IMG): '' ' Input: IMG: Image array Output: IMG: image array after the addition of noise, since the output of the pixel is between [0,1], so obtained by 255 ' '' return random_noise (img, mode = ' gaussian', clip = True) * 255
Rotation: Picture rotated need to include all the boxes, otherwise it will damage the original image annotation. It should be noted that some corners of the rotation of the image may be cut off, we need to avoid this situation.
_rotate_img_bboxes DEF (Self, IMG, bboxes, angle =. 5, Scale =. 1.): '' ' Reference: HTTPS: //blog.csdn.net/saltriver/article/details/79680189 https://www.ctolib.com /topics-44419.html affine transformation: https: //www.zhihu.com/question/20666664 input: IMG: image Array, (H, W, C) bboxes: the image contains all boundingboxs, a list, each element of [x_min, y_min, x_max, y_max ], to ensure that the numerical angle: rotation angle scale: 1 default output: rot_img: image rotation Array rot_bboxes: BoundingBox coordinates after the rotation list '' ' # --- ------------------- rotated image ---------------------- W = img.shape [. 1 ] H = img.shape [0 ] # radian angle becomes = np.deg2rad rangle (angle) # calculate new image width and height, respectively, the highest and lowest points of the vertical distance nw = (abs (np.sin (rangle ) * h) + abs (np.cos (rangle) W *)) * Scale NH = (ABS (np.cos (rangle) * H) + ABS (np.sin (rangle) * W)) * Scale # acquiring an image of a point around the rotation matrix # getRotationMatrix2D (Point2f center , Double angle, Double scale) # Point2f Center: represents a rotation center point # double angle: angle of rotation represented by # double scale: image scaling factor # reference: HTTPS: //cloud.tencent.com/developer/article/1425373 rot_mat = cv2.getRotationMatrix2D ((nw * 0.5, nh * 0.5), angle, scale) # 2x3 matrix returns # center point between the new position and the old center point = np.dot rot_move (rot_mat, np.array ([(NW-W) * 0.5, (NH-H) * 0.5,0])) # The Move Affects. The only Translation, SO Update The Translation # The Transform Part of rot_mat [0,2] + = rot_move [0] rot_mat [1,2] + = rot_move [. 1] # affine transformation rot_img = cv2.warpAffine (img, rot_mat, (int (math.ceil (nw)), int (math.ceil (nh))), flags = cv2.INTER_LANCZOS4) # ceil ceil # ---- ---------------------- correction BoundingBox ------------------ # rot_mat final rotation matrix # obtain the original four bbox midpoint, and then converting these four points to the coordinate system of the rotated rot_bboxes List = () for BBOX in bboxes: x_min = BBOX [0] y_min = BBOX [. 1] BBOX = x_max [2] y_max = BBOX [. 3] name = BBOX [. 4] Point1 = np.dot (rot_mat, np.array ([(+ x_max x_min) / 2, y_min,. 1])) Point2 = np.dot (rot_mat, np.array ([x_max, (+ y_max y_min) / 2,. 1])) Point3 = np.dot (rot_mat, np.array ([(+ x_max x_min) / 2, y_max,. 1])) Point4 np.dot = (rot_mat, np.array ([x_min, (+ y_max y_min) / 2,. 1])) # combined np.array the concat = np.vstack ((Point1, Point2, Point3, Point4)) in vertical # stacking a linear direction # changing array type the concat = concat.astype (np.int32) # coordinate obtained after the rotation RX, Ry, RW, RH = cv2.boundingRect (the concat) rx_min = RX ry_min = Ry rx_max = RX + RW ry_max = ry + rh #加入strip中 rot_bboxes.append ([rx_min, ry_min, rx_max, ry_max, name]) return rot_img, rot_bboxes
Mirror: Image rotated need to include all the boxes, otherwise the original image annotation will cause damage. Here only two kinds of image: horizontal and vertical flip Flip
Mirror # DEF _flip_pic_bboxes (Self, IMG, bboxes): '' ' Reference: https: //blog.csdn.net/jningwei/article/details/78753607 image after the image frame to include all inputs: IMG: Image Array bboxes : All of the images contains boundingboxs, a list, each element of [x_min, y_min, x_max, y_max ], to ensure that the value is output: flip_img: the mirror image Array flip_bboxes: the bounding Box of the mirrored coordinate List '' ' # mirror image ---------------------- ---------------------- Import Copy = copy.deepcopy flip_img (IMG) IF random.random () <0.5: Horizon = True the else: Horizon = False H, W, _ = img.shape if horizon: # 水平翻转 flip_img = cv2.flip(flip_img, -1) else: flip_img = cv2.flip(flip_img, 0) # ---------------------- 矫正boundingbox ---------------------- flip_bboxes = list() for bbox in bboxes: x_min = bbox[0] y_min = bbox[1] x_max = bbox[2] y_max = bbox[3] name = bbox[4] if horizon: flip_bboxes.append([w-x_max, y_min, w-x_min, y_max, name]) else: flip_bboxes.append([x_min, h-y_max, x_max, h-y_min, name]) return flip_img, flip_bboxes