热门标签 | HotTags
当前位置:  开发笔记 > 前端 > 正文

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

本文给大家分两部分介绍,第一部分通过图文的形式给大家介绍了全景图切割的代码,第二部分给大家介绍了盒图展示效果的实现代码,对MATLAB全景图切割相关知识感兴趣的朋友,跟随小编一起看看吧

part1 全景图切割

原图:

在这里插入图片描述

切割效果:

在这里插入图片描述
在这里插入图片描述

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

在这里插入图片描述

1.1 边缘剔除

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

在这里插入图片描述

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

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 图像裁剪

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

在这里插入图片描述
在这里插入图片描述

这部分其实已经有较为成熟的原理和代码:
代码参考: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-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]分别对应图片[右,后,左,前,上,下]

在这里插入图片描述

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

在这里插入图片描述
在这里插入图片描述

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: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

在这里插入图片描述

有缝隙版:

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 全景图的资料请关注其它相关文章!


推荐阅读
  • 页面预渲染适用于主要包含静态内容的页面。对于依赖大量API调用的动态页面,建议采用SSR(服务器端渲染),如Nuxt等框架。更多优化策略可参见:https://github.com/HaoChuan9421/vue-cli3-optimization ... [详细]
  • 将XML数据迁移至Oracle Autonomous Data Warehouse (ADW)
    随着Oracle ADW的推出,数据迁移至ADW成为业界关注的焦点。特别是XML和JSON这类结构化数据的迁移需求日益增长。本文将通过一个实际案例,探讨如何高效地将XML数据迁移至ADW。 ... [详细]
  • 本文探讨了在AspNetForums平台中实施基于角色的权限控制系统的方法,旨在为不同级别的用户提供合适的访问权限,确保系统的安全性和可用性。 ... [详细]
  • 本文总结了 #define 在 C/C++ 编程中的多种用途和技巧,包括定义常量、函数、宏以及条件编译等,并提供了详细的示例和注意事项。 ... [详细]
  • 在开发过程中,使用 HTML 的 `` 标签进行视频播放时,可能会遇到视频路径更新但浏览器仍播放缓存中的旧视频的问题。本文将介绍一种有效的方法来解决这一问题。 ... [详细]
  • 本文详细介绍了如何使用SQL*Plus连接Oracle数据库以及使用MySQL客户端连接MySQL数据库的方法,包括基本命令和具体操作步骤。 ... [详细]
  • 如何寻找程序员的兼职机会
    随着远程工作的兴起,越来越多的程序员开始寻找灵活的兼职工作机会。本文将介绍几个适合程序员、设计师、翻译等专业人士的在线平台,帮助他们找到合适的兼职项目。 ... [详细]
  • 一、使用Microsoft.Office.Interop.Excel.DLL需要安装Office代码如下:2publicstaticboolExportExcel(S ... [详细]
  • 汇编语言标识符和表达式(四)(表达式与符号定义语句)
    7、表达式表达式是程序设计课程里的一个重要的基本概念,它可由运算符、操作符、括号、常量和一些符号连在一起的式子。在汇编语言中,表达式分为:数值表达式和地址表达式。(1)进制伪指令R ... [详细]
  • 本文针对HDU 1042 N! 问题提供详细的解析和代码实现。题目要求计算给定整数N(0 ≤ N ≤ 10000)的阶乘N!。文章不仅提供了算法思路,还附上了C++语言的具体实现。 ... [详细]
  • 本文介绍了使用Python和C语言编写程序来计算一个给定数值的平方根的方法。通过迭代算法,我们能够精确地得到所需的结果。 ... [详细]
  • HTML 表格与列表标签详解
    本文详细介绍了HTML中的表格标签和列表标签的使用方法,包括如何创建表格的不同部分(如标题、头部、主体和脚部),以及如何利用这些标签进行数据展示和布局设计。 ... [详细]
  • 本文介绍了用户界面(User Interface, UI)的基本概念,以及在iOS应用程序中UIView及其子类的重要性和使用方式。文章详细探讨了UIView如何作为用户交互的核心组件,以及它与其他UI控件和业务逻辑的关系。 ... [详细]
  • 本文介绍了如何在 Django 项目中集成和配置 REST Framework,以支持 API 开发。通过在 settings.py 文件中注册 'rest_framework' 应用,可以轻松启用这一功能。 ... [详细]
  • 本文探讨了线性表中元素的删除方法,包括顺序表和链表的不同实现策略,以及这些策略在实际应用中的性能分析。 ... [详细]
author-avatar
黄自安_725
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有