android环境下摄像头数据采集及显示

作者:网络    软件教程库   2020-05-12

以前项目涉及些摄像头预览及数据处理操作,当时的需求是除了做摄像头预览外,还要显示文字、个性图像等,当初在查找资料实现相关模块时,发现很多资料讲的比较繁琐,不够简洁,这里将自己的实现方式分享出来,希望能够为正在做相关工作的同学提供些思路。不过这里先顺便提一下,如果单纯的做摄像头预览,不在预览数据时做添加文字、图像等额外操作,可以用surfaceview方式,性能上会更好些。

这里将摄像头采集及视频图像绘制放在一个模块中,比较便于管理及维护,同时在使用时,因为该类继承自view类,所以可以向操作很多view类一样,将其添加到任何布局中,在与采集的数据宽高比例保持一致的前提下,在页面显示上可以非常灵活的控制视图尺寸大小。不过使用这种方式实现摄像头预览,最大的瓶颈是在旋转yuv数据及将其转为rgb数据时,计算比较耗时,一般情况下采集640*480数据还好,但对于960*720数据来说,手机性能一般的话,就会显得比较卡了。解决方式在做数据旋转时,可以尝试采用ndk c的方式,以提高运行效率,在做yuv转rgb时,也可以尝试用ndk c的方式,但是最好的方式是采用gpu shader方式,直接渲染yuv数据,即将采集的yuv数据以纹理的方式上传至gpu,然后由gpu完成yuv转rgb并显示。下面是相关代码:

public class cameraview extends view implements previewcallback
{
	// 源视频帧宽/高
	private int srcframewidth  = 640;
	private int srcframeheight = 480;
	private int framesize = srcframewidth * srcframeheight;
	private int qtrframesize = srcframewidth * srcframeheight  2;
	
	// 帧预览贴图
	private bitmap previewbmp = null;
	private rect previewrect = null;
	private camera camera = null;
	// 图层
	private baselayer[] layers = null;
	
	// 数据采集
	private int[] rgb_data = null;
	private byte[] yuvdata = null;
	
	// 摄像头前置/后置
	public static final int camera_back  = 0;
	public static final int camera_front = 1;
	private int curcameraindex = camera_back;
	
	public cameraview(context _context)
	{
		super(_context);
	}
	
	public cameraview(context _context, attributeset _attrs)
	{
		super(_context, _attrs);
	}
	
