拍摄AR场景技术实现(有关键源码)

AR场景往往给别人留下的印象深刻,如果模型做的炫丽一点,效果将会更好。那么如何保存这一美好的情景呢?这篇文章将教你如何实现AR场景的拍摄以及永久保存。

1、AR虚实融合场景图层的分析

一个简单的AR场景,在任何系统下的布局方式都不外乎上图所示的类型。本文以在Android系统下的增强现实为例。

虚实融合场景图层都是这种架构,GLSurfaceView用于绘制三维虚拟模型,SurfaceView是显示真实场景视频帧画面,如果使用OpenCV进行图像获取的话,就使用SurfaceView的子类CameraBridgeViewBase。这些布局类的作用应该分的比较清楚。

2、场景获取思路

首先由于真实场景的视频帧画面和三维虚拟模型不在同一个图层上,我们需要分别获取不同图层上的图像,再将它们转换成位图,最后拼合成一张位图图片就可以了。但是传统的拍照方式只能获取真实的场景,无法获取OpenGL渲染的画面。这里就是用传统的方式获取视频图像即可,主要要解决GLSurfaceView上的三维模型。怎么样将三维虚拟模型转化成一张图片?

3、视频帧图像的获取

在Android系统中,

①使用Camera的情况:

参见这里的方法:Android拍照的两种方式http://blog.csdn.net/napolun007/article/details/6103307或者参见官网:http://developer.android.com/training/camera/photobasics.html②使用OpenCV的情况:

使用OpenCV中的Utils.matToBitmap(Mat mat, Bitmap bmp),将获取的视频帧转换成Bitmap就可以了。

4、OpenGL渲染模型转化成位图

主要是将OpenGL绘制的图像转化成像素数据。了解下glReadPixels参数的含义:

void glReadPixels( GLint x, GLint y, GLsizei width,GLsizei height, GLenum format, GLenum type, GLvoid *pixels) ;

前面几个参数指定读取的位置尺寸以及格式, 最后一个参数用来返回结果, 所以像素数据自然是读到pixels中。最后的方法代码如下图所示:

// 保存GL绘制的图形
public static Bitmap saveGLBitmap(int width_surface, int height_surface)
{
// isSave = false;
int w = width_surface;
int h = height_surface;

Log.i("hari", "w:" + w + "-----h:" + h);

int b[] = new int[(int) (w * h)];
int bt[] = new int[(int) (w * h)];
IntBuffer buffer = IntBuffer.wrap(b);
buffer.position(0);
GLES20.glReadPixels(0, 0, w, h, GLES20.GL_RGBA,
GLES20.GL_UNSIGNED_BYTE, buffer);
for (int i = 0; i < h; i++) {
/**
* 由于OpenGL与Android的Bitmap不兼容,这里需要进行一些校正
*/
for (int j = 0; j < w; j++) {
int pix = b[i * w + j];
int pb = (pix >> 16) & 0xff;
int pr = (pix << 16) & 0x00ff0000;
int pix1 = (pix & 0xff00ff00) | pr | pb;
bt[(h - i - 1) * w + j] = pix1;
}
}
Bitmap inBitmap = null;
if (inBitmap == null || !inBitmap.isMutable()
|| inBitmap.getWidth() != w
|| inBitmap.getHeight() != h) {
inBitmap = Bitmap.createBitmap(w, h,
Bitmap.Config.ARGB_8888);
}
// Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
inBitmap.copyPixelsFromBuffer(buffer);
// return inBitmap ;
// return Bitmap.createBitmap(bt, w, h,
// Bitmap.Config.ARGB_8888);
inBitmap = Bitmap.createBitmap(bt, w, h,
Bitmap.Config.ARGB_8888);

ByteArrayOutputStream bos = new ByteArrayOutputStream();
inBitmap.compress(CompressFormat.PNG, 90, bos);
byte[] bitmapdata = bos.toByteArray();
ByteArrayInputStream fis = new ByteArrayInputStream(bitmapdata);

// final Calendar c=Calendar.getInstance();
// long mytimestamp=c.getTimeInMillis();
// String timeStamp=String.valueOf(mytimestamp);
// String myfile="hari"+timeStamp+".jpeg";

File dir_image = new File(Environment.getExternalStorageDirectory()
+ File.separator + "printerscreenshots");
dir_image.mkdirs();

try {
File tmpFile = new File(dir_image + "/"
+ System.currentTimeMillis() + ".png");
FileOutputStream fos = new FileOutputStream(tmpFile);

byte[] buf = new byte[1024];
int len;
while ((len = fis.read(buf)) > 0) {
fos.write(buf, 0, len);
}
fis.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return inBitmap;
}

5、图像的拼合

这个比较简单,就是将两个位图拼合成一幅位图,可以使用Canvas绘图板进行绘制。

public static Bitmap combineBitmap(Bitmap background, Bitmap foreground) {

if (background == null) {
return null;
}

int bgWidth = background.getWidth();

int bgHeight = background.getHeight();

int fgWidth = foreground.getWidth();

int fgHeight = foreground.getHeight();

Bitmap newmap = Bitmap

.createBitmap(bgWidth, bgHeight, Config.ARGB_8888);

Canvas canvas = new Canvas(newmap);

canvas.drawBitmap(background, 0, 0, null);

canvas.drawBitmap(foreground, (bgWidth - fgWidth) / 2,

(bgHeight - fgHeight) / 2, null);

canvas.save(Canvas.ALL_SAVE_FLAG);

canvas.restore();

return newmap;

}

6、增强现实场景图像的保存

这个使用传统的文件保存方法即可。

展示几幅我做出来的效果:

拍摄AR场景技术实现(有关键源码),布布扣,bubuko.com

时间: 2024-12-21 10:10:44

拍摄AR场景技术实现(有关键源码)的相关文章

Cocos2d-X3.0 刨根问底(九)----- 场景切换(TransitionScene)源码分析

上一章我们分析了Scene与Layer相关类的源码,对Cocos2d-x的场景有了初步了解,这章我们来分析一下场景变换TransitionScene源码. 直接看TransitionScene的定义 class CC_DLL TransitionScene : public Scene { public: /** Orientation Type used by some transitions */ enum class Orientation { /// An horizontal orie

DotNetOpenAuth Part 1 : Authorization 验证服务实现及关键源码解析

DotNetOpenAuth 是 .Net 环境下OAuth 开源实现框架.基于此,可以方便的实现 OAuth 验证(Authorization)服务.资源(Resource)服务.针对 DotNetOpenAuth,近期打算整理出三篇随笔: DotNetOpenAuth Part 1 : OAuth2 Authorization 验证服务实现及关键源码解析 DotNetOpenAuth Part 2 : OAuth2 Resource 资源服务实现及关键源码解析 DotNetOpenAuth 

Spark技术内幕:Worker源码与架构解析

首先通过一张Spark的架构图来了解Worker在Spark中的作用和地位: Worker所起的作用有以下几个: 1. 接受Master的指令,启动或者杀掉Executor 2. 接受Master的指令,启动或者杀掉Driver 3. 报告Executor/Driver的状态到Master 4. 心跳到Master,心跳超时则Master认为Worker已经挂了不能工作了 5. 向GUI报告Worker的状态 说白了,Worker就是整个集群真正干活的.首先看一下Worker重要的数据结构: v

SPRING技术内幕,Spring源码深度解析

 SPRING技术内幕,Spring源码深度解析 SPRING技术内幕:深入解析SPRING架构与设计原理(第2版)[带书签].pdf: http://www.t00y.com/file/78131650 Spring源码深度解析 [郝佳编著] sample.pdf: http://www.t00y.com/file/78131634 [jingshuishenliu.400gb.com]Spring Data.pdf: http://www.t00y.com/file/78256084 [

C++STL内存配置的设计思想与关键源码分析

说明:我认为要读懂STL中allocator部分的源码,并汲取它的思想,至少以下几点知识你要了解:operator new和operator delete.handler函数以及一点模板知识.否则,下面你很可能看不大明白,补充点知识再学习STL源码比较好. 下面会结合关键源码分析C++STL(SGI版本)的内存配置器设计思想.关键词既然是“思想”,所以重点也就呼之欲出了. 1.allocator的简短介绍 我阅读的源码是SGI公司的版本,也是看起来最清楚的版本,各种命名最容易让人看懂.alloc

Backbone设计思路和关键源码分析

一. Backbone的江湖地位: backbone作为一个老牌js框架为大规模前端开发提供了新的开发思路:前端MVC模式,这个模式也是前端开发演变过程中的一个重要里程碑,也为MVVM和Redux等开发思路奠定了夯实的基础,后来的react,vue无不是在backbone的影响下开创出来的经典模式.为什么这么说呢?我们先来回顾下Web前端开发的大概演变流程,本过程纯粹个人理解,抛砖引玉,共同探讨,如有偏差请看官指出错误: 1. 无前端:最早的网页就是HTML,还只是静态页面,当时的脚本含量极少甚

快餐刷卡消费之触摸屏实现(含关键源码)

本项目为连锁店餐饮系统.前台C#,服务器采用Java开发,oracle数据库:通过webservice实现前后台的交互,后台以提供服务的方式,供前端调用并进行数据库操作. 商家根据餐饮副食店实际情况提出了新的需求,希望能够通过在店内放置触摸屏的方式,使会员顾客能够以触摸屏的方式选择商品并放入自己的购物车,之后售货员只需要读取卡内的购物车信息即可刷卡消费,这样大大节约了顾客挑选商品的时间,使整个购物流程并行化程度提高.由于顾客消费的时间大多集中在早中晚,并行化会使店内的销售量显著提高. 经过一周的

sklearn中LinearRegression关键源码解读

问题的引入 我们知道,线性回归方程的参数,可以用梯度下降法求解,或者用正规方程求解. 那sklearn.linear_model.LinearRegression中,是不是可以指定求解方式呢?能不能从中获取梯度相关信息呢? 下面是线性回归最简单的用法. from sklearn import linear_model # Create linear regression object regr = linear_model.LinearRegression() # Train the model

iText生成PDF的关键源码分析

对于iText的学习,基本上都是来源于官网上的例子.这和我学习easyUI.jQuery的途径都是一致的. 这也再次证明了,想用好一个软件,官方提供的例子和文档都是最佳的学习资料. 因为对方是最了解这款软件的人,设计出来的demo当然是最有应用价值的~ 这里吐槽一下,iText的demo真难找,官网上反反复复找了好多次才找到,不知道大家是否和我一样,在这里给大家一个捷径. 下面就拿官网的例子来讲一讲,首先如何生成PDF? /** * 这也就是所有demo中最核心的代码 * Creates a P