计算 3D 艺术画

                     

贡献者: addis

  • 本文需要更多参考文献。
  • 本文处于草稿阶段。

1. 3D 艺术画

图
图 1:2011 年最大的 3D 艺术画,画于伦敦街头,获吉尼斯纪录
图
图 2:从不同角度看 3D 艺术画(图 1 由该图中右上角相机拍摄)

2. 计算

预备知识 由图像坐标计算射线,直线和平面的交点

   由预备知识中的两篇文章,若给出预期的效果图(即图 1 中的虚构部分),世界坐标系中投影平面的位置,以及相机模型的参数和位置,就可以将效果图上的点一一对应到世界系的射线,再对应到投影平面上。

   我们不直接投影到世界系的 $xy$ 平面上,是因为一些 3D 艺术画不仅使用地板,也可能使用墙壁和天花板等多个平面。

代码 1:art3D.m
% 参数中矢量不必归一化

% === 设置相机参数 ===
imfile = 'test.png'; % 图片位置
cam_pos = [10, -10, 10]; % 世界参考系中相机位置
cam_z = -cam_pos; % 世界参考系中相机朝向
view_ang = 40/180*pi; % 相机水平视角 (单位:弧度)
cc = [0, 0]; % 光轴相对图片中心的偏移 (单位: 像素),

% === 设置投影平面 ===
plane_o = [0, 0, 0]; % 原点
plane_z = [0, 0, 1]; % z 轴单位矢量
plane_x = [1, 0, 0]; % x 轴单位矢量
% ================

% 相机坐标系
% 相机的 x 轴总是水平
cam_z = cam_z / norm(cam_z);
cam_x = cross([0, 0, -1], cam_z); cam_x = cam_x / norm(cam_x);
cam_y = cross(cam_z, cam_x);
RT = [cam_x', cam_y', cam_z']; % rotation matrix

% 平面坐标系
plane_z = plane_z / norm(plane_z);
plane_y = cross(plane_z, plane_x);
plane_y = plane_y / norm(plane_y);
plane_x = cross(plane_y, plane_z);

% 读取图片
I = imread(imfile);
[N1, N2, ~] = size(I);
f = N2/2/tan(view_ang/2); % 焦距 (单位: 像素)

% 在相机系中生成图片网格(每个像素都是网格中一个正方形)
[xc, yc] = meshgrid(linspace(0.5, N2+0.5, N2+1), linspace(0.5, N1+0.5, N1+1));
xc = xc - N2/2 + 0.5;
yc = yc - N1/2 + 0.5;

% 世界系中的射线(对应每个格点)
vc = zeros(3, (N1+1)*(N2+1));
vc(1,:) = xc(:); vc(2,:) = yc(:); vc(3,:) = f;
v = RT * vc;

% 世界系中射线与平面的交点 (参考 https://wuli.wiki/online/LPint.html)
intersec = ((plane_o - cam_pos) * plane_z') * v ./ (plane_z * v) + cam_pos';

% 将交点转换到平面参考系
inter1 = intersec - plane_o';
if max(plane_z * inter1) > 1e-14
    error('intersection not on plane');
end
xp = plane_x * inter1;
yp = plane_y * inter1;
xp = reshape(xp, N1+1, N2+1);
yp = reshape(yp, N1+1, N2+1);

% 画图
zp = zeros(size(xp));
cdata = double(I)/255; cdata(end+1, end+1, 3) = 0;
figure; surf(xp, yp, zp, 'CData', cdata, 'LineStyle', 'none');
view(0, 90); axis equal;


致读者: 小时百科一直以来坚持所有内容免费无广告,这导致我们处于严重的亏损状态。 长此以往很可能会最终导致我们不得不选择大量广告以及内容付费等。 因此,我们请求广大读者热心打赏 ,使网站得以健康发展。 如果看到这条信息的每位读者能慷慨打赏 20 元,我们一周就能脱离亏损, 并在接下来的一年里向所有读者继续免费提供优质内容。 但遗憾的是只有不到 1% 的读者愿意捐款, 他们的付出帮助了 99% 的读者免费获取知识, 我们在此表示感谢。

                     

友情链接: 超理论坛 | ©小时科技 保留一切权利