一、Gaze
1.特征图生成
问题1:为什么要先渲染出两个低分辨率的特征图(已解决
1.相对直接 生成 高分辨率计算 效率更加迅速
2.多尺度 融合:可以 捕捉粗糙到细致的信息
3.也可以避免 过拟合
2.特征图重塑
问题2:为什么要进行Fe特征图重塑(已解决
我们已知Fe的尺寸为64x64x258,由于下图中旋转矩阵为3x3矩阵,所以要重塑为可以和旋转矩阵相乘的尺寸
问题3: F e − r o t = R F e F_{\mathrm{e-rot}}=\mathbf{R}F_{\mathrm{e}} Fe−rot=RFe怎么理解这个旋转公式(已解决
这是眼睛特征图的显示旋转,其中R为3x3的旋转矩阵,这个旋转矩阵由注视标签决定
所谓注视标签就是俯仰角和偏航角
计算方法:罗德里格斯公式
其中k是旋转轴向量 (xyz轴的单位向量:比如(0,0,1))
K是k向量分量构成斜对称矩阵
这样就可以算出沿着不同坐标旋转的的旋转矩阵
再将 xyz旋转矩阵组合
3.渲染优化图像
问题1:常见的上采样方式(已解决
1.最近插值法 :最近像素
2.双线插值法 :最近四个 的 加权平均值
3.双三次插值法:多一个三次项
4.转置卷积
问题2:转置卷积(已解决
可学习的上采样
不是卷积的逆过程,但是有一个类逆思想:
普通卷积:尺寸减少,深度 变多
转置卷积:尺寸变大,深度变小
假如有一个特征图a,通过一个普通卷积得到特征图b
你们我们可以通过转置卷积从b得到与a类似但不一样的c
经过实验我们可知转置卷积的计算过程
1.假如有一个特征图a,通过一个普通卷积得到特征图b
2.现在我们要从b逆推一个类a的扩大尺寸的过程
3.我们可以设置参数原普通卷积的s,p,k
4.那么我们需要对b预处理
5.首先对于b每个元素内部填充s-1个行或列0
6.对周围填充k-p-1行列 0
7.然后对其 进行s=1p=0,并且卷原卷积核上下左右反转进行普通卷积
这样 就可以得出 与a类似但不一样的c
问题3:为什么感知损失使用了VGG16卷积(已解决
使用VGG16卷积提取图像的多个高级特征,使得目标图像 和 生成图像不仅仅 在 像素相似,也会在视觉 上相似
问题4:怎么理解感知损失公式(已解决
表示每一个输入图像经过神经网格之后处理的特征图
VGG16构成:13卷积+3个池化层最后一个softmax激活函数
softmax激活函数
然后选取最大的作为该类
主要用于多分类问题
问题5:什么是one-hot编码(已解决
[1,0,4,3,2]->
[0 1 0 0 0
1 0 0 0 0
0 0 0 0 1
0 0 0 1 0
0 0 1 0 0]
问题6:什么是功能损失(已解决
根据代码的特殊功能计算这种特殊功能的损失
比如这个计算目标图像和生成图像的注视角度的估计
二、NeRF代码
1._minify函数
①模块导图
②自写
#导入的包
import numpy as np
import os,imageio
#分辨率和放缩的处理
def _minify(basedir,factor=[],resolution=[]):
#判断是否需要加载数据
needload=False
for i in factor:
dir=os.path.join(basedir,'images_{}'.format(i))
################################忘记
if not os.path.exists(dir):
needload=True
#语法忘记
####################################
for r in resolution:
dir=os.path.join(basedir,'images_{}x{}'.format(r[1],r[0]))
if not os.path.exists(dir):
needload=True
if not needload:
return
from subprocess import check_output
#!筛选照片的目录
dir=os.path.join(basedir,'images')
#imgs=[for i in (sorted(os.listdir(dir)))] 错误
imgs = [os.path.join (basedir,i)for i in sorted(os.listdir(dir))]
#imgs2=[]
#for i in imgs:
# if i.endswith('png','','',''):
# imgs2.append(i) 过于麻烦
imgs=[f for f in imgs if any([f.endswith(ew) for ew in['JPG', 'jpg', 'png', 'jpeg', 'PNG']])]
#any? 是检查可迭代对象是否具有某种特性
dir_origin=dir
#!!获得目的信息
wd=os.getcwd()
for i in factor + resolution:
## isinstance的用法
## 统一连接[相同结构]
if(isinstance(i,int)):
name='images_{}'.format(factor)
#%表示数字结构
#i是放缩因子
resizeing='{}%'.format(100./i)
else:
name='images_{}x{}'.format(i[1],i[0])
resizeing='{}x{}'.format(i[1],i[0])
dir=os.path.join(basedir,name)
if os.path.exists(dir):
continue
#!!!使用命令行进行放缩
os.chdir(wd)
os.makedirs(dir)
print('mogrify',dir_origin,resizeing)
#*.通配符
arg='cp {}/*.{}'.format(dir_origin,dir)
check_output(arg,shell=True)
############
ext=imgs[0].split('.')[-1]
############
#join 和直接字符串的区别
#join更加安全 ,直接字符串更加简单
arg=''.join(['mogrify','-resize',resizeing,'-format','png','*.{}'.format(ext)])
#!转换工作目录
check_output(arg,shell=True)
os.chdir(wd)
if ext !='png':
check_output('rm {}/*.{}'.format(dir,'ext'),shell=True)
print('Done')
2._load_data函数
①模块导图
②自写代码
def _load_data(basedir,factor=None,width=None,height=None,log_imgs=True):
##加载数据
poses_arg=np.load(os.path.join(basedir,'poses_bounds.npy'))
poses=poses_arg[:,:-2].reshape(-1,3,5).transpose([1,2,0])
pds=poses_arg[:,-2:].transpose([1,0])
##获得图像的大小
#错误img_dir=[f for f in sorted(os.listdir(os.path.join(basedir,'images'))) if f.endswith() is 'png'or'jpg'or 'jpeg'or'PNG'or'JPG'][0]
#f.endswith()需要传参数
img_dir=[f for f in sorted(os.listdir(os.path.join(basedir,'images')))if f.endswith('JPG') or f.endswith('jpg') or f.endswith('png')][0]
sh=imageio.imread(img_dir).shape
sfs=''
##进行放缩
if factor is not None:
sfs='_{}%'.format(100./factor)
_minify(basedir,factor=[factor])
factor=factor
elif width is not None:
#factor=width/sh[1]
#1.放缩因子=原本/目标的
#2.除法应该使用浮点数
factor=sh[1]/float(width)
#修改为整数(文件名称表达)
height=int(sh[0]/factor)
sfs='_{}x{}'.format(width,height)
_minify(basedir,factor=[factor])
elif height is not None:
factor=sh[0]/float(height)
width=int(sh[1]/factor)
sfs='_{}x{}'.format(height,width)
_minify(basedir,factor=[factor])
else:
factor=1
#错误dir=os.path.join(basedir,'images',sfs)
dir=os.path.join(basedir,'images'+sfs)
#增强鲁棒性
if not os.path.exists(dir):
print("创建失败")
return
dir_imags=[f for f in sorted(os.listdir(os.path.join(basedir,'images')))if f.endswith('JPG') or f.endswith('jpg') or f.endswith('png')]
if len(dir_imags)!=len(poses[...:-1]):
print("创建失败")
return
#更新poses值
imag=[imageio.imread(f) for f in dir_imags]
sh=imag[0].shape
################################
#poses[:2,4,:]=imag[]
#矩阵=常数->矩阵所有数字都等于这个常数√切片中
poses[:2, 4, :] = np.array(sh[:2]).reshape([2, 1])
poses[2, 4, :] = poses[2, 4, :] * 1. / factor
################################
if not log_imgs:
return poses,pds
else:
def imread(f):
if f.endswith('png'):
return imageio.imread(f,ignoregamma=True)
else:
return imageio.imread(f)
###为什么只处理前三,大部分只有三个rgb颜色通道
imags=[imread(f)[...,:3]/255 for f in dir_imags]
imags=np.stack(imags,-1)
return poses,pds,imags
③问题1:poses的构成
poses:维度是nx15
如图左3x3是旋转矩阵,3x1是相机坐标系坐标,右3x1是相机内参
peses.agg后两个分别是近点和远点
④问题2:为什么要在加载数据的时候进行一系列处理
3.相机参数
①相机内参
fx和fy是相机水平方向和垂直方向的焦距,一般fx等于fy等于f
cx和cy是图像原点与相机光心的偏移距离。
②相机外参c2w
左上3x3为旋转矩阵,右3x1是平移向量
旋转矩阵的列向量是对应世界坐标的基向量
平移向量是世界坐标的原点
③如何得到相机参数
COLMAP方法
1.使用colmap软件生成cameras.bin,images.bin,points3D.bin,project.in二级制文件
2.读取文件生成npy文件
4.viewmatrix函数
①思路
参数:up上向量,z向前向量,pos坐标
使用np.cross垂直up和z向量的向量做x轴
在算出z轴(都要归一化)
②自写
def viewmatrix(z,up,pos):
vec_2=normalize(z)
#叉积运算 c=axb
vec_0=normalize(np.cross(z,up))
vec_1=normalize(np.cross(vec_0,vec_2))
#################
m=np.stack([vec_0,vec_1,vec_2,pos],1)
#vec_0也是数组!!
#################
return m
5.ptsocam函数
①作用
对相机坐标到世界坐标变化的实施
②自写
def ptstocam(ptw,c2W):
###np.matmul矩阵乘法
###a=a[...,0]
#a=a[...,np.newaxis]
#便于使用矩阵乘法
tt=np.matmul(c2W[:3,:3].T,(ptw-c2W[:3,3])[...,np.newaxis])[...,0]
return tt
6.poses_avg函数
①作用
计算所有相机的平均姿态
②自写
def poses_avg(poses):
# hwf=poses[0,:3,-1] (3)
hwf = poses[0, :3, -1:] # (3,1)
# c2w=poses[:,:3,:3].mean(0)
# o=poses[:,:3,3].mean(0)
# poes=np.stack(c2w,o,hwf,axis=1)
center = poses[:, :3, 3].mean(0)
vec2 = poses[:, :3, 2].sum(0)
up = poses[:, :3, 1].sum(0)
#concatenate 和stack的区别
#前者:需要处理堆叠轴其他一模一样
#后者:会增加新轴
#a = np.array([1, 2, 3])
#b = np.array([4, 5, 6])
#c = np.concatenate([a, b], axis=0) (6)
# a = np.array([1, 2, 3])
# b = np.array([4, 5, 6])
# c = np.stack([a, b], axis=0) (2,3)
pose = np.concatenate([viewmatrix(vec2, up, center), hwf], axis=1) #(3x5)
return pose
7.render_path_spiral函数
①作用
围绕单个相机生成一系列螺旋式曲线的轨迹
②自写
def render_path_spiral(c2w,up,rads,rots,zrate,N,focal):
hwf=c2w[:,4:5]
poses=[]
rads=np.array(list(rads)+[1.])
for thrat in np.linspace(0.,2*np.pi*rots,N+1)[:-1]:###忘了-1
pos=np.dot(c2w[:3,:4],np.array([np.cos(thrat),-np.sin(thrat),np.sin(thrat*zrate),1.]*rads))
z=normalize(pos-np.dot(c2w[:3,:4],np.array([0,0,-focal,-1])))
poses.append(viewmatrix(up,z,pos))
return poses
8,recenter_poses函数
①作用
将世界坐标系转化为平均姿态坐标系
②过程
算出平均姿态坐标系-》提取转换矩阵=》提取所有姿态除了内参-》将所有量齐次化-》矩阵相乘
③自写
def recenter_poses(poses):
##思路:得到中心相机poes->得出c2w->处理poses(去除相机内参,变成齐次坐标)
c2w=poses_avg(poses)[:3,:4]
#poes_=poses 保证创建了完整的副本
poses_ = poses + 0
bound=np.array([0,0,0,1])
c2w=np.concatenate(c2w,np.reshape(bound,[1,4]),axis=0)
bound=np.tile(np.reshape(bound,[1,1,4]),(poses.shape[0],1,1))
poses=np.concatenate(poses,bound,axis=1)
poses=np.linalg.inv(c2w)@poses
#原本没有齐次化
poses_[:,:3,:4]=poses[:,:3,:4]
poses=poses_
return poses