首页 > 其他分享 >NV12图像格式叠加

NV12图像格式叠加

时间:2023-08-16 09:37:39浏览次数:44  
标签:tmp 图像格式 bm top 叠加 param pos NV12 rect

概述 图像叠加与音频叠加(混音)不同,人耳可以同时听到两种声音,因此混音时需要将两种信号都保留;但视频不同,图像一旦叠加,那么叠加区域人眼就只能看到最上层的图像。本文仅阐述对原始图像数据做修改的叠加方式,不涉及多个plane实现显示级别的图像叠加的知识。因此本文所述的图像叠加基本原理就是:顶层图像的像素直接替换掉底层图像的像素,从而新的图像会显示出叠加效果。   本文针对NV12像素格式图像的叠加(两张图片均为NV12格式),如果想扩展叠加其他图片,则需先将其他图片转为NV12,然后再进行叠加。如下提供bmp格式的顶图转换路径:   顶图(bmp) —> RGB24 —> NV12 —> 执行叠加操作   NV12格式阐述 nv12像素的存储格式可参考:https://blog.csdn.net/lyy901135/article/details/97934892 如下红框地方则为需要替换的区域,只要将如下两个红框内的值替换为对应“顶图”的值就完成了图像的叠加。那么首先就要确认两个红框内的每个像素的位置和红框的大小。   Y数据内的红框 顶图的宽高为144x48,根据NV12的像素组织特点可知,(x,y)对应的红框大小也为144x48,此处的(x,y)对应代码中的(pos_x, pos_y)。代码中rect_y表示Y数据中矩形框起始地址, rect_y = 底图基址(对应坐标原点) + w*y + x,对应代码rect_y = param->bm_buff + param->pos_y * param->bm_w + param->pos_x; 矩形框内每个像素点的位置关系:   /* i 遍历行,j遍历列, w=1920, h=1080*/ for (i=0; i < 48; i++) { /* i 行对应的基址 */ rect_tmp_y = rect_y + i*w; for (j=0; j < 144; j++) { Y(x+j, y+i) = rect_tmp_y + j; } }   UV数据内的红框 顶图的宽高为144x48,根据NV12的像素组织特点可知,(x’,y’)对应的红框大小则为144x24(每两行Y对应一行UV,所以高度减半:48 -> 24)。代码中rect_u表示UV数据中矩形框起始地址, rect_u = 底图基址(对应坐标原点)+ wh + yw/2 + x,对应代码rect_u = param->bm_buff + param->bm_w * param->bm_h + param->pos_y * param->bm_w / 2 + param->pos_x; 正是由于每两行Y才对应一行UV数据的特性,因此再计算偏移时累加的是w的一半,对应上述公式中+ y*w/2。 矩形框内每个像素点的位置关系:   /* i 遍历行,j遍历列, w=1920, h=1080*/ for (i=0; i < 48; i++) { /* i 行对应的uv基址,每两行才更新一次uv基址 */ if (i % 2 == 0) { rect_tmp_u = rect_u + i * param->bm_w / 2; rect_tmp_v = rect_tmp_u + 1; } /* 每两行Y对应一行UV,Y的偶数行对应UV行的U数据,并且U还要求在偶数列位置才取值; * Y的奇数行对应UV行的V数据,并且V还要求在奇数列才取值。 */ for (j=0; j < 144; j++) { if ((i % 2 == 0) && (j % 2 == 0)) { /* U(x+j, y+i)的位置, 偶数行,偶数列 */ rect_tmp_u += 2; } else if ((i % 2 == 1) && (j % 2 == 1)) { /* V(x+j, y+i)的位置, 奇数行,奇数列 */ rect_tmp_v += 2; } } }     代码 /*  * author: [email protected]  * date:   2019-8-2  */   typedef struct _overlayParam { unsigned char *bm_buff; //base map buff int bm_w; //base map width int bm_h; //base map height   unsigned char *top_buff; //top overlay buff int top_w; int top_h;   int pos_x; //position x [0, bm_w-top_w] int pos_y; }overlayParam;   void dump_overlayparam(overlayParam *param) { printf("=== overlayParam ===\n"); printf("\tbm_buff:%p\n", param->bm_buff); printf("\tbm_w:%d\n", param->bm_w); printf("\tbm_h:%d\n\n", param->bm_h); printf("\ttop_buff:%p\n", param->top_buff); printf("\ttop_w:%d\n", param->top_w); printf("\ttop_h:%d\n\n", param->top_h); printf("\tpos_x:%d\n", param->pos_x); printf("\tpos_y:%d\n", param->pos_y); }   /* 功能:nv12图像叠加 */ int pixel_format_nv12_overlay(overlayParam *param) { unsigned char *rect_y = NULL; unsigned char *rect_u = NULL; unsigned char *rect_v = NULL; unsigned char *rect_tmp_y = NULL; unsigned char *rect_tmp_u = NULL; unsigned char *rect_tmp_v = NULL; unsigned char *top_y = NULL; unsigned char *top_u = NULL; unsigned char *top_v = NULL; int i, j;   dump_overlayparam(param);   if (!param || !(param->bm_buff) || !(param->top_buff) || ((param->bm_w * param->bm_h) <= 0) || ((param->top_w * param->top_h) <= 0) || (param->pos_x < 0) || (param->pos_y < 0)) { printf("ERROR: %s input args invalid!\n", __func__); return -EINVAL; }   /* Position align */ param->pos_x = (param->pos_x / 2) * 2; param->pos_y = (param->pos_y / 2) * 2;   if (((param->pos_x + param->top_w) >= param->bm_w) || (((param->pos_y + param->top_h) >= param->bm_h))) { printf("ERROR: %s overlay img size invalid!\n", __func__); return -EINVAL; }   /* * 以(pos_x, pos_y)为起始点分别向右(x轴)和向下(y轴)画一个矩形框(图片左上角为原点), * 矩形框的款高就是顶图的宽高。该矩形框便是需要替换成顶图的区域。 */ rect_y = param->bm_buff + param->pos_y * param->bm_w + param->pos_x; rect_u = param->bm_buff + param->bm_w * param->bm_h + param->pos_y * param->bm_w / 2 + param->pos_x; rect_v = rect_u + 1; top_y = param->top_buff; top_u = param->top_buff + param->top_w * param->top_h; top_v = top_u + 1;   for (i = 0; i < param->top_h; i++) { rect_tmp_y = rect_y + i * param->bm_w; if (i % 2 == 0) { rect_tmp_u = rect_u + i * param->bm_w / 2; rect_tmp_v = rect_tmp_u + 1; }   for (j = 0; j < param->top_w; j++) { /* Replace y value */ *(rect_tmp_y + j) = *(top_y + i * param->top_w + j);   if ((i % 2 == 0) && (j % 2 == 0)) { *rect_tmp_u = *top_u; top_u += 2; rect_tmp_u += 2; } else if ((i % 2 == 1) && (j % 2 == 1)) { *rect_tmp_v = *top_v; top_v += 2; rect_tmp_v += 2; } } }   return 0; }   工程 工程地址(包含Makefile和测试使用的NV12图片): https://download.csdn.net/download/lyy901135/11467723   运行命令:./nv12_add_nv12 images/base_map.nv12 images/top.nv12 images/output.nv12 查看顶图命令:ffplay -s 144x48 -f rawvideo -pixel_format nv12 images/top.nv12 查看叠加后底图命令:ffplay -s 1920x1080 -f rawvideo -pixel_format nv12 images/output.nv12  

标签:tmp,图像格式,bm,top,叠加,param,pos,NV12,rect
From: https://www.cnblogs.com/kn-zheng/p/17633054.html

相关文章

  • 华为OD机试-区间叠加
       importjava.util.ArrayList;importjava.util.TreeMap;importjava.util.stream.IntStream;publicclassMain{publicstaticvoidmain(String[]args){Integer[][]lines=newInteger[5][2];lines[0]=newInteger[]{1,4};......
  • Android平台如何实时叠加电量信息和设备信号状态到GB28181接入端
    技术背景我们在Android平台实现GB28181设备接入,把摄像头和麦克风数据,采集过去,用于移动单兵、智能车载、智慧安防、智能家居、工业仿真等行业时,发现大多场景对视频水印的要求越来越高,从之前的固定位置静态文字水印、png水印等慢慢过渡到动态水印需求。本文,我们要探讨的是,除了常规的......
  • 686. 重复叠加字符串匹配
    给定两个字符串 a和b,寻找重复叠加字符串a的最小次数,使得字符串b成为叠加后的字符串a的子串,如果不存在则返回-1。注意:字符串"abc" 重复叠加0次是"",重复叠加1次是 "abc",重复叠加2次是 "abcabc"。 示例1:输入:a="abcd",b="cdabcdab"输出:3解释:a重复叠加三遍......
  • GDI+区域(Region)排除与路径(GraphicsPath)叠加透明
    1、区域(Region)排除 1CRectrt;2GetClientRect(&rt);34GraphicsPathpa;5pa.AddEllipse(0,0,rt.Width(),rt.Height());6Regionrg(Rect(0,0,rt.Width(),rt.Height()));7rg.Exclude(&pa);8graphics.FillRegion(&SolidBrush(Color(255,0,......
  • 如何将GIS矢量数据叠加到在线地图上?
    ​    通过以下方法可以将GIS矢量数据(dwg、shp、mdb、kml、geojson、gpx等格式)叠加到在线地图上。 方法/步骤下载GIS地图转换器(含地图浏览器)http://www.geosaas.com,下载并安装GIS数据转换器(含地图浏览器)。注册会员即可免费使用。2、点击【加载文件】菜单,选择要加......
  • 如何将数据库中的空间数据叠加到在线地图上?
    ​    通过以下方法可以将数据库中的空间数据叠加到在线地图上,支持SQLServer、MySQL、PostgreSQL。 方法/步骤下载GIS地图转换器(含地图浏览器)http://www.geosaas.com,下载并安装GIS数据转换器(含地图浏览器)。注册会员即可免费使用。2、点击【加载数据库】菜单,连接......
  • Vue3 响应式全局对象json 动态绑定界面三 (Div块样式 字符串叠加)
    效果 man.js  定义响应式全局对象 globalData//全局对象constglobalData=reactive({missedCallData:"",currentUserTel:"",})app.provide('globalData',globalData);在main.js的函数中改变missedCallData 的值从而改变界面列表//改变全局变量gl......
  • 跟着Environmental Research学作图:R语言ggplot2堆积柱形图叠加折线图(1)
    跟着EnvironmentalResearch学作图:R语言ggplot2堆积柱形图叠加折线图(1)简介在环境研究领域,数据可视化是非常重要的工具,可以帮助我们更好地理解和解释复杂的数据。本篇文章将教会你如何使用R语言中的ggplot2包创建堆积柱形图叠加折线图,以展示不同组别之间的关系和趋势。环境设......
  • NV21、NV12、YV12、RGB、YUV、RGBA、RGBX8888等图像色彩编码格式区别
    常用图像颜色编码格式NV21、NV12、YV12、RGB、YUV、RGBA、RGBX8888都是常见的图像颜色编码格式,它们之间的主要区别在于色彩空间和数据排列方式。NV21:NV21是Android系统使用的一种图像颜色编码格式,它采用的是YUV4:2:0的采样方式,意味着垂直方向上每两个像素采样一次,水平方向上每个像......
  • 叠加态和超级定位:量子世界的奇特现象
    亲爱的读者,欢迎回到我们的量子力学系列文章。在前几篇文章中,我们介绍了量子力学的起源、基本概念以及波函数作为描述量子世界的数学工具。今天,我们将深入探索量子力学中的奇特现象,包括叠加态和超级定位。在量子力学中,叠加态是一种非常特殊的态。当一个量子系统可以处于多个可能......