MATLAB 全景图切割及盒图显示的实现步骤


Posted in Python onMay 14, 2021

part1 全景图切割

原图:

MATLAB 全景图切割及盒图显示的实现步骤

切割效果:

MATLAB 全景图切割及盒图显示的实现步骤
MATLAB 全景图切割及盒图显示的实现步骤

以下是切割部分步骤:
举这张图为例,图片格式hdr,jpg啥的都行:

MATLAB 全景图切割及盒图显示的实现步骤

1.1 边缘剔除

有些全景图会自带白灰色边缘,若是直接进行切割便会出现如下效果:

MATLAB 全景图切割及盒图显示的实现步骤

这时候我们首先要对原图进行白边剔除,代码如下:

oriPic=imread('test.hdr');
[rows,cols,~]=size(oriPic);

for i=cols:-1:1
    tempListR=oriPic(floor(rows/4):ceil(3*rows/4),i,1);
    tempListG=oriPic(floor(rows/4):ceil(3*rows/4),i,1);
    tempListB=oriPic(floor(rows/4):ceil(3*rows/4),i,1);
    if all(round(tempListR-mean(tempListR))==0)&&all(tempListR==tempListG)&&all(tempListR==tempListB)
        oriPic(:,i,:)=[];
    else
        break;
    end
end
oriPic=oriPic(:,end:-1:1,:);
for i=size(oriPic,2):-1:1
    tempListR=oriPic(floor(rows/4):ceil(3*rows/4),i,1);
    tempListG=oriPic(floor(rows/4):ceil(3*rows/4),i,1);
    tempListB=oriPic(floor(rows/4):ceil(3*rows/4),i,1);
    if all(round(tempListR-mean(tempListR))==0)&&all(tempListR==tempListG)&&all(tempListR==tempListB)
        oriPic(:,i,:)=[];
    else
        break;
    end
end
oriPic=oriPic(:,end:-1:1,:);
for i=rows:-1:1
    tempListR=oriPic(i,floor(cols/4):ceil(3*cols/4),1);
    tempListG=oriPic(i,floor(cols/4):ceil(3*cols/4),1);
    tempListB=oriPic(i,floor(cols/4):ceil(3*cols/4),1);
    if all(round(tempListR-mean(tempListR))==0)&&all(tempListR==tempListG)&&all(tempListR==tempListB)
        oriPic(i,:,:)=[];
    else
        break;
    end
end
oriPic=oriPic(end:-1:1,:,:);
for i=size(oriPic,1):-1:1
    tempListR=oriPic(i,floor(cols/4):ceil(3*cols/4),1);
    tempListG=oriPic(i,floor(cols/4):ceil(3*cols/4),1);
    tempListB=oriPic(i,floor(cols/4):ceil(3*cols/4),1);
    if all(round(tempListR-mean(tempListR))==0)&&all(tempListR==tempListG)&&all(tempListR==tempListB)
        oriPic(i,:,:)=[];
    else
        break;
    end
end
oriPic=oriPic(end:-1:1,:,:);

1.2 图像裁剪

我们要让完成的就是如下的变换和裁剪:

MATLAB 全景图切割及盒图显示的实现步骤
MATLAB 全景图切割及盒图显示的实现步骤

这部分其实已经有较为成熟的原理和代码:
代码参考:https://stackoverflow.com/questions/29678510/convert-21-equirectangular-panorama-to-cube-map

原理参考:
http://paulbourke.net/panorama/cubemaps/#1

http://paulbourke.net/panorama/cubemaps/

原理参考文章中更加清晰的变化图:

MATLAB 全景图切割及盒图显示的实现步骤

另:
在参考代码的基础上,对映射像素进行了插值处理,可以使图像更加平滑,原理如下:

MATLAB 全景图切割及盒图显示的实现步骤
MATLAB 全景图切割及盒图显示的实现步骤

主要函数代码:

