• yuv420p转RGB


    yuv420是用4个byte存储4个Y的信息,用1个Byte存储U的信息,一个Byte存储V的信息,
    这4个Y共用这2个U和V ,也就是用6个Byte 存储4个像素信息,也就是一个像素需要12个Bits(6*8/4),也就是12bpp。
    注意yuv420p里面的p是指planar,也就是分层存储,先存全部Y的信息,然后是U的信息,最后是V的信息,
    或者这样说: 如果把一个图片按yuv420p的格式保存为二进制数据文件,那么把这个文件均分为6份,那么前面的4份是Y,第5份是U,第6份是V。

    以下程序的流程是:

    1 使用 ffmpeg 先将一张图片保存为 yuv420p的数据文件。
    2 使用下面的程序读取此文件,然后将yuv数据转为rgb,最后使用opencv保存为jpg格式的图片。
    3 主要是熟悉yuv420p的数据格式,以及熟悉yuv如何转为RGB。
    4 最后就是使用opencv将RGB数据保存为图片,注意opencv是需要BGR的数据.

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    using namespace cv;
    
    #define  IMAGE_W 1280
    #define  IMAGE_H 720
    
    #define  FILE_NAME "output420.yuv"
    
    int convert_yuv_to_rgb_pixel(int y, int u, int v) {
    	unsigned int pixel32 = 0;
    	unsigned char *pixel = (unsigned char*) &pixel32;
    	int r, g, b;
    	r = y + (1.370705 * (v - 128));
    	g = y - (0.698001 * (v - 128)) - (0.337633 * (u - 128));
    	b = y + (1.732446 * (u - 128));
    
    	if (r > 255)
    		r = 255;
    	if (g > 255)
    		g = 255;
    	if (b > 255)
    		b = 255;
    	if (r < 0)
    		r = 0;
    	if (g < 0)
    		g = 0;
    	if (b < 0)
    		b = 0;
       //注意opencv是需要BGR的数据
    	pixel[0] = b;  // blue
    	pixel[1] = g;  // green
    	pixel[2] = r;  //red
    	return pixel32;
    }
    
    int convert_yuv420p_to_rgb888_buffer(unsigned char *yuv, unsigned char *rgb,
    		unsigned int width, unsigned int height) {
    	unsigned int pixel32;
    	unsigned char *ptr = rgb;
    	int y0, y1, y2, y3, u, v;
    	int i = 0;
    	unsigned char *a = yuv + width * height * 0;
    	unsigned char *b = yuv + width * height * 1;
    	unsigned char *c = yuv + (int) (width * height * 1.25);
    
    	while (i < width * height) {
    		i += 4;
    		u = *(b++);
    		v = *(c++);
    		for (int j = 0; j < 4; j++) {
    			y0 = *(a++);
    			pixel32 = convert_yuv_to_rgb_pixel(y0, u, v);
    			*(ptr++) = (pixel32 & 0x000000ff);
    			*(ptr++) = (pixel32 & 0x0000ff00) >> 8;
    			*(ptr++) = (pixel32 & 0x00ff0000) >> 16;
    		}
    
    	}
    	return 0;
    }
    
    /**
     * 	 yuyv420p to rgb to jpg.
     *   ffmpeg -i in.jpg -pix_fmt yuv420p output420.yuv -y
     *   ffmpeg  -pix_fmts
     *   yuyv420 use 12bits to store 1 pixes.
     *
     */
    int main() {
    	int ret;
    	int fd = open(FILE_NAME, O_RDWR);
    	if (ret == -1) {
    		perror("open");
    		return -1;
    	}
    	unsigned char yuv[IMAGE_W * IMAGE_H * 3 + 1000];
    
    	ret = read(fd, yuv, IMAGE_W * IMAGE_H * 3 + 1000);
    	if (ret == -1) {
    		perror("read");
    		return -1;
    	}
    
    	assert(ret == IMAGE_W * IMAGE_H * 12 / 8);
    	char rgb24[IMAGE_W * IMAGE_H * 3];
    	convert_yuv420p_to_rgb888_buffer((unsigned char*) yuv,
    			(unsigned char*) rgb24,
    			IMAGE_W, IMAGE_H);
    	Mat image(IMAGE_H, IMAGE_W, CV_8UC3, rgb24);
    	imwrite("output.jpg", image);
    	cout << "success" << endl;
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109

    如果有任何问题,欢迎评论。

  • 相关阅读:
    中科大郑烇、杨坚老师《计算机网络-自顶向下方法》课程 第2章 应用层笔记
    【用户实践】openGauss5.0在某省医保局实时数仓应用
    Matlab绘制面积堆叠图/面积图
    计算机毕业设计springboot加班管理系统的设计与实现 zis2d源码+系统+程序+lw文档+部署
    ROS+PX4+mavros+qgc环境搭建笔记
    YOLOv5训练自己的voc数据集
    【c++&leetcode】1382. Balance a Binary Search Tree
    使用nexus上传jar包图文教程
    MyBatis多条件查询、动态SQL、多表操作、注解开发详细教程
    【简单教程】利用Net2FTP构建免费个人网盘,实现便捷的文件管理
  • 原文地址:https://blog.csdn.net/oHeHui1/article/details/127984399