图像格式互转

2023-10-27

一:灰度图转YUV

由于工作需要,经常接触12bit灰度数据,因此在这里将数据的处理记录下来。

经常接触的是sensor输出的12bit灰度数据,按照需求经常会将这份数据转换成其他格式,如16bit灰度数据(高4bit为0),YUV数据等,其中在转成YUV之前需要先把每个piel的12bit数据变成8bit,即将低4bit舍弃,然后补齐UV数据。

以下代码为将16bit的灰度数据转成YUV格式,由于UV数据都置为128,因此对于YUV420的各种格式的处理也都是相同的了。

#include <stdio.h>

unsigned short grayraw[640*480];	//输入的16bit 灰度数据
unsigned char gray_8bit[640*480];	//输出的8bit 灰度数据
unsigned char gray_yuv[640*480*3/2];//输出的YUV数据,NV12或者NV21等

int main()
{

	int i = 0;
	unsigned short pixel;
	unsigned short temp;
	
	char gray_file[256];
	sprintf(gray_file, "gray_raw");
	FILE *file_grayraw = fopen(gray_file, "rb");
	fread(grayraw, 1, 640 * 480 * 2 , file_grayraw);
	fclose(file_grayraw);
	
	for(i = 0; i < 640*480; i++)
	{
		pixel = grayraw[i];
		temp = (pixel << 4) >> 8;
		gray_8bit[i] = (unsigned char)temp;
		gray_yuv[i] = (unsigned char)temp;
	}
	
	//to 8bit
	char gray_out[256];
	sprintf(gray_out, "grayout.raw");
	FILE *grayout_file = fopen(gray_out, "wb+");
	fwrite((void*)gray_8bit, 1, 640*480, grayout_file);
	fclose(grayout_file);
	
	//to yuv
	memset(gray_yuv+640*480, 128, 640*480/2);
	char gray_yuv_out[256];
	sprintf(gray_yuv_out, "640_480.yuv");
	FILE *grayyuv_file = fopen(gray_yuv_out, "wb+");
	fwrite((void*)gray_yuv, 1, 640*480*3/2, grayyuv_file);
	fclose(grayyuv_file);
			
	return 0;
}

二:NV12转YUV422(UYVY)

NV12格式属于YUV420  即 YYYYYYYYYYYYYYY.....UVUVUVUVUVUV

下面的代码用于将1920*1080的NV12数据转换成UYVY的YUV422格式

原理是将YUV420的由上下两行相邻的共4个Y共享一个U转变为YUV422每行相邻的两个Y共享一个U,具体方式为将YUV420的第一行的Y对应的U(第二行Y也对应着这个U)复制一行,也就是两行的U,其中一行对应YUV422第一行的Y,另一行对应YUV422第二行的Y,如此类推,那么YUV420的第3,4行的Y对应的960个U也是复制成为1920个,分别用于对应YUV422的3,4行的Y。同理,V也是如此。

#include <stdio.h>

char image_buffer[460800];
char image_big_buffer[3110400];
char image_yuv422_buffer[4147200];

static void NV12_to_UYVY(char* src, char* dst, int width, int height)  
{
	char *yuv420_y = src;
	char *yuv420_u = src + width * height;
	char *yuv420_v = src + width * height + 1;
	char *yuv422   = dst;
	
	int i = 0;
	int j = 0;
	
	char u_buf[518400];
	char v_buf[518400];
	memset((void*)u_buf, 0, 518400);
	memset((void*)v_buf, 0, 518400);

	for(i = 0, j = 0; i < 518400; i++)
	{
		u_buf[i] = *(yuv420_u + j);
		j+=2;
	}

	for(i = 0, j = 0; i < 518400; i++)
	{
		v_buf[i] = *(yuv420_v + j);
		j+=2;
	}

	char uu_buf[1036800];
	char vv_buf[1036800];
	memset((void*)uu_buf, 0, 1036800);
	memset((void*)vv_buf, 0, 1036800);

	int uWidth = width / 2;
	int uHeight = height / 2;

	for(i = 0; i < uHeight; i++)
	{
		memcpy((void*)uu_buf + i * 2 * uWidth, u_buf + i * uWidth, uWidth);
		memcpy((void*)uu_buf + i * 2 * uWidth + uWidth, u_buf + i * uWidth, uWidth);
	}

	for(i = 0; i < uHeight; i++)
	{
		memcpy((void*)vv_buf + i * 2 * uWidth, v_buf + i * uWidth, uWidth);
		memcpy((void*)vv_buf + i * 2 * uWidth + uWidth, v_buf + i * uWidth, uWidth);
	}
	
	for(i = 1; i < width * height * 2;)
	{
		*(yuv422 + i) = *yuv420_y++;
		i += 2;
	}

	for(i = 0, j = 0; i < width * height * 2;)
	{
		*(yuv422 + i) = uu_buf[j];
		i += 4;
		j++;
	}

	for(i = 0, j = 0; i < width * height * 2;)
	{
		*(yuv422 + i + 2) = vv_buf[j];
		i += 4;
		j++;
	}
}
 