function resultPic=createCubeMapFace(oriPic,id,height,width)
    [M,N,~]=size(oriPic);
    resultPic=zeros([height,width,3]);
    an=sin(pi/4);
    ak=cos(pi/4);
    
    faceTransform=[0,0;
               pi/2,0;
               pi,0;
               -pi/2,0;
               0,-pi/2;
               0,pi];
    ftu=faceTransform(id,1);
    ftv=faceTransform(id,2);

    for y=0:height-1
        for x=0:width-1
            nx=y/height-0.5;
            ny=x/width-0.5;

            nx=nx*2*an;
            ny=ny*2*an;

            if (ftv == 0)
                u=atan2(nx, ak);
                v=atan2(ny*cos(u),ak);
                u=u+ftu;
            elseif(ftv>0)
                d=sqrt(nx*nx+ny*ny);
                v=pi/2-atan2(d,ak);
                u=atan2(ny,nx);
            else
                d=sqrt(nx*nx+ny*ny);
                v=-pi/2+atan2(d,ak);
                u=atan2(-ny,nx);
            end

            u=u/(pi);
            v=v/(pi/2);

            while(v<-1)
                v=v+2;
                u=u+1;
            end
            while(v>1)
                v=v-2;
                u=u+1;
            end
            while(u<-1)
                u=u+2;
            end
            while(u>1)
                u=u-2;
            end
            u=u/2+0.5;
            v=v/2+0.5;

            u=u*(N-1)+1;
            v=v*(M-1)+1;
            
            fv=floor(v);fv1=floor(v)+1;pv=v-fv;fv1(fv1>M)=M;
            fu=floor(u);fu1=floor(u)+1;pu=u-fu;fu1(fu1>N)=N;
            resultPic(x+1,y+1,:)=double(oriPic(fv,fu,:)).*(1-pv).*(1-pu)+...
                                 double(oriPic(fv1,fu,:)).*(pv).*(1-pu)+...
                                 double(oriPic(fv,fu1,:)).*(1-pv).*(pu)+...
                                 double(oriPic(fv1,fu1,:)).*(pv).*(pu);
        end
    end
    resultPic=uint8(resultPic);
end

函数调用及图像存储:
这里后面长宽数值可以任意设定,但是要求长宽数值一致,如果按照当前写法,结果被存储至result文件夹:

if ~exist('result','dir')
   mkdir('result');
end

