zoukankan      html  css  js  c++  java
  • 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) /

  • 相关阅读:
    python中的字符数字之间的转换函数
    java中的this和super的作用和异同和C++中调用父类的构造函数
    夺命雷公狗---Smarty NO:19 html_options函数
    夺命雷公狗---Smarty NO:18 html_checkboxes
    夺命雷公狗---Smarty NO:17 html_table函数
    夺命雷公狗---Smarty NO:16 html_image函数
    夺命雷公狗---Smarty NO:15 fetch函数
    夺命雷公狗---Smarty NO:14 debug调试
    夺命雷公狗---Smarty NO:13 系统自定义函数(plugins)
    夺命雷公狗---Smarty NO:12 section函数
  • 原文地址:https://www.cnblogs.com/mengyan/p/2666641.html
Copyright © 2011-2022 走看看