int main()
{
	char *originimage = "yuv420_19201080.bin";
	FILE *imagefile = fopen(originimage,"a+");
	if(NULL == imagefile)
	{
		printf("open file[%s] failed!\n", originimage);
		return -1;
	}
	memset((void*)image_big_buffer,0,3110400);
	fread((void*)image_big_buffer, 1, 3110400, imagefile);
	fclose(imagefile);
	
	memset((void*)image_yuv422_buffer,128,4147200);
	NV12_to_UYVY(image_big_buffer, image_yuv422_buffer, 1920, 1080);
	char *big422image = "big422.yuv";
	FILE *fp_422big = fopen(big422image,"a+");
	if(NULL == fp_422big)
	{
		printf("open file[%s] failed!\n", big422image);
		return -1;
	}
	
	fwrite((void*)image_yuv422_buffer, 1, 4147200, fp_422big);
	fclose(fp_422big);	
}

三:YUV444(YUVYUVYUV)转NV12

void YUV444ToNV12(unsigned char *yuv, unsigned char *nv12, int width, int height)
{
	int i = 0;
	int j = 0;
	int k = 0;

	/* copy y data */
	for(i = 0; i < height; i++)
	{
		for(j = 0; j < width; j++)
		{
			*(nv12 + i * width + j) = *(yuv + 3 * k);
			k++;
		}
	}

	unsigned char * ptr_u = nv12 + width * height;
	unsigned char * ptr_v = ptr_u + 1;

	int uv_height = height /2;

	for(i = 0; i < uv_height; i++)
	{
		k = 0;
		for(j = 0; j < width;)
		{
			*(ptr_u + i * width + j) = *(yuv + i * width * 3 * 2 + k * 6 + 1);
			*(ptr_v + i * width + j) = *(yuv + i * width * 3 * 2 + k * 6 + 2);
			j+=2;
			k++;
		}
	}

}

四:BGR888转YUV444(YUVYUVYUV)

void BGR888ToYUV444(unsigned char *yuv, unsigned char *bgr, int pixel_num)
{
    int i = 0;

    for (i = 0; i < pixel_num; ++i) {
        unsigned char b = bgr[i * 3];
        unsigned char g = bgr[i * 3 + 1];
        unsigned char r = bgr[i * 3 + 2];

        // 1. Multiply transform matrix (Y′: unsigned, U/V: signed)
        unsigned short y_tmp = 76 * r + 150 * g + 29 * b;
        unsigned short u_tmp = -43 * r - 84 * g + 127 * b;
        unsigned short v_tmp = 127 * r - 106 * g - 21 * b;

        // 2. Scale down (">>8") to 8-bit values with rounding ("+128") (Y′: unsigned, U/V: signed)
        y_tmp = (y_tmp + 128) >> 8;
        u_tmp = (u_tmp + 128) >> 8;
        v_tmp = (v_tmp + 128) >> 8;

        // 3. Add an offset to the values to eliminate any negative values (all results are 8-bit unsigned)
        yuv[i * 3] = (unsigned char) y_tmp;
        yuv[i * 3 + 1] = (unsigned char) (u_tmp + 128);
        yuv[i * 3 + 2] = (unsigned char) (v_tmp + 128);
    }
}

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

