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、增強現實場景圖像的保存


這個使用傳統的文件保存方法就可以。

展示幾幅我做出來的效果:



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM