|
|
@@ -187,6 +187,36 @@ def angle_loss_cosine(pred_dir, gt_dir):
|
|
|
cos_sim = torch.sum(pred_dir * gt_dir, dim=-1).clamp(-1.0, 1.0)
|
|
|
return 1.0 - cos_sim # 或者 torch.acos(cos_sim) / pi 也可
|
|
|
|
|
|
+
|
|
|
+def single_point_to_heatmap(keypoints, rois, heatmap_size):
|
|
|
+ # type: (Tensor, Tensor, int) -> Tensor
|
|
|
+ print(f'rois:{rois.shape}')
|
|
|
+ print(f'heatmap_size:{heatmap_size}')
|
|
|
+
|
|
|
+
|
|
|
+ print(f'keypoints.shape:{keypoints.shape}')
|
|
|
+ # batch_size, num_keypoints, _ = keypoints.shape
|
|
|
+
|
|
|
+ x = keypoints[..., 0]
|
|
|
+ y = keypoints[..., 1]
|
|
|
+
|
|
|
+ gs = generate_gaussian_heatmaps(x, y,num_points=1, heatmap_size=heatmap_size, sigma=1.0)
|
|
|
+ # show_heatmap(gs[0],'target')
|
|
|
+ all_roi_heatmap = []
|
|
|
+ for roi, heatmap in zip(rois, gs):
|
|
|
+ # print(f'heatmap:{heatmap.shape}')
|
|
|
+ heatmap = heatmap.unsqueeze(0)
|
|
|
+ x1, y1, x2, y2 = map(int, roi)
|
|
|
+ roi_heatmap = torch.zeros_like(heatmap)
|
|
|
+ roi_heatmap[..., y1:y2 + 1, x1:x2 + 1] = heatmap[..., y1:y2 + 1, x1:x2 + 1]
|
|
|
+ # show_heatmap(roi_heatmap,'roi_heatmap')
|
|
|
+ all_roi_heatmap.append(roi_heatmap)
|
|
|
+
|
|
|
+ all_roi_heatmap = torch.cat(all_roi_heatmap)
|
|
|
+ print(f'all_roi_heatmap:{all_roi_heatmap.shape}')
|
|
|
+
|
|
|
+ return all_roi_heatmap
|
|
|
+
|
|
|
def line_points_to_heatmap(keypoints, rois, heatmap_size):
|
|
|
# type: (Tensor, Tensor, int) -> Tensor
|
|
|
print(f'rois:{rois.shape}')
|
|
|
@@ -278,7 +308,7 @@ def line_points_to_heatmap_(keypoints, rois, heatmap_size):
|
|
|
return gs_heatmap
|
|
|
|
|
|
|
|
|
-def generate_gaussian_heatmaps(xs, ys, heatmap_size, sigma=2.0, device='cuda'):
|
|
|
+def generate_gaussian_heatmaps(xs, ys, heatmap_size,num_points=2, sigma=2.0, device='cuda'):
|
|
|
"""
|
|
|
为一组点生成并合并高斯热图。
|
|
|
|
|
|
@@ -294,6 +324,7 @@ def generate_gaussian_heatmaps(xs, ys, heatmap_size, sigma=2.0, device='cuda'):
|
|
|
"""
|
|
|
|
|
|
assert xs.shape == ys.shape, "x and y must have the same shape"
|
|
|
+ print(f'xs:{xs.shape}')
|
|
|
N = xs.shape[0]
|
|
|
print(f'N:{N}')
|
|
|
|
|
|
@@ -307,26 +338,32 @@ def generate_gaussian_heatmaps(xs, ys, heatmap_size, sigma=2.0, device='cuda'):
|
|
|
# print(f'heatmap_size:{heatmap_size}')
|
|
|
# 初始化输出热图
|
|
|
combined_heatmap = torch.zeros((N, heatmap_size, heatmap_size), device=device)
|
|
|
- for i in range(N):
|
|
|
- mu_x1 = xs[i, 0].clamp(0, heatmap_size - 1).item()
|
|
|
- mu_y1 = ys[i, 0].clamp(0, heatmap_size - 1).item()
|
|
|
|
|
|
- # 计算距离平方
|
|
|
- dist1 = (grid_x - mu_x1) ** 2 + (grid_y - mu_y1) ** 2
|
|
|
+ for i in range(N):
|
|
|
+ heatmap= torch.zeros((heatmap_size, heatmap_size), device=device)
|
|
|
+ for j in range(num_points):
|
|
|
+ mu_x1 = xs[i, j].clamp(0, heatmap_size - 1).item()
|
|
|
+ mu_y1 = ys[i, j].clamp(0, heatmap_size - 1).item()
|
|
|
|
|
|
- # 计算高斯分布
|
|
|
- heatmap1 = torch.exp(-dist1 / (2 * sigma ** 2))
|
|
|
+ # 计算距离平方
|
|
|
+ dist1 = (grid_x - mu_x1) ** 2 + (grid_y - mu_y1) ** 2
|
|
|
|
|
|
- mu_x2 = xs[i, 1].clamp(0, heatmap_size - 1).item()
|
|
|
- mu_y2 = ys[i, 1].clamp(0, heatmap_size - 1).item()
|
|
|
+ # 计算高斯分布
|
|
|
+ heatmap1 = torch.exp(-dist1 / (2 * sigma ** 2))
|
|
|
|
|
|
- # 计算距离平方
|
|
|
- dist2 = (grid_x - mu_x2) ** 2 + (grid_y - mu_y2) ** 2
|
|
|
+ heatmap+=heatmap1
|
|
|
|
|
|
- # 计算高斯分布
|
|
|
- heatmap2 = torch.exp(-dist2 / (2 * sigma ** 2))
|
|
|
|
|
|
- heatmap = heatmap1 + heatmap2
|
|
|
+ # mu_x2 = xs[i, 1].clamp(0, heatmap_size - 1).item()
|
|
|
+ # mu_y2 = ys[i, 1].clamp(0, heatmap_size - 1).item()
|
|
|
+ #
|
|
|
+ # # 计算距离平方
|
|
|
+ # dist2 = (grid_x - mu_x2) ** 2 + (grid_y - mu_y2) ** 2
|
|
|
+ #
|
|
|
+ # # 计算高斯分布
|
|
|
+ # heatmap2 = torch.exp(-dist2 / (2 * sigma ** 2))
|
|
|
+ #
|
|
|
+ # heatmap = heatmap1 + heatmap2
|
|
|
|
|
|
# 将当前热图累加到结果中
|
|
|
combined_heatmap[i] = heatmap
|
|
|
@@ -575,21 +612,22 @@ def heatmaps_to_lines(maps, rois):
|
|
|
|
|
|
|
|
|
def lines_features_align(features, proposals, img_size):
|
|
|
- print(f'lines_features_align features:{features.shape}')
|
|
|
+ print(f'lines_features_align features:{features.shape},proposals:{len(proposals)}')
|
|
|
|
|
|
align_feat_list = []
|
|
|
for feat, proposals_per_img in zip(features, proposals):
|
|
|
- # print(f'lines_features_align feat:{feat.shape}, proposals_per_img:{proposals_per_img.shape}')
|
|
|
-
|
|
|
- feat = feat.unsqueeze(0)
|
|
|
- for proposal in proposals_per_img:
|
|
|
- align_feat = torch.zeros_like(feat)
|
|
|
- # print(f'align_feat:{align_feat.shape}')
|
|
|
- x1, y1, x2, y2 = map(lambda v: int(v.item()), proposal)
|
|
|
- # 将每个proposal框内的部分赋值到align_feats对应位置
|
|
|
- align_feat[:, :, y1:y2 + 1, x1:x2 + 1] = feat[:, :, y1:y2 + 1, x1:x2 + 1]
|
|
|
- align_feat_list.append(align_feat)
|
|
|
-
|
|
|
+ print(f'lines_features_align feat:{feat.shape}, proposals_per_img:{proposals_per_img.shape}')
|
|
|
+ if proposals_per_img.shape[0]>0:
|
|
|
+ feat = feat.unsqueeze(0)
|
|
|
+ for proposal in proposals_per_img:
|
|
|
+ align_feat = torch.zeros_like(feat)
|
|
|
+ # print(f'align_feat:{align_feat.shape}')
|
|
|
+ x1, y1, x2, y2 = map(lambda v: int(v.item()), proposal)
|
|
|
+ # 将每个proposal框内的部分赋值到align_feats对应位置
|
|
|
+ align_feat[:, :, y1:y2 + 1, x1:x2 + 1] = feat[:, :, y1:y2 + 1, x1:x2 + 1]
|
|
|
+ align_feat_list.append(align_feat)
|
|
|
+
|
|
|
+ print(f'align_feat_list:{align_feat_list}')
|
|
|
feats_tensor = torch.cat(align_feat_list)
|
|
|
|
|
|
print(f'align features :{feats_tensor.shape}')
|
|
|
@@ -611,7 +649,8 @@ def lines_point_pair_loss(line_logits, proposals, gt_lines, line_matched_idxs):
|
|
|
gs_heatmaps = []
|
|
|
valid = []
|
|
|
for proposals_per_image, gt_kp_in_image, midx in zip(proposals, gt_lines, line_matched_idxs):
|
|
|
- print(f'proposals_per_image:{proposals_per_image.shape}')
|
|
|
+ print(f'line_proposals_per_image:{proposals_per_image.shape}')
|
|
|
+ print(f'gt_lines:{gt_lines}')
|
|
|
kp = gt_kp_in_image[midx]
|
|
|
gs_heatmaps_per_img = line_points_to_heatmap(kp, proposals_per_image, discretization_size)
|
|
|
gs_heatmaps.append(gs_heatmaps_per_img)
|
|
|
@@ -646,6 +685,37 @@ def lines_point_pair_loss(line_logits, proposals, gt_lines, line_matched_idxs):
|
|
|
return line_loss
|
|
|
|
|
|
|
|
|
+def compute_point_loss(line_logits, proposals, gt_points, point_matched_idxs):
|
|
|
+ # type: (Tensor, List[Tensor], List[Tensor], List[Tensor]) -> Tensor
|
|
|
+ N, K, H, W = line_logits.shape
|
|
|
+ len_proposals = len(proposals)
|
|
|
+
|
|
|
+ print(f'starte to compute_point_loss')
|
|
|
+ print(f'compute_point_loss line_logits.shape:{line_logits.shape},len_proposals:{len_proposals}')
|
|
|
+ if H != W:
|
|
|
+ raise ValueError(
|
|
|
+ f"line_logits height and width (last two elements of shape) should be equal. Instead got H = {H} and W = {W}"
|
|
|
+ )
|
|
|
+ discretization_size = H
|
|
|
+
|
|
|
+ gs_heatmaps = []
|
|
|
+ print(f'point_matched_idxs:{point_matched_idxs}')
|
|
|
+ for proposals_per_image, gt_kp_in_image, midx in zip(proposals, gt_points, point_matched_idxs):
|
|
|
+ print(f'proposals_per_image:{proposals_per_image.shape}')
|
|
|
+ kp = gt_kp_in_image[midx]
|
|
|
+ # print(f'gt_kp_in_image:{gt_kp_in_image}')
|
|
|
+ gs_heatmaps_per_img = single_point_to_heatmap(kp, proposals_per_image, discretization_size)
|
|
|
+ gs_heatmaps.append(gs_heatmaps_per_img)
|
|
|
+
|
|
|
+ gs_heatmaps = torch.cat(gs_heatmaps, dim=0)
|
|
|
+ print(f'gs_heatmaps:{gs_heatmaps.shape}, line_logits.shape:{line_logits.squeeze(1).shape}')
|
|
|
+
|
|
|
+ line_logits = line_logits.squeeze(1)
|
|
|
+
|
|
|
+ line_loss = F.cross_entropy(line_logits, gs_heatmaps)
|
|
|
+
|
|
|
+ return line_loss
|
|
|
+
|
|
|
def lines_to_boxes(lines, img_size=511):
|
|
|
"""
|
|
|
输入:
|
|
|
@@ -1244,6 +1314,7 @@ class RoIHeads(nn.Module):
|
|
|
image_shapes (List[Tuple[H, W]])
|
|
|
targets (List[Dict])
|
|
|
"""
|
|
|
+
|
|
|
print(f'roihead forward!!!')
|
|
|
if targets is not None:
|
|
|
for t in targets:
|
|
|
@@ -1301,6 +1372,7 @@ class RoIHeads(nn.Module):
|
|
|
|
|
|
if self.has_line():
|
|
|
print(f'roi_heads forward has_line()!!!!')
|
|
|
+ print(f'labels:{labels}')
|
|
|
line_proposals = [p["boxes"] for p in result]
|
|
|
print(f'boxes_proposals:{len(line_proposals)}')
|
|
|
|
|
|
@@ -1313,28 +1385,57 @@ class RoIHeads(nn.Module):
|
|
|
num_images = len(proposals)
|
|
|
print(f'num_images:{num_images}')
|
|
|
line_proposals = []
|
|
|
+ point_proposals = []
|
|
|
+ arc_proposals = []
|
|
|
+
|
|
|
pos_matched_idxs = []
|
|
|
+ line_pos_matched_idxs = []
|
|
|
+ point_pos_matched_idxs = []
|
|
|
if matched_idxs is None:
|
|
|
raise ValueError("if in trainning, matched_idxs should not be None")
|
|
|
|
|
|
for img_id in range(num_images):
|
|
|
pos = torch.where(labels[img_id] > 0)[0]
|
|
|
- line_proposals.append(proposals[img_id][pos])
|
|
|
- pos_matched_idxs.append(matched_idxs[img_id][pos])
|
|
|
+
|
|
|
+ line_pos=torch.where(labels[img_id] ==2)[0]
|
|
|
+ point_pos=torch.where(labels[img_id] ==1)[0]
|
|
|
+
|
|
|
+ line_proposals.append(proposals[img_id][line_pos])
|
|
|
+ point_proposals.append(proposals[img_id][point_pos])
|
|
|
+
|
|
|
+ line_pos_matched_idxs.append(matched_idxs[img_id][line_pos])
|
|
|
+ point_pos_matched_idxs.append(matched_idxs[img_id][point_pos])
|
|
|
+
|
|
|
+ # pos_matched_idxs.append(matched_idxs[img_id][pos])
|
|
|
else:
|
|
|
if targets is not None:
|
|
|
|
|
|
pos_matched_idxs = []
|
|
|
num_images = len(proposals)
|
|
|
line_proposals = []
|
|
|
+ point_proposals=[]
|
|
|
+ arc_proposals=[]
|
|
|
+
|
|
|
+ line_pos_matched_idxs = []
|
|
|
+ point_pos_matched_idxs = []
|
|
|
print(f'val num_images:{num_images}')
|
|
|
if matched_idxs is None:
|
|
|
raise ValueError("if in trainning, matched_idxs should not be None")
|
|
|
|
|
|
for img_id in range(num_images):
|
|
|
pos = torch.where(labels[img_id] > 0)[0]
|
|
|
- line_proposals.append(proposals[img_id][pos])
|
|
|
- pos_matched_idxs.append(matched_idxs[img_id][pos])
|
|
|
+ # line_proposals.append(proposals[img_id][pos])
|
|
|
+ # pos_matched_idxs.append(matched_idxs[img_id][pos])
|
|
|
+
|
|
|
+ line_pos = torch.where(labels[img_id].item() == 2)[0]
|
|
|
+ point_pos = torch.where(labels[img_id].item() == 1)[0]
|
|
|
+
|
|
|
+ line_proposals.append(proposals[img_id][line_pos])
|
|
|
+ point_proposals.append(proposals[img_id][point_pos])
|
|
|
+
|
|
|
+ line_pos_matched_idxs.append(matched_idxs[img_id][line_pos])
|
|
|
+ point_pos_matched_idxs.append(matched_idxs[img_id][point_pos])
|
|
|
+
|
|
|
else:
|
|
|
pos_matched_idxs = None
|
|
|
|
|
|
@@ -1347,7 +1448,14 @@ class RoIHeads(nn.Module):
|
|
|
line_features = self.channel_compress(features['0'])
|
|
|
#(b.8,512,512)
|
|
|
|
|
|
- line_features = lines_features_align(line_features, line_proposals, image_shapes)
|
|
|
+
|
|
|
+ all_proposals=line_proposals+point_proposals
|
|
|
+ # print(f'all_proposals:{all_proposals}')
|
|
|
+ filtered_proposals = [proposal for proposal in all_proposals if proposal.shape[0] > 0]
|
|
|
+
|
|
|
+
|
|
|
+ line_features = lines_features_align(line_features, filtered_proposals, image_shapes)
|
|
|
+ print(f'line_features from features_align:{line_features.shape}')
|
|
|
|
|
|
line_features = self.line_head(line_features)
|
|
|
#(N,1,512,512)
|
|
|
@@ -1359,36 +1467,59 @@ class RoIHeads(nn.Module):
|
|
|
|
|
|
loss_line = {}
|
|
|
loss_line_iou = {}
|
|
|
-
|
|
|
+ model_loss_point = {}
|
|
|
if self.training:
|
|
|
|
|
|
if targets is None or pos_matched_idxs is None:
|
|
|
raise ValueError("both targets and pos_matched_idxs should not be None when in training mode")
|
|
|
|
|
|
gt_lines = [t["lines"] for t in targets]
|
|
|
+ gt_points = [t["points"] for t in targets]
|
|
|
print(f'gt_lines:{gt_lines[0].shape}')
|
|
|
h, w = targets[0]["img_size"]
|
|
|
img_size = h
|
|
|
- rcnn_loss_line = lines_point_pair_loss(
|
|
|
- line_logits, line_proposals, gt_lines, pos_matched_idxs
|
|
|
- )
|
|
|
- iou_loss = line_iou_loss(line_logits, line_proposals, gt_lines, pos_matched_idxs, img_size)
|
|
|
+ # rcnn_loss_line = lines_point_pair_loss(
|
|
|
+ # line_logits, line_proposals, gt_lines, pos_matched_idxs
|
|
|
+ # )
|
|
|
+ # iou_loss = line_iou_loss(line_logits, line_proposals, gt_lines, pos_matched_idxs, img_size)
|
|
|
+ gt_lines_tensor=torch.cat(gt_lines)
|
|
|
+ gt_points_tensor = torch.cat(gt_points)
|
|
|
+ print(f'gt_lines_tensor:{gt_lines_tensor.shape}')
|
|
|
+ print(f'gt_points_tensor:{gt_points_tensor.shape}')
|
|
|
+ if gt_lines_tensor.shape[0]>0:
|
|
|
+ rcnn_loss_line = lines_point_pair_loss(
|
|
|
+ line_logits, line_proposals, gt_lines, line_pos_matched_idxs
|
|
|
+ )
|
|
|
+ iou_loss = line_iou_loss(line_logits, line_proposals, gt_lines, line_pos_matched_idxs, img_size)
|
|
|
+
|
|
|
+ if gt_points_tensor.shape[0]>0:
|
|
|
+ model_loss_point = compute_point_loss(
|
|
|
+ line_logits, point_proposals, gt_points, point_pos_matched_idxs
|
|
|
+ )
|
|
|
|
|
|
loss_line = {"loss_line": rcnn_loss_line}
|
|
|
loss_line_iou = {'loss_line_iou': iou_loss}
|
|
|
+ loss_point = {"loss_point": model_loss_point}
|
|
|
|
|
|
else:
|
|
|
if targets is not None:
|
|
|
h, w = targets[0]["img_size"]
|
|
|
img_size = h
|
|
|
gt_lines = [t["lines"] for t in targets]
|
|
|
- rcnn_loss_lines = lines_point_pair_loss(
|
|
|
- line_logits, line_proposals, gt_lines, pos_matched_idxs
|
|
|
+ gt_points = [t["points"] for t in targets]
|
|
|
+
|
|
|
+ rcnn_loss_line = lines_point_pair_loss(
|
|
|
+ line_logits, line_proposals, gt_lines, line_pos_matched_idxs
|
|
|
+ )
|
|
|
+ iou_loss = line_iou_loss(line_logits, line_proposals, gt_lines, line_pos_matched_idxs, img_size)
|
|
|
+
|
|
|
+ model_loss_point = compute_point_loss(
|
|
|
+ line_logits, point_proposals, gt_points, point_pos_matched_idxs
|
|
|
)
|
|
|
- loss_line = {"loss_line": rcnn_loss_lines}
|
|
|
|
|
|
- iou_loss = line_iou_loss(line_logits, line_proposals, gt_lines, pos_matched_idxs, img_size)
|
|
|
+ loss_line = {"loss_line": rcnn_loss_line}
|
|
|
loss_line_iou = {'loss_line_iou': iou_loss}
|
|
|
+ loss_point={"loss_point":model_loss_point}
|
|
|
|
|
|
|
|
|
else:
|
|
|
@@ -1405,6 +1536,7 @@ class RoIHeads(nn.Module):
|
|
|
|
|
|
losses.update(loss_line)
|
|
|
losses.update(loss_line_iou)
|
|
|
+ losses.update(loss_point)
|
|
|
|
|
|
if self.has_mask():
|
|
|
mask_proposals = [p["boxes"] for p in result]
|