图像格式互转 的相关文章

  • js中获取body html元素

  • myBatis实现多对多操作的sql语句

    文章目录 1 角色对人 2 人对角色 3 创建数据库语句 总结 1 角色对人 实现角色对人的多对多查询 将有角色的人筛选出来 实现角色对人的多对多查询 SELECT u r id AS rid r role name r role desc
  • Go_方法、方法重写、方法与函数的区别

    方法 方法是绑定在自定义类型上的 常用在结构体上 方法方法不能直接调用 只能通过所绑定s类型的变量来调用 因为方法是和类型做关联的 方法是值拷贝的传递方式 如果希望改变结构体变量的值 需要通过结构体指针实现 方法名首字母大写为公共 小写为私
  • Tomcat的下载及其使用

    目录 一 Tomcat是什么 二 Tomcat的下载安装 1 在搜索框搜索Tomcat 2 下载 3 Tomcat里面的一些具体内容 三 运行Tomcat 1 直接点击脚本运行 2 使用浏览器访问 3 部署页面到Tomcat 一 Tomca
  • Win10如何彻底删除360的办法

    很多用户在购买电脑或者重装系统之后都会给电脑安装360安全卫士 其实360是一款知名的流氓软件 感觉进行了彻底的删除工作 其实还残留了很多 那Win10如何彻底删除360呢 下面小编就来给大家展示一下具体的办法 2022新版Win10 64
  • SQL Part3 --- 聚合操作符

    SQL 聚合操作符 聚合操作符 Aggregate Operators COUNT A SUM A AVG A MAX A MIN A GROUP BY and HAVING 聚合操作符 Aggregate Operators Sailor
  • 在Spring-Boot中进行单元测试

    要进行单元测试 需要引入依赖
  • 关于stl容器的迭代器失效问题

    场景 在项目中使用stl容器的时候 多线程环境下出错 调试很久发现问题是使用容器的时候由于容器扩容导致的线程不安全 还有扩容导致的迭代器失效问题 于是就想着把迭代器失效的问题总结一下 场景重现1 我在项目开发中使用vector时 由于扩容导
  • redis-benchmark工具入门之生成压测数据写入redis

    前言 redis benchmark是Redis自带的基准测试工具 可以用来压测redis目标集群的性能 也可以生成测试数据 方便测试 安装redis benchmark 本文Ubuntu系统 安装工具包 sudo apt get inst
  • 怎样正确查看Linux的内存占用情况

    了个24小时的稳定性测试 探讨了Linux的Mem使用情况 看内存最方便的命令是free m 如 root host free m total used free shared buffers cached Mem 1024 1005 19
  • 100ask_imx6ull视频监控项目-内网穿透(六)

    100ask imx6ull视频监控项目 内网穿透 六 在前面的课程 Ffmpeg和Nginx都运行在开发板上 拉流端只能在同一个局域网内 不能通过局域网外的互联网访问Ngnix 想在任何地方 都可以通过互联网访问Nginx 怎么办 方法1
  • scikit-learn kmeans++

    聚类分析在客户细分中极为重要 有三类比较常见的聚类模型 K mean聚类 层次 系统 聚类 最大期望EM算法 在聚类模型建立过程中 一个比较关键的问题是如何评价聚类结果如何 会用一些指标来评价 原文 http blog csdn net s
  • 【控制工程】单位跃阶响应与传递函数

    一 一阶线性时不变系统的单位阶跃响应 1 单位跃阶 Unit Step 单位阶跃响应是指系统在 单位阶跃信号 的作用下所产生的 零状态响应 作用 可以反应系统的动态特性 所以是分析系统时十分重要和常用的响应类型 注意 单位阶跃函数在t 0这
  • 【数模】TOPSIS法优劣解距离法

    TOPSIS的介绍 利用原始数据的信息 其结果能精确地反映各评价方案之间的差距 层次分析法的局限性 评价的决策层不能太多 否则n很大 判断矩阵和一致矩阵差异可能会很大 平均随机一致性指标RI的表格中n最多是15 TOPSIS步骤 1 将原始
  • 8645 归并排序(非递归算法)

    8645 归并排序 非递归算法 如果你看到和我的贼相似的 那我就是抄的 别骂了 代码实现 include
  • Spring MVC的高级功能(异常处理器,拦截器,文件操作)

    目录 异常处理 拦截器 文件上传和下载 1 异常处理 简单异常处理 自定义异常处理 异常处理注解 简单异常处理器 HandlerExceptionResolver接口 如果希望对Spring MVC中所有异常进行统一处理 可以使用Sprin
  • 卷积层的主要作用_关于卷积的一些基本概念理解(不仅仅是卷积)

    卷积就是相乘再相加 卷积核需要翻转 方便对图像提取特征或者是其他的一些目的 比如边缘检测 除了原图像之外 另一个被用来相乘相加的就被称为是卷积核 同时 卷积核也被称为滤波器 卷积的更加详细生动的解释 https www cnblogs co
  • 百度开源PaddleOCR 超轻量级中文OCR模型,总模型仅8.6M 测试

    版本 https github com PaddlePaddle PaddleOCR git 可以与同样轻量级的ocr识别比较 百度的要好一点 https blog csdn net jy1023408440 article details
  • JAVA--数组元素查找方法

    从头遍历 没有约束条件 数组元素的查找方法 public static int getIndex int arr int key for int i 0 i
  • 如何才能让区块链技术避免成为一个口号?

    区块链是目前互联网上最受热捧的技术 即使是在今年年初数字货币的低迷和ICO被监管部门明确禁止 技术能否落地受到质疑 但是区块链的大火仍在弥漫 现在 这把火已经烧到了很多领域 从金融再到医疗 能源 防伪 溯源 音乐 电影等行业 无不意外的 都

