我已经复制粘贴了我在stackoverflow上找到的一些代码,将默认的相机预览YUV转换成RGB格式,然后上传到OpenGL进行处理。这很好,问题是大部分中央处理器都忙于将YUV图像转换成RGB格式,这变成了瓶颈。
我想将YUV图像上传到GPU,然后在片段着色器中将其转换为RGB。我使用了在CPU上运行的Java YUV to RGB函数,并试图使其在GPU上运行。
这变成了一场小小的噩梦,因为在Java和GPU上进行计算有几个不同之处。首先,预览图像在Java中是字节[],但是字节是有符号的,所以可能会有负值。
此外,片段着色器通常处理[0..1]的浮点值,而不是字节。
我确信这是可以解决的,我几乎解决了。但我花了几个小时试图找出我做错了什么,但还是没能成功。
总之,我要求有人编写这个着色器函数,最好测试一下。对我来说,这将是一个乏味的猴子工作,因为我真的不明白为什么这种转换的工作方式是这样的,我只是试图模仿GPU上相同的功能。
这是一个非常类似的功能,我用在Java:显示YUV图像在Android
我在CPU上做了一些工作,比如将1.5*wh字节YUV格式转换为wh*YUV格式,如下所示:
static public void decodeYUV420SP(int[] rgba, 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 = (int) yuv420sp[yp]+127;
if ((i & 1) == 0) {
v = (int)yuv420sp[uvp++]+127;
u = (int)yuv420sp[uvp++]+127;
}
rgba[yp] = 0xFF000000+(y<<16) | (u<<8) | v;
}
}
}
我添加了127,因为字节是有符号的。然后我将rgba加载到OpenGL纹理中,并尝试在GPU上完成其余的计算。
任何帮助都会被告知。。。
2011年2月,Renderscript首次推出。自从Android3.0蜂巢(API 11)和Android4.2 JellyBean(API 17)加入ScriptIntrinsicYuvToRGB以来,最简单、最有效的解决方案就是使用renderscript进行YUV到RGB的转换。我最近推广了这个解决方案来处理设备旋转。
在CPU上转换听起来很容易,但我相信问题是如何在GPU上做到这一点?
我最近在我的项目中做了这件事,我需要得到非常快的二维码检测,即使相机的角度是45度到打印代码的表面,它的工作性能很好:
(以下代码只是为了包含关键行而进行了裁剪,假设您对Java和OpenGLES都有很好的理解)
>
int[] txt = new int[1];
GLES20.glGenTextures(1,txt,0);
GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,txt[0]);
GLES20.glTextParameterf(... set min filter to GL_LINEAR );
GLES20.glTextParameterf(... set mag filter to GL_LINEAR );
GLES20.glTextParameteri(... set wrap_s to GL_CLAMP_TO_EDGE );
GLES20.glTextParameteri(... set wrap_t to GL_CLAMP_TO_EDGE );
请注意,纹理类型不是GL_texture_2D。这一点很重要,因为SurfaceTexture对象只支持GL_TEXTURE_EXTERNAL_OES类型,这将在下一步中使用。
设置SurfaceTexture:
SurfaceTexture surfTex = new SurfaceTeture(txt[0]);
surfTex.setOnFrameAvailableListener(this);
上面假设“this”是一个实现“onFrameAvailable”函数的对象。
public void onFrameAvailable(SurfaceTexture st)
{
surfTexNeedUpdate = true;
// this flag will be read in GL render pipeline
}
设置相机:
Camera cam = Camera.open();
cam.setPreviewTexture(surfTex);
如果你的目标是Android5.0,那么这个摄像头API是不推荐的,所以如果你是,你必须使用新的摄像头API。
在渲染管道中,使用以下块检查摄影机是否有可用的帧,并使用它更新表面纹理。更新表面纹理时,将填充与其链接的GL纹理。
if( surfTexNeedUpdate )
{
surfTex.updateTexImage();
surfTexNeedUpdate = false;
}
绑定带有摄像头的GL纹理-
GLES20.glBindTexture(GLES20.GL_TEXTURE_EXTERNAL_OS, txt[0]);
不用说,您需要设置当前活动纹理。
在将在片段部分使用上述纹理的GL着色器程序中,必须有第一行:
#extension GL_OES_EGL_imiage_external : require
以上是必备。
纹理均匀性必须为Externaloes类型:
uniform samplerExternalOES u_Texture0;
从中读取像素就像从GL_纹理_2D类型读取像素一样,UV坐标在相同的范围内(从0.0到1.0):
vec4 px = texture2D(u_Texture0, v_UV);
一旦你有你的渲染管道准备渲染上面的纹理和着色器,只需启动相机:
cam.startPreview();
你应该可以在GL屏幕上看到四元摄像头的实时视频。现在,您只需抓取带有glReadPixels的图像:
GLES20.glReadPixels(0,0,width,height,GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, bytes);
上行假设您的FBO是RGBA,字节已经初始化为字节[]数组的适当大小,宽度和高度是FBO的大小。
瞧!您已经从相机中捕获了RGBA像素,而不是转换在onPreviewFrame回调中接收的YUV字节...
你也可以使用RGB帧缓冲对象,如果你不需要它,可以避免alpha。
需要注意的是,摄像机将在自己的线程中调用不是GL渲染管道线程的onFramePrime,因此您不应该在该函数中执行任何GL调用。
我使用维基百科的代码计算GPU上从YUV到RGB的转换:
private static int convertYUVtoRGB(int y, int u, int v) {
int r,g,b;
r = y + (int)1.402f*v;
g = y - (int)(0.344f*u +0.714f*v);
b = y + (int)1.772f*u;
r = r>255? 255 : r<0 ? 0 : r;
g = g>255? 255 : g<0 ? 0 : g;
b = b>255? 255 : b<0 ? 0 : b;
return 0xff000000 | (b<<16) | (g<<8) | r;
}
我把浮点数改成了0.0。。255.0,然后使用上述代码。CPU上的部分是将原始YUV像素重新排列成YUV矩阵(也在wikipdia中显示)。基本上我使用了维基百科的代码,做了最简单的浮点运算
我正在为我的Android应用程序使用此相机预览应用程序。 我想要全屏幕的相机预览。因此,我使用Android API中的示例尝试将预览设置为全屏。这就是我试图做到的: 我使用相对布局作为我的布局。我的布局设置如下: 我仍然无法在整个屏幕上预览我的相机。我想知道如何预览整个屏幕。
我的意图是有一个方形相机预览。 我没有1:1比例的相机预览可用(我在Nexus 5模拟器中),所以我的最佳尺寸可用为640 x 480,所以为了适应正方形预览,我将SurfaceView尺寸设置为与纵横比相等,但将屏幕外的边距偏移一半,以在屏幕上只保留裁剪的正方形。表面视图本身的大小和偏移量是正确的,但是相机预览本身仍然在正方形内显示压缩后的预览,而不是以正确的纵横比部分地在屏幕外显示。 有什么想
我试图捕捉一个YUV图像,但被拉伸了。我正在使用Android Camera2,访问https://github.com/googlearchive/android-camera2basic。Android SDK是28。 当我使用ImageReader从setOnImageAvailableListener()方法捕获YUV2048x1536中的相机帧时,我面临一个奇怪的行为。捕获是拉伸的: Y
本文向大家介绍在Python中使用OpenCV将RGB格式的图像转换为HSV格式的图像,包括了在Python中使用OpenCV将RGB格式的图像转换为HSV格式的图像的使用技巧和注意事项,需要的朋友参考一下 的HSV是另一种类型的颜色空间,其中H代表色相,S表示饱和度和V代表值。 一个色调代表颜色。从0度到360度的角度。 角度 颜色 0-60 红 60-120 黄色 120-180 绿色 180
我的问题是:我在Android系统中安装了一个摄像头,并使用onPreviewFrame侦听器接收预览数据,该侦听器会向我传递一个字节[]数组,其中包含默认AndroidYUV格式的图像数据(设备不支持R5G6B5格式)。每个像素由12位组成,这让事情有点棘手。现在我想做的是将YUV数据转换成ARGB数据,以便对其进行图像处理。为了保持高性能,这必须使用renderscript来完成。 我的想法是
我已经和https://github.com/commonsguy/cwac-camera 创建了我的自定义CameraFragment和自定义CameraHost。 我已经重写了getPictureSize和getPreviewSize。通过这两种方法,我能够找出可以使用的大小。我的总体想法是拍摄一幅方形图像,并在拍摄前预览它。 我一直在测试,没有设备返回正方形格式的大小,所以我想最好的方法是选