part1 全景图切割

原图:

切割效果:


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

1.1 边缘剔除

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

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

oriPic=imread('test.hdr');
[rows,cols,~]=size(oriPic);for i=cols:-1:1tempListR=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,:)=[];elsebreak;end
end
oriPic=oriPic(:,end:-1:1,:);
for i=size(oriPic,2):-1:1tempListR=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,:)=[];elsebreak;end
end
oriPic=oriPic(:,end:-1:1,:);
for i=rows:-1:1tempListR=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,:,:)=[];elsebreak;end
end
oriPic=oriPic(end:-1:1,:,:);
for i=size(oriPic,1):-1:1tempListR=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,:,:)=[];elsebreak;end
end
oriPic=oriPic(end:-1:1,:,:);

1.2 图像裁剪

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


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

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

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

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

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

主要函数代码:

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-1for x=0:width-1nx=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);elsed=sqrt(nx*nx+ny*ny);v=-pi/2+atan2(d,ak);u=atan2(-ny,nx);endu=u/(pi);v=v/(pi/2);while(v<-1)v=v+2;u=u+1;endwhile(v>1)v=v-2;u=u+1;endwhile(u<-1)u=u+2;endwhile(u>1)u=u-2;endu=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);endendresultPic=uint8(resultPic);
end

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

if ~exist('result','dir')mkdir('result');
endfor i=1:6resultPic=createCubeMapFace(oriPic,i,500,500);figure(i)imshow(resultPic)imwrite(resultPic,['result\',num2str(i),'.png'])
end

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

1.3 完整代码

function panoramic2box
oriPic=imread('889027-884424860.jpg');
[rows,cols,~]=size(oriPic);for i=cols:-1:1tempListR=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,:)=[];elsebreak;end
end
oriPic=oriPic(:,end:-1:1,:);
for i=size(oriPic,2):-1:1tempListR=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,:)=[];elsebreak;end
end
oriPic=oriPic(:,end:-1:1,:);
for i=rows:-1:1tempListR=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,:,:)=[];elsebreak;end
end
oriPic=oriPic(end:-1:1,:,:);
for i=size(oriPic,1):-1:1tempListR=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,:,:)=[];elsebreak;end
end
oriPic=oriPic(end:-1:1,:,:);
% =========================================================================
if ~exist('result','dir')mkdir('result');
endfor i=1:6resultPic=createCubeMapFace(oriPic,i,500,500);figure(i)imshow(resultPic)imwrite(resultPic,['result\',num2str(i),'.png'])
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-1for x=0:width-1nx=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);elsed=sqrt(nx*nx+ny*ny);v=-pi/2+atan2(d,ak);u=atan2(-ny,nx);endu=u/(pi);v=v/(pi/2);while(v<-1)v=v+2;u=u+1;endwhile(v>1)v=v-2;u=u+1;endwhile(u<-1)u=u+2;endwhile(u>1)u=u-2;endu=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);endendresultPic=uint8(resultPic);
end
end

1.4 其他几组切割结果

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





part2 盒图展示

2.1 曲面绘制

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

