Project-Reconstruction-3D

概述

  这个项目是本周数字图像处理课程的一个project,目标是利用同一物体多角度的图片对物体进行三维重建。主要是利用世界坐标系和像素坐标系之间的转换进行点是否存在的判断,从而将在世界坐标系中存在的点进行点云的绘制,得到物体重建的结果。

相关知识

坐标系的转换

  为了实现物体的三维重建,我们需要掌握将世界坐标系上的点转换到像素坐标系上的点。这个过程中涉及到的坐标系包括了世界坐标系,相机坐标系,图像坐标系和像素坐标系。在转换的过程中同时需要利用针孔成像原理进行计算。相关知识参考相机标定原理、步骤

相机的参数

  我们在利用数码相机进行一次照相,实际上就是进行了一次世界坐标系和CMOS上的像素坐标系的转换。相机实际上利用了内参和外参两部分参数进行了这个步骤。关于内参和外参的介绍及标定基本思路同样参考相机标定原理、步骤

思路整理

整体思路

  利用matlab的”camera_calibration”工具,我们可以得到相机的参数”cameraParams”,包含相机的内参,外参,以及畸变的信息等。我们进行三维重建的主要思路是在世界坐标系中建立一个可以框住需要重建物体的点阵,然后将世界坐标系的点阵中点转换到各张相机拍摄图片的对应的点。若点阵中的一个点在所有二值化的照片中对应的点都是白色,则基本证明这个点存在在世界坐标系中,若有一张图或多张图上对应的点非白色,则证明这个点没有在世界坐标系中真是存在。
  这个算法有一些问题。第一个问题是当照片数目比较多,且拍摄角度较多的时候,算法更精确一些,因为当照片比较少的时候,虽然对应点在每张图片上都有,但不一定真是存在在世界坐标系中。第二个问题是这个算法的算法复杂度比较高。但是可以进行一些优化,比如如果这个点已经判断在一张图上的对应点不存在,则我们可以将这个点从点阵中去除,从而降低算法复杂度。

部分步骤

  此处仅详细说明算法中关键步骤。
  二值图像的相机畸变矫正主要使用了“undistortImage”函数,实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
binary_images = cell(1, 8);
for i = 1:8
% read the binary img
src_filename = img_set.ImageLocation{i};
[src_path,src_name,src_ext] = fileparts(src_filename);
temp_filename = strcat(src_name,src_ext);
binary_filename = fullfile(binary_dir, temp_filename);
binary_Img = imread(binary_filename);
%Attention : use "undistortImage" to orthodontic distortion
undistortedImage = undistortImage(binary_Img, cameraParams);
binary_images{i} = undistortedImage;
end

  进行世界坐标系到像素坐标系的转换及点是否存在的实现如下,即使用一个for循环来遍历全部RGB图像的二值图像,在每次循环中,利用矩阵计算进行判断投影点是否存在,若存在则保留;若不存在,则去除。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
%% get the point in the cuboid
loop_point = ones(num_points, 1);
K = cameraParams.IntrinsicMatrix;
figure;
for j = 1:8
% transform the world coordinate system to pixel coordinate system
fprintf('begin check points in photo: %d\n', j);
R = cameraParams.RotationMatrices(:,:,j);
T = cameraParams.TranslationVectors(j,:);
temp_pixel = cuboid * [R;T] * K;
s = temp_pixel(:,3);
system_pixel = [temp_pixel(:,1)./s, temp_pixel(:,2)./s];

% loop the point between all pictures one by one
% if the point is not in the picture,the point is eliminated.
p_row = round(system_pixel(:,2));
p_col = round(system_pixel(:,1));
loop_point = loop_point & binary_images{j}(p_row + (p_col-1)*row)>0;

% put points into the binary_img
% to check whether the corresponding relationship between points is correct.
subplot(3,3,j);
imshow(binary_images{j});
hold on;
indices = find(loop_point);
system_pixel_remain = system_pixel(indices(1:2:end),:);
plot(system_pixel_remain(:,1),system_pixel_remain(:,2),'r.');
hold off;
end

  最后将剩余的点组成的点云画出。
  本次实验重建的是一个中间为空心的相机三脚架上的辅助固定架,重建过程中每张图片对应点如下:
   photo1
  最后重建的结果如下:
     photo2

代码实现

  代码实现参考我的github:SuperYanyann/Digital_Image_Processing

小结

  这次project中有三个比较大的问题,第一个问题是Matlab的”camera_calibration”使用的时候,用来计算的图片和对应的参数矩阵的对应的问题,当每次进行照片删除的时候,需要将文件夹中的图像序号做对应的修改。第二个问题是空间中长方体坐标选择的问题,根据”camera_calibration”工作中得到的可视化的坐标系进行坐标的选择是一个比较高效的方法。三个问题是标定板的选择的问题,应该选择左右不对称的标定板,防止坐标轴原点出现在左在右不统一的情况。

参考

[1] Camera Calibration Toolbox for Matlab
[2] 相机标定原理、步骤
[3] 相机参数标定及标定结果如何使用