Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/utils/rboxs_utils.py
Views: 475
"""1Oriented Bounding Boxes utils2"""3import numpy as np4pi = 3.1415925import cv26import torch78def gaussian_label_cpu(label, num_class, u=0, sig=4.0):9"""10转换成CSL Labels:11用高斯窗口函数根据角度θ的周期性赋予gt labels同样的周期性,使得损失函数在计算边界处时可以做到“差值很大但loss很小”;12并且使得其labels具有环形特征,能够反映各个θ之间的角度距离13Args:14label (float32):[1], theta class15num_theta_class (int): [1], theta class num16u (float32):[1], μ in gaussian function17sig (float32):[1], σ in gaussian function, which is window radius for Circular Smooth Label18Returns:19csl_label (array): [num_theta_class], gaussian function smooth label20"""21x = np.arange(-num_class/2, num_class/2)22y_sig = np.exp(-(x - u) ** 2 / (2 * sig ** 2))23index = int(num_class/2 - label)24return np.concatenate([y_sig[index:],25y_sig[:index]], axis=0)2627def regular_theta(theta, mode='180', start=-pi/2):28"""29limit theta ∈ [-pi/2, pi/2)30"""31assert mode in ['360', '180']32cycle = 2 * pi if mode == '360' else pi3334theta = theta - start35theta = theta % cycle36return theta + start3738def poly2rbox(polys, num_cls_thata=180, radius=6.0, use_pi=False, use_gaussian=False):39"""40Trans poly format to rbox format.41Args:42polys (array): (num_gts, [x1 y1 x2 y2 x3 y3 x4 y4])43num_cls_thata (int): [1], theta class num44radius (float32): [1], window radius for Circular Smooth Label45use_pi (bool): True θ∈[-pi/2, pi/2) , False θ∈[0, 180)4647Returns:48use_gaussian True:49rboxes (array):50csl_labels (array): (num_gts, num_cls_thata)51elif52rboxes (array): (num_gts, [cx cy l s θ])53"""54assert polys.shape[-1] == 855if use_gaussian:56csl_labels = []57rboxes = []58for poly in polys:59poly = np.float32(poly.reshape(4, 2))60(x, y), (w, h), angle = cv2.minAreaRect(poly) # θ ∈ [0, 90]61angle = -angle # θ ∈ [-90, 0]62theta = angle / 180 * pi # 转为pi制6364# trans opencv format to longedge format θ ∈ [-pi/2, pi/2]65if w != max(w, h):66w, h = h, w67theta += pi/268theta = regular_theta(theta) # limit theta ∈ [-pi/2, pi/2)69angle = (theta * 180 / pi) + 90 # θ ∈ [0, 180)7071if not use_pi: # 采用angle弧度制 θ ∈ [0, 180)72rboxes.append([x, y, w, h, angle])73else: # 采用pi制74rboxes.append([x, y, w, h, theta])75if use_gaussian:76csl_label = gaussian_label_cpu(label=angle, num_class=num_cls_thata, u=0, sig=radius)77csl_labels.append(csl_label)78if use_gaussian:79return np.array(rboxes), np.array(csl_labels)80return np.array(rboxes)8182# def rbox2poly(rboxes):83# """84# Trans rbox format to poly format.85# Args:86# rboxes (array): (num_gts, [cx cy l s θ]) θ∈(0, 180]8788# Returns:89# polys (array): (num_gts, [x1 y1 x2 y2 x3 y3 x4 y4])90# """91# assert rboxes.shape[-1] == 592# polys = []93# for rbox in rboxes:94# x, y, w, h, theta = rbox95# if theta > 90 and theta <= 180: # longedge format -> opencv format96# w, h = h, w97# theta -= 9098# if theta <= 0 or theta > 90:99# print("cv2.minAreaRect occurs some error. θ isn't in range(0, 90]. The longedge format is: ", rbox)100101# poly = cv2.boxPoints(((x, y), (w, h), theta)).reshape(-1)102# polys.append(poly)103# return np.array(polys)104105def rbox2poly(obboxes):106"""107Trans rbox format to poly format.108Args:109rboxes (array/tensor): (num_gts, [cx cy l s θ]) θ∈[-pi/2, pi/2)110111Returns:112polys (array/tensor): (num_gts, [x1 y1 x2 y2 x3 y3 x4 y4])113"""114if isinstance(obboxes, torch.Tensor):115center, w, h, theta = obboxes[:, :2], obboxes[:, 2:3], obboxes[:, 3:4], obboxes[:, 4:5]116Cos, Sin = torch.cos(theta), torch.sin(theta)117118vector1 = torch.cat(119(w/2 * Cos, -w/2 * Sin), dim=-1)120vector2 = torch.cat(121(-h/2 * Sin, -h/2 * Cos), dim=-1)122point1 = center + vector1 + vector2123point2 = center + vector1 - vector2124point3 = center - vector1 - vector2125point4 = center - vector1 + vector2126order = obboxes.shape[:-1]127return torch.cat(128(point1, point2, point3, point4), dim=-1).reshape(*order, 8)129else:130center, w, h, theta = np.split(obboxes, (2, 3, 4), axis=-1)131Cos, Sin = np.cos(theta), np.sin(theta)132133vector1 = np.concatenate(134[w/2 * Cos, -w/2 * Sin], axis=-1)135vector2 = np.concatenate(136[-h/2 * Sin, -h/2 * Cos], axis=-1)137138point1 = center + vector1 + vector2139point2 = center + vector1 - vector2140point3 = center - vector1 - vector2141point4 = center - vector1 + vector2142order = obboxes.shape[:-1]143return np.concatenate(144[point1, point2, point3, point4], axis=-1).reshape(*order, 8)145146def poly2hbb(polys):147"""148Trans poly format to hbb format149Args:150rboxes (array/tensor): (num_gts, poly)151152Returns:153hbboxes (array/tensor): (num_gts, [xc yc w h])154"""155assert polys.shape[-1] == 8156if isinstance(polys, torch.Tensor):157x = polys[:, 0::2] # (num, 4)158y = polys[:, 1::2]159x_max = torch.amax(x, dim=1) # (num)160x_min = torch.amin(x, dim=1)161y_max = torch.amax(y, dim=1)162y_min = torch.amin(y, dim=1)163x_ctr, y_ctr = (x_max + x_min) / 2.0, (y_max + y_min) / 2.0 # (num)164h = y_max - y_min # (num)165w = x_max - x_min166x_ctr, y_ctr, w, h = x_ctr.reshape(-1, 1), y_ctr.reshape(-1, 1), w.reshape(-1, 1), h.reshape(-1, 1) # (num, 1)167hbboxes = torch.cat((x_ctr, y_ctr, w, h), dim=1)168else:169x = polys[:, 0::2] # (num, 4)170y = polys[:, 1::2]171x_max = np.amax(x, axis=1) # (num)172x_min = np.amin(x, axis=1)173y_max = np.amax(y, axis=1)174y_min = np.amin(y, axis=1)175x_ctr, y_ctr = (x_max + x_min) / 2.0, (y_max + y_min) / 2.0 # (num)176h = y_max - y_min # (num)177w = x_max - x_min178x_ctr, y_ctr, w, h = x_ctr.reshape(-1, 1), y_ctr.reshape(-1, 1), w.reshape(-1, 1), h.reshape(-1, 1) # (num, 1)179hbboxes = np.concatenate((x_ctr, y_ctr, w, h), axis=1)180return hbboxes181182def poly_filter(polys, h, w):183"""184Filter the poly labels which is out of the image.185Args:186polys (array): (num, 8)187188Return:189keep_masks (array): (num)190"""191x = polys[:, 0::2] # (num, 4)192y = polys[:, 1::2]193x_max = np.amax(x, axis=1) # (num)194x_min = np.amin(x, axis=1)195y_max = np.amax(y, axis=1)196y_min = np.amin(y, axis=1)197x_ctr, y_ctr = (x_max + x_min) / 2.0, (y_max + y_min) / 2.0 # (num)198keep_masks = (x_ctr > 0) & (x_ctr < w) & (y_ctr > 0) & (y_ctr < h)199return keep_masks200201