for i=1:6oriPic.(['p',num2str(i)])=imread(['result\',num2str(i),'.png']);
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')


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';

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

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

2.3 完整代码

无缝隙版:

function showBox
for i=1:6oriPic.(['p',num2str(i)])=imread(['result\',num2str(i),'.png']);
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


有缝隙版:

function showBox2
for i=1:6oriPic.(['p',num2str(i)])=imread(['result\',num2str(i),'.png']);
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 全景图切割及盒图显示相关推荐

  1. matlab: 盒图---boxplot

    盒图(boxplot) 盒图是在1977年由美国的统计学家约翰·图基(John Tukey)发明的.它由五个数值点组成:最小值(min),下四分位数(Q1),中位数(median),上四分位数(Q3) ...

  2. 箱形图或盒图Boxplot以及matlab实现

    箱形图(英文:Box plot),又称为盒须图.盒式图.盒状图或箱线图,是一种用作显示一组数据分散情况资料的统计图.因型状如箱子而得名.在各种领域也经常被使用,常见于品质管理,快速识别异常值. 箱形图 ...

  3. MATLAB可视化实战系列(二十四)-三维可视化如何利用圆锥图显示向量场?

    前言 在物理学中,我们学习了矢量,知道了磁力线等矢量图.如何画出优美的矢量场图呢?科学计算软件matlab可以很容易地绘制出矢量场图.下面跟随博主一起来看下matlab高级可视化内容,如何利用圆锥图显 ...

  4. Boxplot(盒图)

    今天看到一个程序(matlab版本),里面有个函数叫"boxplot",没见过,查了些资料,找到一篇不错的文章,贴在这供大家参考. 地址:http://blog.renren.co ...

  5. python安装盒怎么打开_python盒图

    广告关闭 腾讯云11.11云上盛惠 ,精选热门产品助力上云,云服务器首年88元起,买的越多返的越多,最高返5000元! python.print(a)print(a)print(a)print(a)p ...

  6. semilogx 多条曲线_怎么让两个指数在一个坐标,matlab里怎样一个坐标上显示多个曲线,而且横轴要用指数形式的?谢谢...

    Q1:matlab里怎样一个坐标上显示多个曲线,而且横轴要用指数形式的?谢谢 多个纵轴数组分别是y1,y2,y3,横轴数组为x 命令为: semilogx(x,y1,x,y2,x,y3) 完了 Q2: ...

  7. 爆料图显示iPhone 14 Pro及Max机身更厚 摄像头凸起也更多

    近日,据国外媒体报道,在苹果的春季新品发布会举行之后,分析师和研究机构的重点也就转移到了苹果秋季新品发布会将推出的新品上,尤其是下半年将推出的iPhone 14系列智能手机,有关这一系列智能手机的消息 ...

  8. matlab数据显示格式,如何使用MATLAB以图形格式记录和显示数据

    图形表示形式总是有助于可视化数据,并且通过查看趋势和模式非常容易.有很多软件可以根据输入值绘制图形,但是在嵌入式系统中,MATLAB是最受欢迎的软件之一,它不仅可以以图形形式显示结果,而且可以轻松地与 ...

  9. matplotlib 柱状图、饼图;直方图、盒图

    matplotlib 柱状图.饼图:直方图.盒图 #-*- coding: utf-8 -*-import matplotlib.pyplot as plt import numpy as np im ...

最新文章

  1. 商汤提基于贪心超网络的One-Shot NAS,达到最新SOTA | CVPR 2020
  2. mysql ignore index_mysql use index、ignore index、force index用法
  3. CSS3 filter:drop-shadow滤镜与box-shadow区别
  4. Speex for Android
  5. Map、Set、List简介
  6. IOS设计模式的六大设计原则之开放-关闭原则(OCP,Open-Close Principle)
  7. footer固定到底部
  8. 注意2018年数据中心的这5大发展趋势
  9. 信息系统项目管理师-项目整体、收尾、变更管理考点笔记
  10. 计算机桌面上的声音图标没了怎么办,Win7电脑右下角声音图标不见了怎么办?...
  11. Symbian和C++ SDK开发入门之应用程序
  12. 大数据分析的作用有哪些
  13. 用vue实时监听多个用户扫描二维码
  14. java 获取jsessionid_如何从JSESSIONID加载Java HttpSession?
  15. 这5种数据挖掘技术,大数据玩的贼溜!
  16. python合并word单元格_使用win32com合并和取消合并单元格
  17. 五猴分桃python_猴子分桃问题 | 学步园
  18. 手写tomcat socket closed_ipad pencil2019防误触电容笔苹果air3触屏控手写笔mini5绘画202010元优惠券券后价65元...
  19. (自适应手机端)pbootcms响应式企业通用网站模板
  20. Linux学习笔记 16(存储设备管理)

热门文章

  1. Android 深入理解 ANR 触发原理:Service
  2. Android targetSdkVersion从23升级到26适配指南
  3. (1-10总结)微信点餐项目-第一阶段总结
  4. 用Python把B站视频弹幕爬下来,绘制词云图看看大家最关心什么!
  5. 神了!有人用一个项目把23种设计模式与六大原则融会贯通了
  6. 百度飞桨亮相2019 AIIA,四大领先技术剑指落地引开发者点赞
  7. 大二Web课程设计 HTML+CSS制作苹果商城网站 Apple商城 8个页面
  8. 数字孪生医院:一个围绕着智慧医院决策的建模、管理和行动闭环的全新方式...
  9. Windows磁盘管理(Raid)
  10. 你的收藏夹里,有哪些神奇有趣的小网站?