android攝像頭獲取圖像——第三彈


                                        相機獲取圖像的格式問題
android中承認的格式的參考網址為 :http://developer.android.com/reference/android/graphics/ImageFormat.html);

並不是所有的android攝像機都支持這種格式,其中最為常用(android系統默認)的格式為:NV21格式;(所有相機都支持)。但是往往我們需要將這種格式轉化為其它的類型,以便於進行相關處理,最常見的就是rgb和jpeg類型,還有android中的BitMap 格式的圖像類型。NV21格式其實是一種YUV格式,相關格式的說明可參考網絡資料~,下面帖一下相關算法:

public void decodeToBitMap(byte[] data, Camera _camera) {
Size size = mCamera.getParameters().getPreviewSize();
try {
YuvImage image = new YuvImage(data, ImageFormat.NV21, size.width,
size.height, null);
if (image != null) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compressToJpeg(new Rect(0, 0, size.width, size.height),
80, stream);
Bitmap bmp = BitmapFactory.decodeByteArray(
stream.toByteArray(), 0, stream.size());
stream.close();
}
} catch (Exception ex) {
Log.e("Sys", "Error:" + ex.getMessage());
}
}

注意:該算法只適用於android2.2以后的版本~

——————————————————————————————————————

 

 

另外帖出一篇網文,僅供參考者圖像格式詳解網址:http://ticktick.blog.51cto.com/823160/555791
算法網址:http://www.cnblogs.com/lyout/archive/2012/03/16/2400370.html
本次摘錄網址 :
上次講的是攝像頭的初始化,如果覺得這么就萬事OK的話,那就大錯特錯了。接下來的東西讓人感到更加頭痛。
在我的這個應用里,不需要把拍下來的圖片存儲,只需要把預覽的圖片數據處理一下就好,很自然的我只是用了onPreviewFrame 
調用,考慮處理傳遞進來的data數據流就是了。
網上很多帖子都說,然后用BitmapFactory的decodeByteArray()函數來解析圖片就行了,我試了一下,發現這真是徹頭徹尾 的謊 
言,data字節流默認是YCbCr_420_SP(雖然可以改,但其他的格式未必兼容),decodeByteArray()壓根兒不 認!SDK2.2之后, 
似乎提供了一個YuvImage的類來轉一下(那Google一開始提供這個借口是做什么的?),難道就要把老機給拋棄了么??萬 萬不 
能啊(窮人最理解窮人們了)!
好在這個世界總是不缺少好人和牛人的,有人提供了這么一段轉換的代碼:
上次講的是攝像頭的初始化,如果覺得這么就萬事OK的話,那就大錯特錯了。接下來的東西讓人感到更加頭痛。
在我的這個應用里,不需要把拍下來的圖片存儲,只需要把預覽的圖片數據處理一下就好,很自然的我只是用了onPreviewFrame 
調用,考慮處理傳遞進來的data數據流就是了。
網上很多帖子都說,然后用BitmapFactory的decodeByteArray()函數來解析圖片就行了,我試了一下,發現這真是徹頭徹尾 的謊 
言,data字節流默認是YCbCr_420_SP(雖然可以改,但其他的格式未必兼容),decodeByteArray()壓根兒不 認!SDK2.2之后, 
似乎提供了一個YuvImage的類來轉一下(那Google一開始提供這個借口是做什么的?),難道就要把老機給拋棄了么??萬 萬不 
能啊(窮人最理解窮人們了)!
好在這個世界總是不缺少好人和牛人的,有人提供了這么一段轉換的代碼:

static public void decodeYUV420SP(int[] rgb, byte[] yuv420sp, int width, int height) {
final int frameSize = width * height;

for (int j = 0, yp = 0; j < height; j++) {
int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
for (int i = 0; i < width; i++, yp++) {
int y = (0xff & ((int) yuv420sp[yp])) - 16;
if (y < 0) y = 0;
if ((i & 1) == 0) {
v = (0xff & yuv420sp[uvp++]) - 128;
u = (0xff & yuv420sp[uvp++]) - 128;
}

int y1192 = 1192 * y;
int r = (y1192 + 1634 * v);
int g = (y1192 - 833 * v - 400 * u);
int b = (y1192 + 2066 * u);

if (r < 0) r = 0; else if (r > 262143) r = 262143;
if (g < 0) g = 0; else if (g > 262143) g = 262143;
if (b < 0) b = 0; else if (b > 262143) b = 262143;

rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff);
}
}
}

我不是很清楚這里面的原理,但是它能在我這里工作,暫時可以了……然后你才可以吧處理完的rgb[]傳給decodeByteArray()。
順便好心的把使用SDK2.2之后的也貼上吧,萬一有用呢……

public void onPreviewFrame(byte[] data, Camera arg1) {
FileOutputStream outStream = null;
try {
YuvImage yuvimage = new YuvImage(data,ImageFormat.NV21,arg1.getParameters().getPreviewSize 
().width,arg1.getParameters().getPreviewSize().height,null);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
yuvimage.compressToJpeg(new Rect(0,0,arg1.getParameters().getPreviewSize().width,arg1.getParameters 
().getPreviewSize().height), 80, baos);

outStream = new FileOutputStream(String.format("/sdcard/%d.jpg", System.currentTimeMillis()));
outStream.write(baos.toByteArray());
outStream.close();

Log.d(TAG, "onPreviewFrame - wrote bytes: " + data.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
}
Preview.this.invalidate();
}

 


哦,得到的圖像旋轉了90°(似乎有的機型設置一下setRotation(90)可以搞定,但還是那句話,不通用啊,況且這個是2.1之后 的API)。手動轉一下吧……

——————注:經本人驗證,並沒有出現旋轉90°的問題。。。

Matrix matrix = new Matrix();
matrix.postRotate(90);
// 這里的rgb就是剛剛轉換處理的東東
Bitmap bmp = Bitmap.createBitmap(rgb, 0, w, w, h, Bitmap.Config.ARGB_4444);
Bitmap nbmp = Bitmap.createBitmap(bmp,
0, 0, bmp.getWidth(), bmp.getHeight(), matrix, true);
終於正常了~~~
考慮到需要做識別,自然得先把它轉成灰度圖像,經典心理公式Gray = R*0.299 + G*0.587 + B*0.114出場了,但是手機的計算 
速度不那么快,這樣的浮點運算還是盡量避免吧~ 於是考慮Gray = (R*299 + G*587 + B*114 + 500) / 1000或者Gray = (R*30 + 
G*59 + B*11 + 50) /


免責聲明!

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



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