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 相关文章推荐
[原创]使用豆瓣提供的国内pypi源
Jul 02 Python
在Python中给Nan值更改为0的方法
Oct 30 Python
Python面向对象之类和实例用法分析
Jun 08 Python
python实现动态数组的示例代码
Jul 15 Python
Django 迁移、操作数据库的方法
Aug 02 Python
浅谈Python_Openpyxl使用(最全总结)
Sep 05 Python
python使用socket实现的传输demo示例【基于TCP协议】
Sep 24 Python
Python OpenCV去除字母后面的杂线操作
Jul 05 Python
Django如何实现密码错误报错提醒
Sep 04 Python
python实战之一步一步教你绘制小猪佩奇
Apr 22 Python
python中opencv实现图片文本倾斜校正
Jun 11 Python
利用Matlab绘制各类特殊图形的实例代码
Jul 16 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
提升PHP执行速度全攻略(上)
2006/10/09 PHP
PHP exif扩展方法开启详解
2014/07/28 PHP
在Windows XP下安装Apache+MySQL+PHP环境
2015/02/22 PHP
php递归删除指定文件夹的方法小结
2015/04/20 PHP
windows server 2008/2012安装php iis7 mysql环境搭建教程
2016/06/30 PHP
利用PHP抓取百度阅读的方法示例
2016/12/18 PHP
ThinkPHP 5.1 跨域配置方法
2019/10/11 PHP
javascript操作文本框readOnly
2007/05/15 Javascript
javascript flash下fromCharCode和charCodeAt方法使用说明
2008/01/12 Javascript
prototype Element学习笔记(Element篇三)
2008/10/26 Javascript
JavaScript中String.match()方法的使用详解
2015/06/06 Javascript
javascript合并表格单元格实例代码
2016/01/03 Javascript
一波JavaScript日期判断脚本分享
2016/03/06 Javascript
jQuery 实现评论等级好评差评特效
2016/05/06 Javascript
JS实现搜索框文字可删除功能
2016/12/28 Javascript
微信小程序手势操作之单触摸点与多触摸点
2017/03/10 Javascript
nuxt静态部署打包相对路径操作
2020/11/06 Javascript
[55:11]完美世界DOTA2联赛PWL S2 SZ vs LBZS 第一场 11.26
2020/11/30 DOTA
Python 条件判断的缩写方法
2008/09/06 Python
python编写网页爬虫脚本并实现APScheduler调度
2014/07/28 Python
浅析python中的分片与截断序列
2016/08/09 Python
python 接口_从协议到抽象基类详解
2017/08/24 Python
python3 发送任意文件邮件的实例
2018/01/23 Python
python 获取等间隔的数组实例
2019/07/04 Python
Python Django view 两种return的实现方式
2020/03/16 Python
魔幻般冒泡背景的CSS3按钮动画
2016/02/27 HTML / CSS
HTML5中使用json对象的实例代码
2018/09/10 HTML / CSS
Hotels.com中国区:好订网
2016/08/18 全球购物
欧洲顶级的童装奢侈品购物网站:Bambini Fashion(面向全球)
2018/04/24 全球购物
芬兰设计商店美国:Finnish Design Shop US
2019/03/25 全球购物
涉外文秘个人求职的自我评价
2013/10/07 职场文书
党风廉设责任书
2014/04/16 职场文书
暑期学习心得体会
2014/09/02 职场文书
认错检讨书
2014/10/02 职场文书
计生个人工作总结
2015/02/28 职场文书
go select编译期的优化处理逻辑使用场景分析
2021/06/28 Golang