YUV色彩空间的物理意义从RGB转化为YUV时,Y分量代表灰度,但是计算Y时并不是将RGB三者平均而得的,RGB的权值并不相同,这是为什么?或者说这么设计有什么依据吗?
Y 代表亮度,UV为色度,人眼对亮度敏感,对色度相对不敏感.所以很多图像处理方法,为了节省运行时间,都对y做复杂处理,对UV简单处理.三个系数中,G对应的系数较大,这个老师说过的,可是不太记得了~~
你说的这些我都知道,我想知道的是“为什么Y的计算公式中RGB的权值各不相同?”
上课只听了大概,细节记不得了,丢脸……
在网上搜索了下,这些权值的确定是为了更符合人眼的感知。人眼对光谱中的黄-绿色区域更敏感,所以G对应的权值较大。
Luma can be relatively easly calculated from RGB channels by averaging the color values and giving more weight to some colors over others to find out the luma value. Scientists came up with weights that match human perception where green has high contribution, red half of that, blue - one third of red. Why this is the case is simply a matter of the way the brain works and this perceptive model is important in how YUV was developed.
human color perception is most sensitive to light in the yellow-green region of the spectrum
参考:/tutorials/color-perception.htm
为您推荐:
其他类似问题
Y分量确实是灰度,但是灰度化的方法有几种,你所说的RGB三者平均是取灰度的一种方法,而常规RGB转YUV的Y分量转换,采用的是加权平均法,根据颜色的重要性,人眼对绿色最敏感,对蓝色最不敏感,所以用加权平均法取的Y
扫描下载二维码scale YUV420视频的缩放,经过高度的优化,其中三次卷积插值(cubic convolution) 的效 Special Effects 图形图像处理 238万源代码下载-
&文件名称: scale
& & & & &&]
&&所属分类:
&&开发工具: C-C++
&&文件大小: 4 KB
&&上传时间:
&&下载次数: 59
&&提 供 者:
&详细说明:YUV420视频的缩放,经过高度的优化,其中三次卷积插值(cubic convolution)算法的效果最好,优化程度也最高。其基本思想是通过整型化、查表等方法消除每一帧图像插值运算中的浮点运算和乘除法运算。-scale YUV420 video frames with cubic, bilinear & cubic convolution interpolation algorithms。
&近期下载过的用户:
&相关搜索:
&输入关键字,在本站238万海量源码库中尽情搜索:
&[] - 图像缩放,输入输出都是yuv420格式的yuv文件
&[] - 二次线性插值和三次卷积插值,高质量图像缩放技术之一,文中有大量代码,实用性很强。
&[] - 基于Retinex的MSRCR算法的C语言实现。其中的高斯平滑采用了与尺度无关的快速算法,每个点的运算只要6MADD。程序改自GRetinex,一个GIMP插件
&[] - 本人写的YUV图像缩放程序,支持不同的算法,宏开关控制,小巧好用
&[] - 双线性插值和三次卷积法将图象扩大两倍,c语言实现。2073人阅读
Android-Camera开发(11)
文章例如通过将YUV分成三个纹理,在shader中取出并且经过公式变换,转换成RGB。我尝试了下,显示的是灰色的,可能是这篇文章采用的是planar格式的YUV,与Android平台的packed格式的YUV不同,因此需要在纹理绑定处进行数据指针的修改。
之前在一篇13年北大硕士的论文中提出了一种实现方法,采用双通道,将Y通道与UV通道分别贴图。网上也有单通道经过一些转换再转换的方法,欢迎讨论。
首先我们探讨下YUV格式
Android平台相机预览数据获取接口onPreviewFrame中默认获取的是YUV420sp格式,例如下图为8X4像素的YUV图像示意图
即首先将Y信号排列,然后UV数据分别交错排列。其中Y信号数组长度为width * height,UV信号长度为width * heght / 2,数组首元素位置起始于width * height。总长度为width * height * 1.5,相比于采用传统的rgb格式长度减少一半,因此常用语电视信号传输。
其中Y表示明亮度,也就是灰阶值。UV表示色度,是描述影响色彩及饱和度,用于指定像素颜色。因此,如果我们只使用Y通道,看到的就是原图的灰度图。
因为GPU并不会根据传入的纹理判断格式,所以我们可以将YUV数据作为RGB数据欺骗GPU,将Y通道与UV通道分成两个纹理传入shader,在shader中利用GPU的优势来进行快速转换。注意要使用两个不同的纹理单元,例如GL_TEXTURE0和GL_TEXTURE1,同样修改glUniform1i第二个参数
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, id_y);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
glUniform1i(gvImageTextureY, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, id_uv);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width/2, height/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, data + width*height);
glUniform1i(gvImageTextureUV, 1);
与直接使用RBGA数据不同,这里的参数采用的是GL_LUMINANCE,与GL_LUMINANCE_ALPHA,与GL_RGBA不同,GL_RGBA单独保存R、G、B、A四个数据,而GL_LUMINANCE将这四个数据合并成一个,因为这样1个Y就可以与1个RGBA对应。GL_LUMINANCE_ALPHA代表首先是亮度,然后是alpha值,这样我们就能将U值与V值分别取出。
之后通过shader将YUV格式转为RGB格式:
uniform sampler2D mGLUniformT
uniform sampler2D mGLUniformTexture1;
varying highp vec2 textureC
const mat3 yuv2rgb = mat3(
1, 0, 1.2802,
1, -0.214821, -0.380589,
void main() {
vec3 yuv = vec3(
1.1643 * (texture2D(mGLUniformTexture, textureCoordinate).r - 0.0625),
texture2D(mGLUniformTexture1, textureCoordinate).a - 0.5,
texture2D(mGLUniformTexture1, textureCoordinate).r - 0.5
vec3 rgb = yuv * yuv2
gl_FragColor = vec4(rgb, 1);
其中,texture2D(mGLUniformTexture, textureCoordinate).r即YUV中的Y数据,texture2D(mGLUniformTexture, textureCoordinate).a即YUV中的V数据,剩下一个就是U,经过矩阵公式转换后就是RGB数据,然后设置给gl_FragColor,OpenGL就可以正确的显示了
其余部分基本不变,也不再赘述
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:58287次
排名:千里之外
原创:30篇
评论:78条
文章:12篇
阅读:37470
文章:15篇
阅读:17844
(3)(8)(8)(6)(1)(2)(1)(1)5066人阅读
& & 本文用Java创建UI并联合JNI层操作surface来直接显示yuv数据(yv12),开发环境为Android 4.4,全志A23平台。
package com.example.
import java.io.F
import java.io.FileInputS
import android.app.A
import android.os.B
import android.os.E
import android.util.L
import android.view.S
import android.view.SurfaceH
import android.view.SurfaceHolder.C
import android.view.SurfaceV
public class MainActivity extends Activity {
final private String TAG = &MyYUVViewer&;
final private String FILE_NAME = &yuv_320_240.yuv&;
private int width = 320;
private int height = 240;
private int size = width * height * 3/2;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nativeTest();
SurfaceView surfaceview = (SurfaceView) findViewById(R.id.surfaceView);
SurfaceHolder holder = surfaceview.getHolder();
holder.addCallback(new Callback(){
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
Log.d(TAG,&surfaceCreated&);
byte[]yuvArray = new byte[size];
readYUVFile(yuvArray, FILE_NAME);
nativeSetVideoSurface(holder.getSurface());
nativeShowYUV(yuvArray,width,height);
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// TODO Auto-generated method stub
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
private boolean readYUVFile(byte[] yuvArray,String filename){
// 如果手机插入了SD卡,而且应用程序具有访问SD的权限
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
// 获取SD卡对应的存储目录
File sdCardDir = Environment.getExternalStorageDirectory();
// 获取指定文件对应的输入流
FileInputStream fis = new FileInputStream(
sdCardDir.getCanonicalPath() +&/& + filename);
fis.read(yuvArray, 0, size);
fis.close();
}catch (Exception e) {
e.printStackTrace();
private native void nativeTest();
private native boolean nativeSetVideoSurface(Surface surface);
private native void nativeShowYUV(byte[] yuvArray,int width,int height);
System.loadLibrary(&showYUV&);
activity_main.xml
&LinearLayout xmlns:android=&/apk/res/android&
android:layout_width=&fill_parent&
android:layout_height=&fill_parent&
android:orientation=&vertical& &
&SurfaceView
android:id=&@+id/surfaceView&
android:layout_width=&fill_parent&
android:layout_height=&360dp& /&
&/LinearLayout&
JNI层,showYUV.cpp(libshowyuv.so)采用动态注册JNI函数的方法.
#include &jni.h&
#include &android_runtime/AndroidRuntime.h&
#include &android_runtime/android_view_Surface.h&
#include &gui/Surface.h&
#include &assert.h&
#include &utils/Log.h&
#include &JNIHelp.h&
#include &media/stagefright/foundation/ADebug.h&
#include &ui/GraphicBufferMapper.h&
#include &cutils/properties.h&
static sp&Surface&
static int ALIGN(int x, int y) {
// y must be a power of 2.
return (x + y - 1) & ~(y - 1);
static void render(
const void *data, size_t size, const sp&ANativeWindow& &nativeWindow,int width,int height) {
ALOGE(&[%s]%d&,__FILE__,__LINE__);
sp&ANativeWindow& mNativeWindow = nativeW
int mCropWidth =
int mCropHeight =
int halFormat = HAL_PIXEL_FORMAT_YV12;//颜色空间
int bufWidth = (mCropWidth + 1) & ~1;//按2对齐
int bufHeight = (mCropHeight + 1) & ~1;
CHECK_EQ(0,
native_window_set_usage(
mNativeWindow.get(),
GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN
| GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP));
CHECK_EQ(0,
native_window_set_scaling_mode(
mNativeWindow.get(),
NATIVE_WINDOW_SCALING_MODE_SCALE_CROP));
// Width must be multiple of 32???
//很重要,配置宽高和和指定颜色空间yuv420
//如果这里不配置好,下面deque_buffer只能去申请一个默认宽高的图形缓冲区
CHECK_EQ(0, native_window_set_buffers_geometry(
mNativeWindow.get(),
bufHeight,
halFormat));
ANativeWindowBuffer *//描述buffer
//申请一块空闲的图形缓冲区
if ((err = native_window_dequeue_buffer_and_wait(mNativeWindow.get(),
&buf)) != 0) {
ALOGW(&Surface::dequeueBuffer returned error %d&, err);
GraphicBufferMapper &mapper = GraphicBufferMapper::get();
Rect bounds(mCropWidth, mCropHeight);
CHECK_EQ(0, mapper.lock(//用来锁定一个图形缓冲区并将缓冲区映射到用户进程
buf-&handle, GRALLOC_USAGE_SW_WRITE_OFTEN, bounds, &dst));//dst就指向图形缓冲区首地址
if (true){
size_t dst_y_size = buf-&stride * buf-&
size_t dst_c_stride = ALIGN(buf-&stride / 2, 16);//1行v/u的大小
size_t dst_c_size = dst_c_stride * buf-&height / 2;//u/v的大小
memcpy(dst, data, dst_y_size + dst_c_size*2);//将yuv数据copy到图形缓冲区
CHECK_EQ(0, mapper.unlock(buf-&handle));
if ((err = mNativeWindow-&queueBuffer(mNativeWindow.get(), buf,
-1)) != 0) {
ALOGW(&Surface::queueBuffer returned error %d&, err);
buf = NULL;
static void nativeTest(){
ALOGE(&[%s]%d&,__FILE__,__LINE__);
static jboolean
nativeSetVideoSurface(JNIEnv *env, jobject thiz, jobject jsurface){
ALOGE(&[%s]%d&,__FILE__,__LINE__);
surface = android_view_Surface_getSurface(env, jsurface);
if(android::Surface::isValid(surface)){
ALOGE(&surface is valid &);
ALOGE(&surface is invalid &);
ALOGE(&[%s][%d]\n&,__FILE__,__LINE__);
static void
nativeShowYUV(JNIEnv *env, jobject thiz,jbyteArray yuvData,jint width,jint height){
ALOGE(&width = %d,height = %d&,width,height);
jint len = env-&GetArrayLength(yuvData);
ALOGE(&len = %d&,len);
jbyte *byteBuf = env-&GetByteArrayElements(yuvData, 0);
render(byteBuf,len,surface,width,height);
static JNINativeMethod gMethods[] = {
{&nativeTest&,
(void *)nativeTest},
{&nativeSetVideoSurface&,
&(Landroid/view/S)Z&,
(void *)nativeSetVideoSurface},
{&nativeShowYUV&,
&([BII)V&,
(void *)nativeShowYUV},
static const char* const kClassPathName = &com/example/myyuvviewer/MainActivity&;
// This function only registers the native methods
static int register_com_example_myyuvviewer(JNIEnv *env)
ALOGE(&[%s]%d&,__FILE__,__LINE__);
return AndroidRuntime::registerNativeMethods(env,
kClassPathName, gMethods, NELEM(gMethods));
jint JNI_OnLoad(JavaVM* vm, void* reserved)
ALOGE(&[%s]%d&,__FILE__,__LINE__);
JNIEnv* env = NULL;
jint result = -1;
if (vm-&GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
ALOGE(&ERROR: GetEnv failed\n&);
assert(env != NULL);
ALOGE(&[%s]%d&,__FILE__,__LINE__);
if (register_com_example_myyuvviewer(env) & 0) {
ALOGE(&ERROR: MediaPlayer native registration failed\n&);
/* success -- return valid version number */
result = JNI_VERSION_1_4;
Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
showYUV.cpp
LOCAL_SHARED_LIBRARIES := \
libcutils \
libutils \
libbinder \
libandroid_runtime \
libstagefright_foundation
LOCAL_MODULE:= libshowYUV
LOCAL_MODULE_TAGS := tests
include $(BUILD_SHARED_LIBRARY)
生成的so文件复制到Java项目里 与src并列的libs/armeabi目录下,没有就手动创建目录,
这样Eclipse会自动把so库打包进apk。
转载请注明出处:
yuvdata下载地址:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:28727次
排名:千里之外
原创:13篇
评论:48条
(1)(1)(1)(4)(3)(3)(1)(1)Yuvnfg写作高分指南:雅思写作常用三类关联词汇总_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
Yuvnfg写作高分指南:雅思写作常用三类关联词汇总
上传于||文档简介
&&Yuvnfg写作高分指南:雅思写作常用三类关联词汇总
阅读已结束,如果下载本文需要使用0下载券
想免费下载更多文档?
定制HR最喜欢的简历
下载文档到电脑,查找使用更方便
还剩13页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