• Android AR场景拍照技术实现(有关键源代码)


    ARVR技术交流群:129340649

    欢迎增加。


    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、增强现实场景图像的保存


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

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


  • 相关阅读:
    ASP.NET页面打印技术的总结
    js传递中文参数的url到asp(jscript)解释得到的中文参数为乱码的解决方法
    header的用法(PHP)
    oracle 11g road(/dev/shm需注意)
    mysql 主从同步 Error 'Out of range value for column的问题
    linux shell 过滤特殊字符开始的行
    Oracle穿越incarnation恢复数据
    多普达A6388刷机2.3
    【忽悠普通人用】隐藏文件夹的方法
    电脑同时使用双网卡实现方法
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/6834484.html
Copyright © 2020-2023  润新知