原文
一,用途
主要用于证明方法的有效性、增加工作量、增加论文字数。,用于比较验证。
可视化两个图,使用了新方法的和使用之前的,相互比较,根据图标内容写论文,说明新方法体现的作用。
二,步骤
1,加载数据并预处理
加载数据:通过classdataset,生成数据加载迭代器。(这里仅加载一张图片,跳过此操作)
数据(图片)预处理:调整大小 —— 转化为Tensor格式 —— 归一化 —— 数据增强 —— 图片数据处理等(这里取前三个)
def image_proprecess(img_path):
img = Image.open(img_path)
data_transforms = transforms.Compose([
transforms.Resize((384, 384), interpolation=3),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])
data = data_transforms(img)
data = torch.unsqueeze(data,0)
return data
加载一张图时,使用 torch.unsqueeze 将三维张量变成四维。
2,修改网络
当需要可视化某一层的特征图时,需要将该层的特征图返回出来,所以修改网络中的 forward 函数:
def forward(self, x):
x = self.model.conv1(x)
x = self.model.bn1(x)
x = self.model.relu(x)
x = self.model.maxpool(x)
feature = self.model.layer1(x)
x = self.model.layer2(feature)
x = self.model.layer3(x)
x = self.model.layer4(x)
return feature,x
3, 定义网络并加载预训练模型
def Init_Setting(epoch):
dirname = '/mnt/share/VideoReID/share/models/Methods5_trial1'
model = siamese_resnet50(701, stride=1, pool='avg')
trained_path = os.path.join(dirname, 'net_%03d.pth' % epoch)
print("load %03d.pth" % epoch)
model.load_state_dict(torch.load(trained_path))
model = model.cuda().eval()
return model
注:最后一行,为将网络设置为推理模式
4,可视化特征图
将特征图的某一通道转化为一张图来进行可视化:
def visualize_feature_map(img_batch,out_path,type,BI):
feature_map = torch.squeeze(img_batch)
feature_map = feature_map.detach().cpu().numpy()
feature_map_sum = feature_map[0, :, :]
feature_map_sum = np.expand_dims(feature_map_sum, axis=2)
for i in range(0, 2048):
feature_map_split = feature_map[i,:, :]
feature_map_split = np.expand_dims(feature_map_split,axis=2)
if i > 0:
feature_map_sum +=feature_map_split
feature_map_split = BI.transform(feature_map_split)
plt.imshow(feature_map_split)
plt.savefig(out_path + str(i) + "_{}.jpg".format(type) )
plt.xticks()
plt.yticks()
plt.axis('off')
feature_map_sum = BI.transform(feature_map_sum)
plt.imshow(feature_map_sum)
plt.savefig(out_path + "sum_{}.jpg".format(type))
print("save sum_{}.jpg".format(type))
- 参数img_batch是从网络中的某一层传回来的特征图,BI是双线性插值的函数,自定义的,下面会讲。
- 由于只可视化了一张图片,因此img_batch是四维的,且batchsize维为1。第三行将它从GPU上弄到CPU上,并变成numpy格式。
- 剩下部分主要完成将每个通道变成一张图,以及将所有通道每个元素对应位置相加,并保存。
双线性插值
在经过多次网络下采样后,后面层的特征图一般变得只有7×7,16×16大小。可视化后特别小,因此需要对其进行上采样。双线性插值就是上采样方法之一,
class BilinearInterpolation(object):
def __init__(self, w_rate: float, h_rate: float, *, align='center'):
if align not in ['center', 'left']:
logging.exception(f'{align} is not a valid align parameter')
align = 'center'
self.align = align
self.w_rate = w_rate
self.h_rate = h_rate
def set_rate(self,w_rate: float, h_rate: float):
self.w_rate = w_rate # w 的缩放率
self.h_rate = h_rate # h 的缩放率
# 由变换后的像素坐标得到原图像的坐标 针对高
def get_src_h(self, dst_i,source_h,goal_h) -> float:
if self.align == 'left':
# 左上角对齐
src_i = float(dst_i * (source_h/goal_h))
elif self.align == 'center':
# 将两个图像的几何中心重合。
src_i = float((dst_i + 0.5) * (source_h/goal_h) - 0.5)
src_i += 0.001
src_i = max(0.0, src_i)
src_i = min(float(source_h - 1), src_i)
return src_i
# 由变换后的像素坐标得到原图像的坐标 针对宽
def get_src_w(self, dst_j,source_w,goal_w) -> float:
if self.align == 'left':
# 左上角对齐
src_j = float(dst_j * (source_w/goal_w))
elif self.align == 'center':
# 将两个图像的几何中心重合。
src_j = float((dst_j + 0.5) * (source_w/goal_w) - 0.5)
src_j += 0.001
src_j = max(0.0, src_j)
src_j = min((source_w - 1), src_j)
return src_j
def transform(self, img):
source_h, source_w, source_c = img.shape # (235, 234, 3)
goal_h, goal_w = round(
source_h * self.h_rate), round(source_w * self.w_rate)
new_img = np.zeros((goal_h, goal_w, source_c), dtype=np.uint8)
for i in range(new_img.shape[0]): # h
src_i = self.get_src_h(i,source_h,goal_h)
for j in range(new_img.shape[1]):
src_j = self.get_src_w(j,source_w,goal_w)
i2 = ceil(src_i)
i1 = int(src_i)
j2 = ceil(src_j)
j1 = int(src_j)
x2_x = j2 - src_j
x_x1 = src_j - j1
y2_y = i2 - src_i
y_y1 = src_i - i1
new_img[i, j] = img[i1, j1]*x2_x*y2_y + img[i1, j2] * \
x_x1*y2_y + img[i2, j1]*x2_x*y_y1 + img[i2, j2]*x_x1*y_y1
return new_img
#使用方法
BI = BilinearInterpolation(8, 8)
feature_map = BI.transform(feature_map)
5,主函数流程
imgs_path = "/path/to/imgs/"
save_path = "/save/path/to/output/"
model = Init_Setting(120)
BI = BilinearInterpolation(8, 8)
data = image_proprecess(out_path + "0836.jpg")
data = data.cuda()
output, _ = model(data)
visualize_feature_map(output, save_path, "drone", BI)
仅作学习记录分享,侵联删。