【单幅图像深度处理】代码有关问题解读

本文内容多是个人理解,如有问题望多多指正


一、误差:

误差分析

在论文中,使用了三个标准误差测量法来估计单目深度预测的准确性,这三个标准误差测量法是目前最先进的方法[21,22,14,6]中常用的。这些误差是为每个像素定义的,并对图像中的所有像素和数据集中的所有图像进行平均。


三个标准误差测量法如下:
标准误差测量法

对训练数据量的鲁棒性: 为了评估对训练量的敏感性,文中通过逐步减少训练数据来模拟该方法在两个数据集上的行为。并没有使用完整的训练集,而是随机抽取一小部分训练数据进行训练。下图中的曲线表明,当训练数据量逐渐减少时,误差值(‘ rel’和‘ log10’)的变化。即可知,当随着培训数据量的逐渐减少,这两个误差指标都缓慢增加,所以误差值越小越好

误差指标

二、checkpoint.pth.tar:

其实训练一个深度神经网络是需要挺长的时间的,即使是在高性能服务器上,有些训练也要持续几天之久。
如果当你遇到这种尴尬的情况:花了一天时间好不容易训练模型到 60% 啦,突然,机房要停电?学长要占用服务器?购买的 GPU 计算时间用完了等等。

这时候该怎么办呢??

训练了一大半的模型不能功亏一篑呀,所以这时候就要未雨绸缪回头有机会了加载接着训练,所以这时候就要将模型保存为一个文件:

#未雨绸缪,防止丢失
        if err < best_val_err:
            best_val_err = err#当前最好精度
            torch.save({
                'epoch': start_epoch + epoch + 1,#保存的当前轮数
                'state_dict': model.state_dict(),#训练好的参数
                'optimizer': optimizer.state_dict(),#优化器参数,为了后续的resume
            }, 'checkpoint.pth.tar')#保存模型到checkpoint.pth.tar

然后再重新加载

resume_file = 'checkpoint.pth.tar'
    if resume_from_file:
        if os.path.isfile(resume_file):
            print("=> loading checkpoint '{}'".format(resume_file))
            checkpoint = torch.load(resume_file)
            start_epoch = checkpoint['epoch']#epoch,可以用于更新学习率等
            model.load_state_dict(checkpoint['state_dict'])#模型参数
            print("=> loaded checkpoint '{}' (epoch {})"
                  .format(resume_file, checkpoint['epoch']))
        else:
            print("=> no checkpoint found at '{}'".format(resume_file))

这样就可以保存(save)&加载(load)训练中的 PyTorch 模型啦,而且这样也不怕服务器突然掉链子,还能够把训练各个阶段的模型都保存下来,用于研究模型训练的各个步骤。


三、nyu_depth_v2_labeled.mat数据集:

由于是.mat文件,所以我用matlab把该文件打开后如下图:

nyu数据集

其中列举一些变量的含义:

(1)depths-HxWxN维度的矩阵深度图,其中H和W分别为高度和宽度,N为图像的个数。深度元素的值是米。

(2)images-HxWx3xN RGB图像矩阵,其中H和W分别是高度和宽度,N是图像的数量

(3)labels-HxWxN标签矩阵,其中H和W分别是高度和宽度,N是图像数量。 标签范围从1…C,其中C是类的总数。 标签的范围从1…C是类的总数。如果一个像素的标签值为0,那么这个像素就没有标记。


代码中首先应用交叉验证将训练集划分为两部分,训练集验证集
训练集:用于训练模型
验证集:在使用测试集得出模型误差之前,用验证测试模型的误差
先给定一个分隔位置,然后确定测试集和验证集:

val_start_idx = int(len(train_lists) * 0.8)                 #交叉验证集

    val_lists = train_lists[val_start_idx:-1]
    train_lists = train_lists[0:val_start_idx]

后再用torch.utils.data.DataLoader()迭代取该数据集(一个一个batch读入),该接口主要用来将自定义的数据读取接口的输出或者PyTorch已有的数据读取接口的输入按照batch size封装成Tensor,后续只需要再包装成Variable即可作为模型的输入

train_loader = torch.utils.data.DataLoader(NyuDepthLoader(data_path, train_lists),
                                               batch_size=batch_size, shuffle=True, drop_last=True)
    val_loader = torch.utils.data.DataLoader(NyuDepthLoader(data_path, val_lists),
                                               batch_size=batch_size, shuffle=True, drop_last=True)
    test_loader = torch.utils.data.DataLoader(NyuDepthLoader(data_path, test_lists),
                                             batch_size=batch_size, shuffle=True, drop_last=True)

