色彩的二次抽样
在RGB颜色模式下,每个像素点由Red、Green、Blue三种颜色组合而成,YUV使用色彩通道UV和亮度通道Y,这种格式更适合图像处理领域,图片的所有细节保存在亮度通道中,如果没有亮度,图片就是一张灰度图片,人的眼睛对亮度的敏感度要高于颜色,所以可以通过减少每个像素点的颜色值,达到效果比较好的压缩,这个减少颜色数据的过程就是色彩的二次抽样
YUV转RGB绘制纹理
纹理映射只能在RGBA方式下执行,摄像头采集YUV,需要把YUV转换成RGBA
-
CoreVideo进行分离Y分量和UV分量
-
Fragment Shader对Y分量和UV分量进行采样
-
Fragment Shader转换YUV到RGB
-
进行渲染
看一下BT.601的RGB到YUV的转换算法
R' = 1.164*(Y’-16) + 1.596*(Cr'-128)
G' = 1.164*(Y’-16) - 0.392*(Cb'-128) - 0.813*(Cr'-128)
B' = 1.164*(Y’-16) + 2.017*(Cb'-128)
// 其中括号里面的是做伽马矫正用的
所以我们的转换矩阵可以这样写
mat3( 1.164, 1.164, 1.164,
0.0, -0.392, 2.017,
1.596, -0.813, 0.0,)
Fragment Shader中的转换下面这样写
varying highp vec2 texCoordVarying;
precision mediump float;
uniform sampler2D SamplerY;
uniform sampler2D SamplerUV;
uniform mat3 colorConversionMatrix;
void main() {
mediump vec3 yuv;
lowp vec3 rgb;
yuv.x = (texture2D(SamplerY, texCoordVarying).r);// - (16.0/255.0));
yuv.yz = (texture2D(SamplerUV, texCoordVarying).ra - vec2(0.5, 0.5));
rgb = colorConversionMatrix * yuv;
gl_FragColor = vec4(rgb, 1);
色彩的二次抽样在RGB颜色模式下,每个像素点由Red、Green、Blue三种颜色组合而成,YUV使用色彩通道UV和亮度通道Y,这种格式更适合图像处理领域,图片的所有细节保存在亮度通道中,如果没有亮度,图片就是一张灰度图片,人的眼睛对亮度的敏感度要高于颜色,所以可以通过减少每个像素点的颜色值,达到效果比较好的压缩,这个减少颜色数据的过程就是色彩的二次抽样YUV转RGB绘制纹理纹理映射只能在RGBA方式下执行,摄像头采集YUV,需要把YUV转换成RGBA获取到视频帧的YUV数据Core
* Very simple example of how to perform YUV->RGB (YCrCb->RGB)
* conversion with an OpenGL fragmen shader. The data (not included)
* is presumed to be three files with Y, U and V samples for a 720x576
* pixels large image.
* Note! The examp
GPU 实现 RGB -- YUV 转换
RGB --> YUV 转换的公式是现成的,直接在 CPU 端转换的话,只需要遍历每个像素,得到新的 YUV 值,根据其内存分布规律,合理安排分布即可。然而在 CPU 端进行转换,存在的问题运行效率太低,无法满足高效转换的需求。我们将目光投向拥有流水线体系的支持高速浮点数计算的硬件——GPU.
转换公式如下:
GPU 上面的实现
考虑在 GP...
* Very simple example of how to perform YUV->RGB (YCrCb->RGB)
* conversion with an OpenGL fragmen shader. The data (not included)
* is presumed to be three files with Y, U and V samples for a 72
2. 将YUV数据绑定到一个纹理单元上。
3. 创建一个着色器程序,用于将YUV数据转换为RGB格式。
4. 将纹理对象绑定到FBO(Frame Buffer Object),并将着色器程序与FBO绑定。
5. 渲染FBO以将YUV数据转换为RGB格式。
下面是一个简单的代码示例:
1. 创建纹理对象
GLuint textureID;
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
2. 绑定YUV数据到纹理单元
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, yData);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textureID);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width / 2, height / 2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, uvData);
3. 创建着色器程序
const char* vertexShader =
"attribute vec4 position;\n"
"attribute vec2 texCoord;\n"
"varying vec2 v_texCoord;\n"
"void main()\n"
"{\n"
" gl_Position = position;\n"
" v_texCoord = texCoord;\n"
"}\n";
const char* fragmentShader =
"precision highp float;\n"
"varying vec2 v_texCoord;\n"
"uniform sampler2D yTexture;\n"
"uniform sampler2D uvTexture;\n"
"void main()\n"
"{\n"
" float y = texture2D(yTexture, v_texCoord).r;\n"
" float u = texture2D(uvTexture, v_texCoord).r - 0.5;\n"
" float v = texture2D(uvTexture, v_texCoord).a - 0.5;\n"
" float r = y + 1.13983 * v;\n"
" float g = y - 0.39465 * u - 0.58060 * v;\n"
" float b = y + 2.03211 * u;\n"
" gl_FragColor = vec4(r, g, b, 1.0);\n"
"}\n";
GLuint programID = glCreateProgram();
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShaderID, 1, &vertexShader, NULL);
glCompileShader(vertexShaderID);
glAttachShader(programID, vertexShaderID);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShaderID, 1, &fragmentShader, NULL);
glCompileShader(fragmentShaderID);
glAttachShader(programID, fragmentShaderID);
glLinkProgram(programID);
glUseProgram(programID);
4. 绑定纹理对象到FBO,并将着色器程序与FBO绑定
GLuint fboID;
glGenFramebuffers(1, &fboID);
glBindFramebuffer(GL_FRAMEBUFFER, fboID);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0);
glViewport(0, 0, width, height);
glUseProgram(programID);
glUniform1i(glGetUniformLocation(programID, "yTexture"), 0);
glUniform1i(glGetUniformLocation(programID, "uvTexture"), 1);
5. 渲染FBO
GLfloat vertices[] = {
-1.0f, 1.0f, 0.0f, 1.0f,
-1.0f, -1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 1.0f, 1.0f,
1.0f, -1.0f, 1.0f, 0.0f
GLubyte indices[] = {0, 1, 2, 3};
glVertexAttribPointer(glGetAttribLocation(programID, "position"), 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), vertices);
glVertexAttribPointer(glGetAttribLocation(programID, "texCoord"), 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), vertices + 2);
glEnableVertexAttribArray(glGetAttribLocation(programID, "position"));
glEnableVertexAttribArray(glGetAttribLocation(programID, "texCoord"));
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, indices);
glDisableVertexAttribArray(glGetAttribLocation(programID, "position"));
glDisableVertexAttribArray(glGetAttribLocation(programID, "texCoord"));
Unity 打包warning:Missing Project ID和Unable to access Unityservices.Please log in,or request ......
ଘ(੭ˊᵕˋ)੭* ੈkg:
C++ 保存Excel文件(带密码保护)
zyw169888:
Unity Shader之磨砂玻璃与水雾玻璃效果
seed_ling:
Unity 工具之 UniWebView 内嵌网页/浏览器到应用中,并且根据UGUI大小放置(简单适配UGUI)
一切皆会:
直播换脸后,我们来搞搞微信QQ聊天换脸!| avatarify
2401_85850341: