音视频 - YUV像素处理

将一帧YUV图像变成黑白照,只保留Y数据(灰度图)

我们把UV数据去掉,只写入Y数据,那么只剩下Y数据,打开图片的时候选择一定要选择以“Y”格式打开,而不是“YUV420”格式打开。

#include <stdio.h>
#include <stdlib.h>

#define startImage "lena_256x256_yuv420p.yuv"

int main()
{
        FILE *fp  = NULL;
        FILE *fp1 = NULL;

        unsigned char *readBuf;
        readBuf = (unsigned char *)malloc(256*256*3/2);

        fp  = fopen(startImage,"rb+");
        fp1 = fopen("new_256x256_yuv420p.y","wb+");

        fread(readBuf,1,256*256,fp);

        fwrite(readBuf,1,256*256,fp1);

        free(readBuf);
        fclose(fp);
        fclose(fp1);
        return 0;
}

用yuv420格式打开的样子
在这里插入图片描述

用y格式打开的样子
在这里插入图片描述

将一帧YUV图像变成黑白照,将UV置0(灰度图)

上面只保存了Y数据,准确来说不算是YUV图像,我们不把UV拿掉,将U和V的数据修改为0就代表无色,让他置0也可以让他呈现黑白照。

U、V是图像中的经过偏置处理的色度分量。在偏置处理前,它的取值范围是-128-127,这时,把U和V数据修改为0代表无色。在偏置处理后,它的取值范围变成了0-255,所以这时候需要取中间值,即128。所以我们下面要将U和V数据修改为128

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define outPutFileName "testGrey.yuv"

int testYuv420Grey(char *fileName, int width, int height)
{
    FILE *fp;
    FILE *fp1;
    unsigned char *readBuf;
    readBuf = (unsigned char *)malloc(width*height*3/2);
    fp = fopen(fileName, "rb+");
    fp1 = fopen(outPutFileName, "wb+");

    /* read yuv file */
    fread(readBuf, 1, width*height, fp);

    /* memset U and V*/
    memset(readBuf+width*height, 128, width*height/2);

    /* create new file */
    fwrite(readBuf, 1, width*height*3/2, fp1);
	
	free(readBuf);
    fclose(fp);
    fclose(fp1);
    return 0;
}

int main()
{
    testYuv420Grey("lena_256x256_yuv420p.yuv", 256, 256);
    return 0;
}

在这里插入图片描述

将一帧YUV图像U值置0,其他不动

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define outPutFileName "test0u.yuv"

int testYuv420Grey(char *fileName, int width, int height)
{
    FILE *fp;
    FILE *fp1;
    unsigned char *readBuf;
    readBuf = (unsigned char *)malloc(width*height*3/2);
    fp = fopen(fileName, "rb+");
    fp1 = fopen(outPutFileName, "wb+");

    /* read yuv file */
    fread(readBuf, 1, width*height, fp);

    /* memset U*/
    memset(readBuf+width*height, 128, width*height/4);

    /* create new file */
    fwrite(readBuf, 1, width*height*3/2, fp1);
	
	free(readBuf);
    fclose(fp);
    fclose(fp1);
    return 0;
}

int main()
{
    testYuv420Grey("lena_256x256_yuv420p.yuv", 256, 256);
    return 0;
}

在这里插入图片描述

将一帧YUV图像V值置0,其他不动

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define outPutFileName "test0v.yuv"

int testYuv420Grey(char *fileName, int width, int height)
{
    FILE *fp;
    FILE *fp1;
    unsigned char *readBuf;
    readBuf = (unsigned char *)malloc(width*height*3/2);
    fp = fopen(fileName, "rb+");
    fp1 = fopen(outPutFileName, "wb+");

    /* read yuv file */
    fread(readBuf, 1, width*height, fp);

    /* memset V */
    memset(readBuf+width*height*5/4, 128, width*height/4);

    /* create new file */
    fwrite(readBuf, 1, width*height*3/2, fp1);
	
	free(readBuf);
    fclose(fp);
    fclose(fp1);
    return 0;
}

int main()
{
    testYuv420Grey("lena_256x256_yuv420p.yuv", 256, 256);
    return 0;
}

在这里插入图片描述

将Y(亮度)值减半

#include <stdio.h>
#include <stdlib.h>

#define startImage "lena_256x256_yuv420p.yuv"

int main()
{
        FILE *fp  = NULL;
        FILE *fp1 = NULL;
        int  nIdx = 0;

        unsigned char *readBuf;
        readBuf = (unsigned char *)malloc(256*256*3/2);

        fp  = fopen(startImage,"rb+");
        fp1 = fopen("halfbrightness.yuv","wb+");

        fread(readBuf,1,256*256*3/2,fp);

        for(nIdx=0;nIdx<256*256;nIdx++)
        {
                readBuf[nIdx] = readBuf[nIdx]/2;
        }

        fwrite(readBuf,1,256*256*3/2,fp1);

        free(readBuf);
        fclose(fp);
        fclose(fp1);
        return 0;
}

在这里插入图片描述

自己制作一帧YUV420灰阶测试图

U和V数据置为128,将Y数据递增即可。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define OP_File "GreyTest.yuv"
#define yMAX 255

/**
 * Get gray scale test diagram
 * @param width :  输出图片的宽
 * @param height: 输出图片的高
 * @param num   :  输出灰阶测试图条数
 *
 */
int getGreyTest(int width,int height,int num)
{
        FILE *fp = NULL;
        int y_data[32];
        int new_ydata = 0;
        int yMAX_distance = yMAX/num;
        int width_distance = width/num;
        long FILE_Size = width*height*3/2;

        unsigned char *buf;
        buf = (unsigned char *)malloc(FILE_Size);

        fp = fopen(OP_File,"wb+");
        if(fp == NULL)
        {
                printf("fopen error!\n");
                return -1;
        }

        for(int i = 0;i<num;i++)
        {
                y_data[i] = new_ydata;
                new_ydata += yMAX_distance;
                printf("Y = %d U = %d V = %d\n",y_data[i],128,128);
        }

        memset(buf,0,FILE_Size);
        for(int h=0;h<height;h++)
        {
                for(int cnt = 0;cnt<num;cnt++)
                {
                        memset(buf + cnt*width_distance + h*width,y_data[cnt]
                                        ,width_distance);
                }

        }

        memset(buf+height*width,128,height*width/2);

        fwrite(buf,1,FILE_Size,fp);
        printf("Generate success\n");

        free(buf);
        fclose(fp);

}
int main()
{
        int num = 0;
        printf("please input num:\n");
        scanf("%d",&num);
        getGreyTest(352,288,num);
        return 0;
}

下图中有四列,每列还会分为行(h * width)和列(cnt * width_distance)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

遇到的问题

注意:因为CSDN编辑格式我给 * 旁边各加了个空格

刚开始学习的时候,看半天fwritefwrite(pic+w * h,1,w * h/4,fp2)没看懂是啥意思,pic+w * h就是pic从w*h开始操作数据

其中前w * h Byte存储Y,接着的w * h * 1/4 Byte存储U,最后w * h * 1/4 Byte存储V

参考文档:
音视频入门(一) - YUV像素处理
yuv rgb 像素格式1
视音频数据处理入门:RGB、YUV像素数据处理.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只小阿大:)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值