再根据以下代码获得原始图和深度图,注意要提取深度图像,要记得取max

        for input, depth in val_loader:
            input_var = Variable(input.type(dtype))#模型的输入
            depth_var = Variable(depth.type(dtype))

            output = model(input_var)#resnet50模型处理后的输出

            input_rgb_image = input_var[0].data.permute(1, 2, 0).cpu().numpy().astype(np.uint8)#原始图像
            input_gt_depth_image = depth_var[0][0].data.cpu().numpy().astype(np.float32)#depth图像
            pred_depth_image = output[0].data.squeeze().cpu().numpy().astype(np.float32)

            input_gt_depth_image /= np.max(input_gt_depth_image)#提取depth图像
            pred_depth_image /= np.max(pred_depth_image)#提取预测的深度图像

            plot.imsave('input_rgb_epoch_0.png', input_rgb_image)
            plot.imsave('gt_depth_epoch_0.png', input_gt_depth_image, cmap="viridis")
            plot.imsave('pred_depth_epoch_0.png', pred_depth_image, cmap="viridis")

四、test模块误差和阈值部分的代码理解:

这里误差计算中pred_depth_image多表示观测值input_gt_depth_image则多表示真值阈值Threshold部分没有查到太多与该代码有关的相关资料,我理解的是他给定一个阈值部分,这样图像的深浅或许会有不同的显现,在这里等待大家不同的理解

初始化:

Threshold_1_25 = 0
Threshold_1_25_2 = 0
Threshold_1_25_3 = 0
RMSE_linear = 0.0
RMSE_log = 0.0
RMSE_log_scale_invariant = 0.0
ARD = 0.0
SRD = 0.0

计算:(注释中也有部分理解)

 #观测次数n
        n = np.sum(input_gt_depth_image > 1e-3)

        idxs = (input_gt_depth_image <= 1e-3)
        pred_depth_image[idxs] = 1
        input_gt_depth_image[idxs] = 1

        pred_d_gt = pred_depth_image / input_gt_depth_image
        pred_d_gt[idxs] = 100
        gt_d_pred = input_gt_depth_image / pred_depth_image
        gt_d_pred[idxs] = 100

        # 设定阈值
        Threshold_1_25 += np.sum(np.maximum(pred_d_gt, gt_d_pred) < 1.25) / n
        Threshold_1_25_2 += np.sum(np.maximum(pred_d_gt, gt_d_pred) < 1.25 * 1.25) / n
        Threshold_1_25_3 += np.sum(np.maximum(pred_d_gt, gt_d_pred) < 1.25 * 1.25 * 1.25) / n

        log_pred = np.log(pred_depth_image)#求观测值的log,为了便于下面求误差
        log_gt = np.log(input_gt_depth_image)#求真实值的log,为了便于下面求误差

        d_i = log_gt - log_pred

#下为不同误差计算
#均方根误差(RMSE),它是观测值与真值偏差的平方和观测次数n比值的平方根,pred_depth_image:观测值,input_gt_depth_image:真值
        RMSE_linear += np.sqrt(np.sum((pred_depth_image - input_gt_depth_image) ** 2) / n)#均方根误差
        RMSE_log += np.sqrt(np.sum((log_pred - log_gt) ** 2) / n)#rms(log)
        RMSE_log_scale_invariant += np.sum(d_i ** 2) / n + (np.sum(d_i) ** 2) / (n ** 2)
        ARD += np.sum(np.abs((pred_depth_image - input_gt_depth_image)) / input_gt_depth_image) / n#rel,相对误差
        SRD += np.sum(((pred_depth_image - input_gt_depth_image) ** 2) / input_gt_depth_image) / n

Threshold_1_25 /= num_samples
Threshold_1_25_2 /= num_samples
Threshold_1_25_3 /= num_samples
RMSE_linear /= num_samples
RMSE_log /= num_samples
RMSE_log_scale_invariant /= num_samples
ARD /= num_samples
SRD /= num_samples

print('Threshold_1_25: {}'.format(Threshold_1_25))
print('Threshold_1_25_2: {}'.format(Threshold_1_25_2))
print('Threshold_1_25_3: {}'.format(Threshold_1_25_3))
print('RMSE_linear: {}'.format(RMSE_linear))
print('RMSE_log: {}'.format(RMSE_log))
print('RMSE_log_scale_invariant: {}'.format(RMSE_log_scale_invariant))
print('ARD: {}'.format(ARD))
print('SRD: {}'.format(SRD))

五、NYU_ResNet-UpProj.npy:

模型文件(.npy)部分内容如下:由一个字典组成,字典中的每一个键对应一层网络模型参数

由于numpy版本存在不兼容的问题,所以我用如下代码在控制台上输出了.npy文件的内容:

import numpy as np
old = np.load
np.load = lambda *a,**k: old(*a,**k,allow_pickle=True)
test=np.load('NYU_ResNet-UpProj.npy',encoding = "latin1")  #加载文件
#doc = open('1.txt', 'a')  #打开一个存储文件,并依次写入
#print(test, file=doc)  #将打印内容写入文件中
print(test)

输出的部分内容如下:

.npy文件

或写入文件,内容如图:

npy文件

所以可直接利用如下语句加载模型权重

weights_file = "NYU_ResNet-UpProj.npy"

 model_params = model.state_dict()
 data_dict = np.load(weights_file, encoding='latin1').item()#加载npy文件格式


越努力,越幸运

end~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354