随机推荐

  • 实战Elastic Stack分析K8S应用日志--交付kibana

    Kibana是一个开源的分析和可视化平台 用于和Elasticsearch一起工作 用Kibana来搜索 查看 并和存储在Elasticsearch索引中的数据进行交互 可以轻松地执行高级数据分析 并且以各种图标 表格和地图的形式可视化数据
  • TNN行业首发Arm 32位 FP16指令加速,理论性能翻倍

    转自 https cloud tencent com developer article 1774206 https www cnblogs com zhangshenghui p 11825760 html FP16是半精度浮点格式 相比
  • RuntimeError:An attempt has been made to start a new process before thecurrent process has finished。

    报错 RuntimeError An attempt has been made to start a new process before the current process has finished its bootstrappin
  • MPDA:基于Domain Adaption的V2X协同感知(3D目标检测)

    标签 Domain gap CP without sharing the model information Intermediate Fusion 3D Object Detection 论文标题 Bridging the Domain
  • 前端編譯 : Babel 基礎入門

    前端編譯 Babel 基礎入門 前言 正文 什麼是 Babel Babel 模塊介紹 babel cli 從項目中運行 Babel CLI babel register babel node babel core 配置 Babel babe
  • OpenCV 人脸检测(HAAR/DNN)

    1 HAAR级联检测 include
  • 深入理解ThreadLocal源码

    1 预备知识 强软弱虚引用 在Java中有四种引用的类型 强引用 软引用 弱引用 虚引用 设计这四种引用的目的是可以用程序员通过代码的方式来决定对象的生命周期 方便GC 强引用 强引用是程序代码中最广泛使用的引用 如下 Object o n
  • NoSQL数据库详细介绍

    一 NoSQL发展历史 二 什么是NoSQL 三 为什么使用NoSQL 四 NoSQL vs RDBMS 五 常见的数据库 六 NoSQL的四种类型 1 键值 Key Value 存储 2 文档 Document Oriented 存储 3
  • C语言学生信息管理程序

    程序要求如下 实验源码 要求实现学生信息的查找 添加 删除 修改 浏览 保存 从文件读取7 个功能 每个功能模块均能实现随时从模块中退出 而且可以选择不同的方式实 现所需功能 从而完成一个学生管理系统所需功能 2 要使用结构体来实现对学生信
  • pytorch学习笔记——timm库

    当使用ChatGPT帮我们工作的时候 确实很大一部分人就会失业 当然也有很大一部分人收益其中 我今天继续使用其帮我了解新的内容 也就是timm库 毫不夸张的说 Chat GPT比百分之80的博客讲的更清楚更好 仅次于源码 当提到计算机视觉的
  • centos8使用grubby修改内核启动参数

    grubby是一个用于更新和显示有关各种体系结构特定的引导程序的配置文件信息的命令行工具 它主要设计用于安装新内核并需要查找有关当前引导环境的信息的脚本 同时也可以对启动内核的各项信息参数进行修改 本文主要介绍如何在centos8中使用gr
  • 前端接入sentry可能会遇到的坑

    前端接入sentry可能会遇到的坑 多个项目下 sourcemap 会混乱 解决 在配置版本的时候除了填写版本号 最好在版本号添加该项目名称前缀 sourcemap 源码定位不了 解决 1 仔细查看对应的路径是否正确 2 nginx 是否设
  • 关于 Linux 看这篇就够了

    流量如水 文章就是一个瓶子 标题是瓶口 内容是瓶身 瓶子装水有多快依赖瓶口大小 瓶子装水有多少依赖瓶身大小 关于 Linux 看这篇就够了 操作系统概述 Linux 操作系统安装 Linux 文件系统 Linux 命令操作 Linux 权限
  • Just demo test

    MainWindow MainWindow QWidget parent QMainWindow parent ui new Ui MainWindow ui gt setupUi this for int i 0 i lt 3 i QLa
  • Collections中的双向队列-deque

    双端队列 可以快速的从另外一侧追加和推出对象 deque是一个双向链表 针对list连续的数据结构插入和删除进行优化 它提供了两端都可以操作的序列 这表示在序列的前后你都可以执行添加或删除操作 双向队列 deque 对象支持以下方法 1 a
  • easyExcel 用XSSF画斜线

    注册拦截器 WriteSheet writeSheet EasyExcel writerSheet 0 sheet1 registerWriteHandler new CustomCellWriteHandler head header b
  • CF1604 C. Di-visible Confusion(lcm)

    include
  • 《Data Cleansing for Models Trained with SGD》笔记

    1 在其 appendix B 中证 Lemma 7 时说由于 1 s
  • AD18设置默认线宽

    点击设计 gt 规则 选择Routing gt Width 在这里设置
  • 图像格式互转

    一 灰度图转YUV 由于工作需要 经常接触12bit灰度数据 因此在这里将数据的处理记录下来 经常接触的是sensor输出的12bit灰度数据 按照需求经常会将这份数据转换成其他格式 如16bit灰度数据 高4bit为0 YUV数据等 其中