一、背景与概要
在经过第三篇发现的CMVS开源项目的研究探索后,本文将针对CMVS与PMVS技术进行实验性探索,研究其相关的情况,如可行性、精度与可靠性等。
组件包遵循GPL开源协议,开源地址如下:GitHub,该版本适用于Windows/Linux等平台。
CMVS采用C++进行开发,能快速处理大量高精度数据,可以通过CUDA进行模型加速重建与渲染。
而Python具有简洁简单可快速开发的优势,故采用Python+CMVS结合开发的方式,一方面即可扩展已有的GNSSAMS程序,加入三维形变监测功能,另一方面能够实现代码的精简与快速开发,使得研究注意力能够集中在三维模型的构建与处理上。
二、图像三维重建基本流程
- 多视角图像
- 图像特征提取匹配
- 稀疏重建Sfm
- 稠密重建MVS
- 点云模型化
- 生成三维模型
从上面流程来看,CMVS实现了稠密点云的重建,后续的数据提取等还需要进一步的编程处理。
三、基本流程试验
3.1 流程框架与重难点标记
序号 | 项目 | 备注 |
---|---|---|
1 | 相机参数标定 | 两种方式 |
2 | 多角度原始目标影像获取与相片相机参数文件标定 | 采用影像自带参数或是棋盘法,通过Python提取 |
3 | 获取影像的特征提取与匹配 | 待研究如何制作 |
4 | 稀疏重建Sfm | 待研究 |
5 | 稠密重建MVS | 待研究 |
6 | 点云模型化 | 待研究 |
7 | 生成三维模型 | 待研究 |
8 | 模型控制点世界三维坐标获取与存档 | 需要模型结果与模型存储结构 |
9 | 时序模型控制点平面网型形变分析 | 通过不同时候获取的同一目标三维模型,确定控制点组成的表面网变化情况,得出形变数据 |
本次研究的风险在于CMVS是否可用,成果是否能进行二次开发。
记录一下:2020年9月11日,电脑注册表疑似遭到破坏,需要重装系统,重整所有系统问题。
3.2 相机参数标定与固定拍摄角度的参数确定
相机参数包含相机的内参与外参,相机参数确定了成像的相关情况。
3.2.1 从EXIF获取相机参数
相关的代码如下:
def getPara_PICTURE_EXIF(self,standardPic):
"""
从图像EXIF参数中获取相机参数
:param standardPic: 标准像片
:return:
"""
# CMOS长宽信息
w_c = 6.29
h_c = 5.21
# 读取图片的长宽信息
img = cv2.imread(standardPic)
h = img.shape[0]
w = img.shape[1]
print(w, h)
# 从EXIF中读取焦距
i = Image(standardPic)
a, b = i.read_exif().get('Exif.Photo.FocalLength').split('/')
fm = int(a) / int(b)
f = w * fm / w_c
# 计算内参信息
K = np.zeros((3, 3))
K[0][0] = f
K[1][1] = f
K[0][2] = w / 2
K[1][2] = h / 2
print(K)
3.2.2 采用棋盘法估计相机参数
棋盘法即张正友标定法,需要棋盘图,可以用摄影测量专业的相机标定板。
但网上有很多棋盘图相关的图像,但是为了保证高清与自适应需要,可以自己做一个。
棋盘生成的代码参见:地表三维模型的构建与时序模型地表形变监测(五):相机标定试验与研究
标定图片拍摄规范 |
---|
在标定的整个过程中,不能调节相机的光圈、焦距,要保证在标定中摄像头进光量与焦距的一致 |
建议在摄像头视野内五个不同位置上(左上、右上、左下、右下、正中心)分别拍摄图片 |
拍摄的图片最好为摄像头视野的1/4左右 |
不要只拍摄标定板与镜头面平行的图片,也要拍摄一些有倾斜角度的图片 |
拍摄过程中可以对标定板适当的进行补光,调节标定板到镜头的距离,以便于排出清晰的图片 |
标定图片数量个人认为15张左右,太少的话标定的参数会不准确 |
标定时用的标定板最好选择x方向与y方向棋盘格不同的,便于标定程序识别标定板方向 |
相关的代码如下:
def getPara_CHESE(self,standardPicDir):
"""
棋盘法(张正友法)获取相机内参
:param standardPicDir: 标准像片
:return:
"""
# 设置棋盘板长宽
chessboard_size = (9, 6)
# 定义数组存储检测到的点
obj_points = [] # 真实世界中的三维坐标
img_points = [] # 图片平面的二维坐标
####准备目标坐标 (0,0,0),(1,0,0)...(9,6,0)
# 设置世界坐标下的坐标值
# 假设棋盘正好在x-y平面上,z直接取零,从而简化初始步骤
# objp包含的是10*7每一角点的坐标
objp = np.zeros((np.prod(chessboard_size), 3), np.float32) # 9*6个三维坐标
objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2)
# 读取图片,使用glob文件名管理工具
calibration_paths = glob.glob(standardPicDir+"/*.JPG")
# 对每张图片,识别出角点,记录世界物体坐标和图像坐标
for img_path in tqdm(calibration_paths):
# tqdm是进度条,以了解距离处理上一个图像多长时间,还剩多少图像没有处理
# 加载图片
img = cv2.imread(img_path)
# 照片太大 缩小一半 (不能缩小!!!!内参会变!!像素变小了 并不是对原图像处理)
# img = cv2.resize(img, None, fx=0.2, fy=0.2, interpolation=cv2.INTER_CUBIC)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#
# cv2.imshow('i',img)
# cv2.waitKey(0)
# 寻找角点将其存入corners(该图片9*6个角点坐标),ret是找到角点的标志(True/False)
ret, corners = cv2.findChessboardCorners(gray, (9, 6), None)
if ret == True:
# 检测到角点执行以下操作(一般都能检测到角点,除非图片不是规定的棋盘格)
# 定义角点精准化迭代过程的终止条件 (包括精度和迭代次数)
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.0010)
# 执行亚像素级角点检测
corners2 = cv2.cornerSubPix(gray, corners, (5, 5), (-1, -1), criteria)
obj_points.append(objp)
img_points.append(corners2)
# 可视化角点
# img = cv2.drawChessboardCorners(gray,(9,6),corners2,ret)
# cv2.imshow('s',img)
# cv2.waitKey(100)
# 相机标定
# 每张图片都有自己的旋转和平移矩阵 但是相机内参是畸变系数只有一组(因为相机没变,焦距和主心坐标是一样的)
ret, K, dist, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, gray.shape[::-1], None, None)
# 保存参数
np.save("./camera_params/ret", ret)
np.save("./camera_params/K", K)
np.save("./camera_params/dist", dist)
np.save("./camera_params/rvecs", rvecs)
np.save("./camera_params/tvecs", tvecs)
print(K)
3.3 Python联合式开发与多源信息反馈
采用Python将exe、DLL库等各功能模块链接起来,实现信息数据采集-数据标记与处理-三维重建的工作。
3.3.1 CMVS开源建模软件
Python调用机制:
import subprocess
rootDir = "../source/exModule/"
# 设置命令
commend1 = rootDir + "\cmvs.exe" + " " + rootDir + "\pmvs\\"
commend2 = rootDir + "\genOption.exe" + " " + rootDir + "\pmvs\\"
commend3 = rootDir + "\pmvs2.exe" + " " + rootDir + "\pmvs\ option-0000"
# 执行CMVS
process = subprocess.Popen(commend1, shell=True)
process.wait()
process = subprocess.Popen(commend2, shell=True)
process.wait()
process = subprocess.Popen(commend3, shell=True)
process.wait()
3.3.2 Python脚本开发与GNSSAMS综合——数据处理与信息呈现
将处理的结果融入到前端PyQt5组件,将三维模型呈现出来。
3.4 模型数据处理(纠正/去噪等)与二次开发可行性评估
CMVS是否提供成熟的方案?
3.5 时序模型数据比对与形变提取
时序模型
3.6 形变提取误差与可靠性评估
评估评价
四、参考文献
[1]ayayayayo. 学习记录之三维重建相关论文阅读[OL]. CSDN. 2020-01-11.
[2]ayayayayo. 学习记录之相机内参估计[OL]. CSDN. 2020-01-19.
[3]ayayayayo. 学习记录之三维重建2:cmvs稠密点云重建的实现[OL]. CSDN. 2020-02-12.
[4]dongtuu. opencv-python 张正友相机标定法实现[OL]. CSDN. 2018-03-10.
[5]weixin_33795833. 生成黑白棋盘标定图和单目相机标定(一)(python+opencv实现)[OL]. CSDN. 2014-06-13.
Comments NOTHING