2019独角兽企业重金招聘Python工程师标准>>>

上次讲的是摄像头的初始化,如果觉得这么就万事OK的话,那就大错特错了。接下来的东西让人感到更加头痛。

在我的这个应用里,不需要把拍下来的图片存储,只需要把预览的图片数据处理一下就好,很自然的我只是用了onPreviewFrame调用,考虑处理传递进来的data数据流就是了。

网上很多帖子都说,然后用BitmapFactory的decodeByteArray()函数来解析图片就行了,我试了一下,发现这真是彻头彻尾的谎言,data字节流默认是YCbCr_420_SP(虽然可以改,但其他的格式未必兼容),decodeByteArray()压根儿不认!SDK2.2之后,似乎提供了一个YuvImage的类来转一下(那Google一开始提供这个借口是做什么的?),难道就要把老机给抛弃了么??万万不能啊(穷人最理解穷人们了)!

好在这个世界总是不缺少好人和牛人的,有人提供了这么一段转换的代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

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之后的也贴上吧,万一有用呢……

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

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)。手动转一下吧……

1

2

3

4

5

6

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) / 100。但是除法总是还是不够快,用移位吧……Gray = (R*19595 + G*38469 + B*7472) >> 16,稍微小一点,用Gray = (R*38 + G*75 + B*15) >> 7也足够了。

经过一番努力学习,把写就的代码兴致勃勃的在手机上跑了一下,虽然不够快结果出来了,想想也是大负荷运算啊,自我安慰客户应该可以有这样的耐心吧。

就在这个时候,我突然想起一件很重要的事情!
我需要的是灰度图,也就是亮度风量,而最开始的YUV,不就是亮度色度饱和度么?!那么Y分类不就是我需要的灰度值吗!!我在做什么,辛辛苦苦转成RGB,再转成亮度,吃饱了撑着不是。想到这里我立刻用头撞墙九九一百八十一次,一悼念我那白白死去的脑细胞的在天之灵。立刻重写,删除大量代码,快多了,效果也好~~ 鄙视一下两小时前的自己!

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);

}

}

}

转载于:https://my.oschina.net/u/1177694/blog/489150

Android用摄像头的那点破事相关推荐

  1. android录像摄像头卡死,Android用摄像头的那点破事

    摄像头不是所有随便的(w, h)都能够认识的,所以呢,我们有了下面这样的增强版: List mSupportedPreviewSizes; mSupportedPreviewSizes = mCame ...

  2. 关于Android蓝牙串口通信那点破事

    Android蓝牙串口通讯 闲着无聊玩起了Android蓝牙模块与单片机蓝牙模块的通信,简单思路就是要手机通过蓝牙发送控制指令给单片机,并作简单的控制应用.单片机的蓝牙模块连接与程序暂且略过,此文主要 ...

  3. [Android开发那点破事]解决android.os.NetworkOnMainThreadException

    昨天和女朋友换了手机,我的iPhone 4S 换了她得三星I9003.第一感觉就是好卡,果断刷机.以前是Android 2.3的系统.回来刷成了4.4. 好了,问题来了.在我用手机测试我们的APP的时 ...

  4. 【Android开发那点破事】打开APP加载页面实现

    今天的破事呢就说说APP加载页面的实现.一般情况下,当APP打开的时候,我们需要做很多事情,比如检查网络连接啊,初始化一些配置啊等等.我们可以让这些事情在APP完全打开之前做完,然后呢在打开的过程中显 ...

  5. 【Android开发那点破事】解决android.os.NetworkOnMainThreadException

    昨天和女朋友换了手机,我的iPhone 4S 换了她得三星I9003.第一感觉就是好卡,果断刷机.以前是Android 2.3的系统.回来刷成了4.4. 好了,问题来了.在我用手机测试我们的APP的时 ...

  6. Android -- 获取摄像头帧数据解码

    由于Android下摄像头预览数据只能  ImageFormat.NV21 格式的,所以解码时要经过一翻周折. Camera mCamera = Camera.open();Camera.Parame ...

  7. android 7调用摄像头,Android调用摄像头拍照(兼容7.0)

    [实例简介] Android调用摄像头拍照(兼容7.0)Demo,原博客文章https://blog.csdn.net/u010356768/article/details/70808162 [实例截 ...

  8. Android双目三维重建:Android双目摄像头实现双目测距

    Android双目三维重建:Android双目摄像头实现双目测距 目录 Android双目三维重建:Android双目摄像头实现双目测距 1.开发版本 2.Android双目摄像头 3.双目相机标定 ...

  9. 团队管理那点破事!OKR绩效、核心人才、面试、技术分享、研发流程....

    今天来聊聊团队管理,可能你现在还是一线开发,没有带团队,感觉这个话题与你无关,其实不然. 程序员的职业生涯曲折,技术更新迭代快,走技术深度,走架构师路线,势必要付出常人的时间和精力.而管理则可以更好的 ...

最新文章

  1. Altium Designer快捷键失效恢复方法
  2. 使用HMSegmentedControl实现分段控件
  3. C语言工程代码查看神器 SourceInsight
  4. python 用户输入_Python 用户输入(input)
  5. 数据库运维平台~慢日志模块设计
  6. Sentinel(五)之流量控制
  7. CRC32算法详细推导(3)
  8. u-boot分析(八)----串口初始化
  9. 一个月学会Python的Quora指南和资料放送
  10. 红旗linux6.0安装不了,在红旗linux6.0中安装vmware tools遇到的问题
  11. arcgis engine设置数据源路径_不懂ArcGIS,你前期分析用什么做的?
  12. 02-微信小程序商城 顶部广告图片(微信小程序商城开发、小程序毕业设计、小程序源代码)(黄菊华-微信小程序开发教程)
  13. c语言pow函数原型_c语言中pow函数的用法是什么?_后端开发
  14. 计算机网络-什么是网络协议?
  15. Enterprise Library 2.0 -- Exception Handing Applcation Block
  16. 为什么Lisp如此先进,却永远成为不了编程主流语言?深度解析Lisp的优势与劣势
  17. Spring Boot学习案例开源项目
  18. 世界十大经典汽车赛道盘点
  19. 随机变量的函数的分布
  20. vue中实现生成海报图片html2canvas详细教程

热门文章

  1. swift_014(Swift 的控制流)
  2. 封装进程内存相关操作函数
  3. void关键字的使用规则
  4. Asp.net Core认证和授权:JWT认证和授权
  5. .NET Core版本七牛云SDK使用
  6. MySqli操作数据库
  7. 你甘心就这样过一辈子?
  8. [转]详细的mysql时间和日期函数
  9. Lua中使用Sleep函数
  10. ASP.NET中删除文件夹下的文件