	public cameraview(context context, int previewwidth, int previewheight, int cameraindex)
	{
		super(context);
		
		curcameraindex = cameraindex;
		rgb_data = new int[framesize];
		yuvdata = new byte[framesize * 3 / 2];
		
		previewbmp = bitmap.createbitmap(srcframeheight, srcframewidth, config.argb_8888);
		previewrect = new rect(0, 0, previewwidth, previewheight);
		
		// 定义图层
		layers = new baselayer[2];
		layers[0]  = new textlayer(context, 0, false);
		layers[1] = new imagelayer(context, 1, false);
		
		// 文字
		((textlayer)layers[0]).setfontparams(32, color.cyan);
		((textlayer)layers[0]).settextpos(100, 300);
		((textlayer)layers[0]).setcontent(天气还不错....);
		layers[0].setvisible(true);
		
		// 图像
		((imagelayer)layers[1]).setimagepos(100, 150);
		layers[1].setvisible(true);
		
		// 初始化并打开摄像头
		startcamera(cameraindex);
		
		this.setbackgroundcolor(color.parsecolor(#82858b));
	}
	
	// 根据索引初始化摄像头
	public void startcamera(int cameraindex)
	{
		// 先停止摄像头
		stopcamera();
		
		// 再初始化并打开摄像头
		if (camera == null)
		{
			camera = camera.open(cameraindex);
			camera.parameters params = camera.getparameters();
			params.setpreviewsize(srcframewidth, srcframeheight);
			params.setpreviewformat(imageformat.nv21);
			camera.setparameters(params);
			camera.setpreviewcallback(this);
			camera.startpreview();
		}
	}
	
	// 停止并释放摄像头
	public void stopcamera()
	{
		if (camera != null)
		{
			camera.setpreviewcallback(null);
			camera.stoppreview();
			camera.release();
			camera = null;
		}
	}
	
	// 绘制
	@override
	protected void ondraw(canvas canvas)
	{
		super.ondraw(canvas);
		
		// 填充数据(因为数据已经旋转过,此时宽与高需要互换)
		previewbmp.setpixels(rgb_data, 0, srcframeheight, 0, 0, srcframeheight, srcframewidth);
		
		// 绘制图层
		for (baselayer layer : layers)
		{
			if (layer.isvisible())
			{
				layer.drawlayer(previewbmp);
			}
		}
		
		// 贴图
		canvas.drawbitmap(previewbmp, null, previewrect, null);
	}
	
	// 获取摄像头视频数据
	@override
	public void onpreviewframe(byte[] data, camera camera)
	{
		int i = 0, j = 0, k = 0;
		int uvheight = srcframeheight  1;

		// 旋转yuv数据
		if (curcameraindex == camera_back)
		{
			// 旋转y
			for (i = 0; i  srcframewidth; i++)
			{
				for (j = srcframeheight - 1; j = 0; j--)
				{
					yuvdata[k] = data[srcframewidth * j + i];
					k++;
				}
			}

			// 旋转uv
			for (i = 0; i  srcframewidth; i += 2)
			{
			   for (j = uvheight - 1; j = 0; j--)
			   {
				   yuvdata[k] = data[framesize + srcframewidth * j + i + 1];// cb/u
				   yuvdata[k + qtrframesize] = data[framesize + srcframewidth * j + i];// cr/v
				   k++;
			   }
			}
		}
		else
		{
			// 旋转y
			for (i = srcframewidth - 1; i = 0; i--)
			{
				for (j = srcframeheight - 1; j = 0; j--)
				{
					yuvdata[k] = data[srcframewidth * j + i];
					k++;
				}
			}

			// 旋转uv
			for (i = srcframewidth - 2; i = 0; i -= 2)
			{
			   for (j = uvheight - 1; j = 0; j--)
			   {
				   yuvdata[k] = data[framesize + srcframewidth * j + i + 1];// cb/u
				   yuvdata[k + qtrframesize] = data[framesize + srcframewidth * j + i];// cr/v
				   k++;
			   }
			}
		}
		
		// yuv转rgb(因为数据已经旋转过,此时宽与高需要互换)
		int yp = 0;
		for (i = 0, yp = 0; i  srcframewidth; i++)
		{
			int uvp = framesize + (i  1) * uvheight, u = 0, v = 0;
			for (j = 0; j  srcframeheight; j++, yp++)
			{
				int y = (0xff  yuvdata[yp]) - 16;
				if ((j  1) == 0)
				{
					u = (0xff  yuvdata[uvp + (j1)]) - 128;
					v = (0xff  yuvdata[uvp + qtrframesize + (j1)]) - 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_data[i*srcframeheight + j] = 0xff000000 | ((r  6)  0xff0000) | ((g  2)  0xff00) | ((b  10)  0xff);
			}// for
		}// for
		
		invalidate();
	}
}
工程下载链接:http://download.csdn.net/detail/u013085897/8652979




android环境下摄像头数据采集及显示

原文地址:http://blog.csdn.net/grafx/article/details/45422945

这篇内容就是由软件教程库 小编为各位整理 原文链接:https://www.itjcku.com/9999/1091354.html

阅读全部内容


Tags:环境摄像头数据采集收集显示

返回首页



推荐内容

uva10003CuttingSticks简单区间dp

// uva 10003 cutting sticks 区间dp // 经典的区间dp // dp(i,j)表示切割小木 ...

Go的语言特性总结

写在前面: 近来关于对golang的讨论有很多,七牛的几个大牛们也断定go语言在未来将会快速发展,并且很可能会取代ja ...

golang控制channel的出入口

golang控制channel的出入口 我们常常使用channel来在多个goroutine之间做数据通讯,但是cha ...

UVA10479TheHendrieSequence规律

题目大意:一个序列,刚开始由0变到了1,接着往后一个个变化下去 变化的规则是,如果当前数是k,就在这个序列的最后面加上 ...

在不是Activity类中调用Toast和Dialog

有时候我们需要在非activity类中处理一些逻辑,显示toast对话框或者是弹出一个dialog,但是在非activi ...

查询Oraclesql语句中绑定变量值的方法

alter session set nls_date_format = #39;yyyy-mm-dd,hh24:mi:s ...

Hdoj1588GaussFibonacci【矩阵快速幂】

gauss fibonacci time limit: 1000/1000 ms (java/others) m ...

Hdoj5195DZYLovesTopologicalSorting【拓扑】+【线段树】

dzy loves topological sorting time limit: 4000/2000 ms (jav ...

【转自mos文章】使用单条sql来查询出awr中的syatemstatistics

使用单条sql来查询出awr中的syatem statistics 参考自: how to monitor system ...

I.MX6Q(TQIMX6Q/TQE9)学习笔记——新版BSP之u-boot移植

前段时间就开始学习i.mx6q了,但是最近工作实在是忙,间断了一些时间了。为了提高移植效率,还是考虑移植freescal ...

eclipse应用技巧

最近发现eclipse作为ide还是有很多值得探索的使用技巧的,转载一下他人整理好的资源以做分享。 快捷键的使用,加速 ...

Mysql创建数据库的排序规则中文选择哪种编码

mysql中文编码 mysql创建数据库的排序规则 中文 选择哪种编码原文地址:http://blog. ...

线性表简述

一、简单实现增,删,改、查 package datatructs; /** * 表接口 */ public int ...

android测试本地服务调试流程

我今天调试的整个过程 1,安卓发现连不上本地的tomcat 2,使用浏览器直接尝试,发现可以连上 3,怀疑是安卓app和 ...

设计模式1

静态工厂模式,工厂方法模式,抽象工厂模式 工厂方法改进了添加新产品时,静态工厂不满足的开-闭原则;而抽象工厂满足了当产品 ...

c语言文件操作总结

#includelt;stdio.hgt; /********************************** ...

(c#)如果添加的字段中已经有了身份证号码,则年龄和性别和出生年月可得

//把界面文本框里面的身份证号进行提取,以二代身份证为例 model.ecardid = txt_cardno. ...

Scrum时间估算

在新公司里,不懂软件工程的产品经理经常逼迫研发人员作出很不靠谱的时间估算。常见场景有下面这些: 需求未细化的情况下要求给 ...

C++11中uniforminitialization和initializer_list

c++11中出现了uniform initialization的概念: int a1 = {1};//ok int a ...

关于Scrum

最近某些产品经理发出下两周的工作计划的时候,喜欢带上sprint这个字眼,看上去貌似是要走敏捷开发这一套,只可惜,我觉得 ...

输入输出简单解释

;汇编指令,表示程序将被汇编成能在intel386系列及以上的计算机上运行.386;model flat 表明程序使用保 ...

2015第18周五问题即机会

问题即机会,当一切问题都不存在的时候,请问你的机会在哪里? 你能达到怎样的境界,取决于你怎样认识这个世界。对于问题,有人 ...

solr配置方案

http://www.sjsjw.com/kf_cloud/article/44_5945_1823.asp cento ...

什么是二维码?

二维码,业界当然是人人听说,人人用过。 这个话题,我倒是百感交集,我一直认为,我有一种二维码情节。 一方面, 我自认 ...

1475:方格取数

1475: 方格取数 time limit:5 secmemory limit:64 mbsubmit:578solv ...

敏捷开发宣言(一)

原文: inpiduals and interactionsover processes and tools worki ...

(C#)一个项目的配置和增删改查

一、windows窗体项目环境配置步骤 1.文件mdash;gt;新建mdash;gt;项目mdash;gt;windo ...

比例简化

题目描述description 在社交媒体上,经常会看到针对某一个观点同意与否的民意调查以及结果。例如,对某一观点表示 ...

sockaddr和sockaddr_in的区别

struct sockaddr和struct sockaddr_in这两个结构体用来处理网络通信的地址。 在各种系统调用 ...

基于Html5的智能家居手机客户端设计(一)——找到openhab的rest

今天开始我的毕业设计,基于html5的智能家居手机客户端设计。挑剔了好久,终于找到我可以使用国外开源项目智能家居核心 ...


本网站部分内容来自互联网,版权归原作者所有,文章内容仅代表原作者个人观点。如有侵权请联系我们删除 电子邮件 itjcku@foxmail.com