for i=1:6
    resultPic=createCubeMapFace(oriPic,i,500,500);
    figure(i)
    imshow(resultPic)
    imwrite(resultPic,['result\',num2str(i),'.jpg'])
end

另: 如图所示
图片序号[1,2,3,4,5,6]分别对应图片[右,后,左,前,上,下]

MATLAB 全景图切割及盒图显示的实现步骤

1.3 完整代码

function panoramic2box
oriPic=imread('889027-884424860.jpg');
[rows,cols,~]=size(oriPic);

for i=cols:-1:1
    tempListR=oriPic(floor(rows/4):ceil(3*rows/4),i,1);
    tempListG=oriPic(floor(rows/4):ceil(3*rows/4),i,1);
    tempListB=oriPic(floor(rows/4):ceil(3*rows/4),i,1);
    if all(round(tempListR-mean(tempListR))==0)&&all(tempListR==tempListG)&&all(tempListR==tempListB)
        oriPic(:,i,:)=[];
    else
        break;
    end
end
oriPic=oriPic(:,end:-1:1,:);
for i=size(oriPic,2):-1:1
    tempListR=oriPic(floor(rows/4):ceil(3*rows/4),i,1);
    tempListG=oriPic(floor(rows/4):ceil(3*rows/4),i,1);
    tempListB=oriPic(floor(rows/4):ceil(3*rows/4),i,1);
    if all(round(tempListR-mean(tempListR))==0)&&all(tempListR==tempListG)&&all(tempListR==tempListB)
        oriPic(:,i,:)=[];
    else
        break;
    end
end
oriPic=oriPic(:,end:-1:1,:);
for i=rows:-1:1
    tempListR=oriPic(i,floor(cols/4):ceil(3*cols/4),1);
    tempListG=oriPic(i,floor(cols/4):ceil(3*cols/4),1);
    tempListB=oriPic(i,floor(cols/4):ceil(3*cols/4),1);
    if all(round(tempListR-mean(tempListR))==0)&&all(tempListR==tempListG)&&all(tempListR==tempListB)
        oriPic(i,:,:)=[];
    else
        break;
    end
end
oriPic=oriPic(end:-1:1,:,:);
for i=size(oriPic,1):-1:1
    tempListR=oriPic(i,floor(cols/4):ceil(3*cols/4),1);
    tempListG=oriPic(i,floor(cols/4):ceil(3*cols/4),1);
    tempListB=oriPic(i,floor(cols/4):ceil(3*cols/4),1);
    if all(round(tempListR-mean(tempListR))==0)&&all(tempListR==tempListG)&&all(tempListR==tempListB)
        oriPic(i,:,:)=[];
    else
        break;
    end
end
oriPic=oriPic(end:-1:1,:,:);
% =========================================================================
if ~exist('result','dir')
   mkdir('result');
end

for i=1:6
    resultPic=createCubeMapFace(oriPic,i,500,500);
    figure(i)
    imshow(resultPic)
    imwrite(resultPic,['result\',num2str(i),'.jpg'])
end



% =========================================================================
function resultPic=createCubeMapFace(oriPic,id,height,width)
    [M,N,~]=size(oriPic);
    resultPic=zeros([height,width,3]);
    an=sin(pi/4);
    ak=cos(pi/4);
    
    faceTransform=[0,0;
               pi/2,0;
               pi,0;
               -pi/2,0;
               0,-pi/2;
               0,pi];
    ftu=faceTransform(id,1);
    ftv=faceTransform(id,2);

    for y=0:height-1
        for x=0:width-1
            nx=y/height-0.5;
            ny=x/width-0.5;

            nx=nx*2*an;
            ny=ny*2*an;

            if (ftv == 0)
                u=atan2(nx, ak);
                v=atan2(ny*cos(u),ak);
                u=u+ftu;
            elseif(ftv>0)
                d=sqrt(nx*nx+ny*ny);
                v=pi/2-atan2(d,ak);
                u=atan2(ny,nx);
            else
                d=sqrt(nx*nx+ny*ny);
                v=-pi/2+atan2(d,ak);
                u=atan2(-ny,nx);
            end

            u=u/(pi);
            v=v/(pi/2);

            while(v<-1)
                v=v+2;
                u=u+1;
            end
            while(v>1)
                v=v-2;
                u=u+1;
            end
            while(u<-1)
                u=u+2;
            end
            while(u>1)
                u=u-2;
            end
            u=u/2+0.5;
            v=v/2+0.5;

            u=u*(N-1)+1;
            v=v*(M-1)+1;
            
            fv=floor(v);fv1=floor(v)+1;pv=v-fv;fv1(fv1>M)=M;
            fu=floor(u);fu1=floor(u)+1;pu=u-fu;fu1(fu1>N)=N;
            resultPic(x+1,y+1,:)=double(oriPic(fv,fu,:)).*(1-pv).*(1-pu)+...
                                 double(oriPic(fv1,fu,:)).*(pv).*(1-pu)+...
                                 double(oriPic(fv,fu1,:)).*(1-pv).*(pu)+...
                                 double(oriPic(fv1,fu1,:)).*(pv).*(pu);
        end
    end
    resultPic=uint8(resultPic);
end
end

1.4 其他几组切割结果

图片源自:https://www.cgmodel.com/article/9004.html

MATLAB 全景图切割及盒图显示的实现步骤
MATLAB 全景图切割及盒图显示的实现步骤
MATLAB 全景图切割及盒图显示的实现步骤
MATLAB 全景图切割及盒图显示的实现步骤
MATLAB 全景图切割及盒图显示的实现步骤
MATLAB 全景图切割及盒图显示的实现步骤

part2 盒图展示

2.1 曲面绘制

使用surf绘制各个曲面后,并为各个曲面贴图:

for i=1:6
    oriPic.(['p',num2str(i)])=imread(['result\',num2str(i),'.jpg']);   
end
[rows,cols,~]=size(oriPic.p1);
[baseXY,baseZ]=meshgrid(1:cols,rows:-1:1);

ax=gca;hold(ax,'on')


surf(baseXY(:,end:-1:1)-(1+rows)/2,-(rows-1)./2.*ones(size(baseXY)),baseZ,'CData',oriPic.p1,'EdgeColor','none','FaceColor','interp')
surf(-(rows-1)./2.*ones(size(baseXY)),baseXY-(1+rows)/2,baseZ,'CData',oriPic.p2,'EdgeColor','none','FaceColor','interp')
surf(baseXY-(1+rows)/2,(rows-1)./2.*ones(size(baseXY)),baseZ,'CData',oriPic.p3,'EdgeColor','none','FaceColor','interp')
surf((rows-1)./2.*ones(size(baseXY)),baseXY(:,end:-1:1)-(1+rows)/2,baseZ,'CData',oriPic.p4,'EdgeColor','none','FaceColor','interp')
surf(baseXY'-(1+rows)/2,baseXY-(1+rows)/2,ones(size(baseXY)),'CData',oriPic.p6(end:-1:1,end:-1:1,:),'EdgeColor','none','FaceColor','interp')
surf(baseXY'-(1+rows)/2,baseXY-(1+rows)/2,rows-1+ones(size(baseXY)),'CData',oriPic.p5(:,end:-1:1,:),'EdgeColor','none','FaceColor','interp')

MATLAB 全景图切割及盒图显示的实现步骤
MATLAB 全景图切割及盒图显示的实现步骤

2.2 视角调整

通过设置axes属性将视角调整至盒子里面

ax=axes('parent',fig,'position',[-0.45 -0.45 1.9 1.9]);hold(ax,'on')
ax.ZLim=[0,rows+1];
ax.XLim=[0-(1+rows)/2,rows+1-(1+rows)/2];
ax.YLim=[0-(1+rows)/2,rows+1-(1+rows)/2];
ax.Color=[0 0 0];
ax.CameraPosition=[0,0,rows/2];
ax.CameraPositionMode='manual';
ax.DataAspectRatio=[1,1,1];
ax.DataAspectRatioMode='manual';
ax.Projection='perspective';
ax.CameraTargetMode='manual';
ax.CameraViewAngle = 7;
ax.View=[-2.7391 90.0000];
ax.CameraTarget=[0 0 (rows-1)/2];
ax.Toolbar.Visible='on';

运行后点击那个三位旋转按钮即可开始漫游

MATLAB 全景图切割及盒图显示的实现步骤

此时的盒图是无缝隙版本,有缝隙版放在后面

MATLAB 全景图切割及盒图显示的实现步骤

2.3 完整代码

无缝隙版:

function showBox
for i=1:6
    oriPic.(['p',num2str(i)])=imread(['result\',num2str(i),'.jpg']);   
end
[rows,cols,~]=size(oriPic.p1);
[baseXY,baseZ]=meshgrid(1:cols,rows:-1:1);

fig=figure('units','pixels','position',[300 80 500 500],...
                       'Numbertitle','off','menubar','none','resize','off',...
                       'name','box');
                   

ax=axes('parent',fig,'position',[-0.45 -0.45 1.9 1.9]);hold(ax,'on')
ax.ZLim=[0,rows+1];
ax.XLim=[0-(1+rows)/2,rows+1-(1+rows)/2];
ax.YLim=[0-(1+rows)/2,rows+1-(1+rows)/2];
ax.Color=[0 0 0];
ax.CameraPosition=[0,0,rows/2];
ax.CameraPositionMode='manual';
ax.DataAspectRatio=[1,1,1];
ax.DataAspectRatioMode='manual';
ax.Projection='perspective';
ax.CameraTargetMode='manual';
ax.CameraViewAngle = 7;
ax.View=[-2.7391 90.0000];
ax.CameraTarget=[0 0 (rows-1)/2];
ax.Toolbar.Visible='on';




surf(baseXY(:,end:-1:1)-(1+rows)/2,-(rows-1)./2.*ones(size(baseXY)),baseZ,'CData',oriPic.p1,'EdgeColor','none','FaceColor','interp')
surf(-(rows-1)./2.*ones(size(baseXY)),baseXY-(1+rows)/2,baseZ,'CData',oriPic.p2,'EdgeColor','none','FaceColor','interp')
surf(baseXY-(1+rows)/2,(rows-1)./2.*ones(size(baseXY)),baseZ,'CData',oriPic.p3,'EdgeColor','none','FaceColor','interp')
surf((rows-1)./2.*ones(size(baseXY)),baseXY(:,end:-1:1)-(1+rows)/2,baseZ,'CData',oriPic.p4,'EdgeColor','none','FaceColor','interp')
surf(baseXY'-(1+rows)/2,baseXY-(1+rows)/2,ones(size(baseXY)),'CData',oriPic.p6(end:-1:1,end:-1:1,:),'EdgeColor','none','FaceColor','interp')
surf(baseXY'-(1+rows)/2,baseXY-(1+rows)/2,rows-1+ones(size(baseXY)),'CData',oriPic.p5(:,end:-1:1,:),'EdgeColor','none','FaceColor','interp')

end

MATLAB 全景图切割及盒图显示的实现步骤

有缝隙版:

function showBox2
for i=1:6
    oriPic.(['p',num2str(i)])=imread(['result\',num2str(i),'.jpg']);   
end
[rows,cols,~]=size(oriPic.p1);
[baseXY,baseZ]=meshgrid(1:cols,rows:-1:1);

fig=figure('units','pixels','position',[300 80 500 500],...
                       'Numbertitle','off','menubar','none','resize','off',...
                       'name','box');
                   

ax=axes('parent',fig,'position',[-0.45 -0.45 1.9 1.9]);hold(ax,'on')
ax.ZLim=[0,rows+1];
ax.XLim=[0-(1+rows)/2,rows+1-(1+rows)/2];
ax.YLim=[0-(1+rows)/2,rows+1-(1+rows)/2];
ax.Color=[0 0 0];
ax.CameraPosition=[0,0,rows/2];
ax.CameraPositionMode='manual';
ax.DataAspectRatio=[1,1,1];
ax.DataAspectRatioMode='manual';
ax.Projection='perspective';
ax.CameraTargetMode='manual';
ax.CameraViewAngle = 7;
ax.View=[-2.7391 90.0000];
ax.CameraTarget=[0 0 (rows+1)/2];
ax.Toolbar.Visible='on';




surf(baseXY(:,end:-1:1)-rows/2,-rows./2.*ones(size(baseXY)),baseZ,'CData',oriPic.p1,'EdgeColor','none','FaceColor','interp')
surf(-rows./2.*ones(size(baseXY)),baseXY-(1+rows)/2,baseZ,'CData',oriPic.p2,'EdgeColor','none','FaceColor','interp')
surf(baseXY-(1+rows)/2,rows./2.*ones(size(baseXY)),baseZ,'CData',oriPic.p3,'EdgeColor','none','FaceColor','interp')
surf(rows./2.*ones(size(baseXY)),baseXY(:,end:-1:1)-(1+rows)/2,baseZ,'CData',oriPic.p4,'EdgeColor','none','FaceColor','interp')
surf(baseXY'-(1+rows)/2,baseXY-(1+rows)/2,zeros(size(baseXY)),'CData',oriPic.p6(end:-1:1,end:-1:1,:),'EdgeColor','none','FaceColor','interp')
surf(baseXY'-(1+rows)/2,baseXY-(1+rows)/2,rows+ones(size(baseXY)),'CData',oriPic.p5(:,end:-1:1,:),'EdgeColor','none','FaceColor','interp')

end

MATLAB 全景图切割及盒图显示的实现步骤
MATLAB 全景图切割及盒图显示的实现步骤

以上就是MATLAB 全景图切割及盒图显示的详细内容,更多关于MATLAB 全景图的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python的绘图工具matplotlib使用实例
Jul 03 Python
python使用多线程不断刷新网页的方法
Mar 31 Python
python开发之list操作实例分析
Feb 22 Python
Python极简代码实现杨辉三角示例代码
Nov 15 Python
Python深入06——python的内存管理详解
Dec 07 Python
python+opencv轮廓检测代码解析
Jan 05 Python
基于python历史天气采集的分析
Feb 14 Python
深入理解Django-Signals信号量
Feb 19 Python
python 用户交互输入input的4种用法详解
Sep 24 Python
Python Pandas 转换unix时间戳方式
Dec 07 Python
linux 下selenium chrome使用详解
Apr 02 Python
jenkins+python自动化测试持续集成教程
May 12 Python
使用pandas或numpy处理数据中的空值(np.isnan()/pd.isnull())
May 14 #Python
PyQt5爬取12306车票信息程序的实现
python flask框架快速入门
如何将numpy二维数组中的np.nan值替换为指定的值
May 14 #Python
使用numpy nonzero 找出非0元素
May 14 #Python
Python机器学习之KNN近邻算法
May 14 #Python
Python爬虫基础讲解之请求
You might like
解析thinkphp中的导入文件标签
2013/06/20 PHP
使用php计算排列组合的方法
2013/11/13 PHP
实现在同一方法中获取当前方法中新赋值的session值解决方法
2014/06/26 PHP
PHP编程计算日期间隔天数的方法
2017/04/26 PHP
PHP中quotemeta()函数的用法讲解
2019/04/04 PHP
jQuery选择头像并实时显示的代码
2010/06/27 Javascript
JS获取各种宽度、高度的简单介绍
2014/12/19 Javascript
jQuery图片特效插件Revealing实现拉伸放大
2015/04/22 Javascript
简介JavaScript中用于处理正切的Math.tan()方法
2015/06/15 Javascript
jQuery图片轮播滚动切换代码分享
2020/04/20 Javascript
jQuery实现滚动条滚动到子元素位置(方便定位)
2017/01/08 Javascript
js实现贪吃蛇小游戏(容易理解)
2017/01/22 Javascript
详解nodejs异步I/O和事件循环
2017/06/07 NodeJs
JavaScript 获取元素在父节点中的下标(推荐)
2017/06/28 Javascript
node.js + socket.io 实现点对点随机匹配聊天
2017/06/30 Javascript
Vue组件模板形式实现对象数组数据循环为树形结构(实例代码)
2017/07/31 Javascript
微信小程序使用checkbox显示多项选择框功能【附源码下载】
2017/12/11 Javascript
微信小程序时间标签和时间范围的联动效果
2019/02/15 Javascript
Vue 实现从小到大的横向滑动效果详解
2019/10/16 Javascript
python实现带错误处理功能的远程文件读取方法
2015/04/29 Python
Python字符串转换成浮点数函数分享
2015/07/24 Python
在MAC上搭建python数据分析开发环境
2016/01/26 Python
如何分离django中的媒体、静态文件和网页
2019/11/12 Python
Python @property及getter setter原理详解
2020/03/31 Python
PyQt5.6+pycharm配置以及pyinstaller生成exe(小白教程)
2020/06/02 Python
美国最值得信赖的宠物药房:Allivet
2019/03/23 全球购物
iHerb俄罗斯:维生素、补品和天然产品
2020/07/09 全球购物
Java中的类包括什么内容?设计时要注意哪些方面
2012/05/23 面试题
工商企业管理实习自我鉴定
2013/12/04 职场文书
一年级数学教学反思
2014/02/01 职场文书
2014年基层党组织公开承诺书
2014/03/29 职场文书
离婚财产分隔协议书
2014/10/23 职场文书
2014年物流工作总结
2014/11/25 职场文书
无罪辩护词范文
2015/05/21 职场文书
golang switch语句的灵活写法介绍
2021/05/06 Golang
python 安全地删除列表元素的方法
2022/03/16 Python