文章目录

  • NV21格式图像旋转
    • 基础知识
    • 逆时针旋转90°

NV21格式图像旋转

刚刚接触Android开发,开始学习一些图像像素格式,需要完成 NV21 的图像进行旋转,这里我们将从原理开始分析,分享一下我对 NV21 图像旋转的理解与实现。

基础知识

在开始旋转 NV21 图像时,需要对 RGB 与 YUV 图像的存储方式有一定的了解,没有概念的同学可以看看这儿:

常用视频像素格式NV12、NV2、I420、、Yv12、YUYV

NV21 属于 YUV420,其采样方式如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GSO2CMrK-1649641050030)(//img-blog.csdn.net/20180321201019127?watermark/2/text/Ly9ibG9nLmNzZG4ubmV0L2Nnd2FuZ18xNTgw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)]

上图为一个 4*4 的图像,即宽度 width=4,高度 height=4;
于是,其图像数据特点是四个 Y 共用一个组 UV,且共用方式是 Y1、Y2、Y5、Y6 公用 (UV)1,而 Y3、Y4、Y7、Y8 共用 (UV)2,这是由它的采样方式得到的<共用方式很重要>。
需要记住的是:在内存中,YUV 的存储一般为,Y 是连续存储,而 UV 打包一起存储,即在内存中其存储方式如下:当用一个一维数组 data 来保存该数据时,其在内存中的分布则是:

data= {Y1,Y2,Y3,Y4,Y5,Y6,Y7,Y8,Y9,Y10,Y11,Y12,Y13,Y14,Y15,Y16,V1,U1,V2,U2,V3,U3,V4,U4}

这么看好像不是很好懂,咱么换种方式:

{Y1,  Y2,  Y3,  Y4,Y5,  Y6,  Y7,  Y8,Y9,  Y10, Y11, Y12,Y13, Y14, Y15, Y16,V1,  U1,  V2,  U2,V3,  U3,  V4,  U4
}

同样还是一维数组,只是这次根据图像的宽度和高度把一维数组的堆放方式换一下,可以看到 Y1~Y16 即为 16 个像素的Y分量的值(记住:4*4 的图像),而 Y1、Y2、Y3、Y4共用 V1、U1。

逆时针旋转90°

为了对上午进行逆时针旋转,首先将旋转后图像数据在内存中的分布画出来,一开始我画出的图像如下:

{Y4,  Y8,  Y12,  Y16,  U2,  U4Y3,  Y7,  Y11,  Y15,  V2,  V4Y2,  Y6,  Y10,  Y14,  U1,  U3Y1,  Y5,  Y9,   Y13,  V1,  V3
}<错误方式...>

当时我怎么也没有想明白,这样旋转后,即使 Y1、Y2、Y5、Y6 依然可以共用 V1、U1,但它在内存中还如何存储?因为这个数据在内存中使用一个一维数组连续存储,这样的话岂不是 Y 分量的存储断开了?…
之后,从采样方式出发想了想之后,或许应该是把 Y 分量和 UV 分量分开旋转,如下:

{ Y4,  Y8,  Y12,  Y16,  Y3,  Y7,  Y11,  Y15,  Y2,  Y6,  Y10,  Y14,  Y1,  Y5,  Y9,   Y13,  V2,  U2,  V4,   U4,V1,  U1,  V3,   U3
}
< V 和对应的 U 应该为一个整体共同旋转>

于是,Y4、Y8、Y3、Y7 仍然共用 V2、U2;Y2、Y6、Y1、Y5 仍然共用 V1、U1;

下面给出一段简单的测试代码:

// 定义类
class YUVImage{public:YUVImage();int rotateTest(const int* dataIn, int width, int height, int degree, int* dataOut);int showIamge(const int* data, int width, int height);
};
int YUVImage::rotateTest(const int *dataIn, int width, int height, int degree, int *dataOut)
{int k = 0;int height2 = (int) (1.5 * height);// rotate Yfor (int i = width - 1; i >= 0; --i){for (int j = 0; j < height; ++j){*(dataOut + k) = *(dataIn + j * width + i);++k;}}// rotate UVfor (int i = width - 1; i > 0; --i){for (int j = height; j < height2; ++j){*(dataOut + k) = *(dataIn + j * width + i - 1);++k;*(dataOut + k) = *(dataIn + j * width + i);++k;}--i;}return 0;
}
// show image
int YUVImage::showIamge(const int *data, int width, int height)
{int height2 = int(1.5 * height);for (int i = 0; i < height2; ++i){for (int j = 0; j < width; ++j){cout << *(data + i * width + j) << " ";}cout << endl;}cout << endl;return 0;
}

测试模块

int _tmain(int argc, _TCHAR *argv[])
{int old[48] = {11, 12, 13, 14, 15, 16, 17, 18, 21, 22, 23, 24, 25, 26, 27, 28, 31, 32, 33, 34, 35, 36,37, 38, 41, 42, 43, 44, 45, 46, 47, 48, 81, 82, 83, 84, 85, 86, 87, 88, 91, 92, 93, 94,95, 96, 97, 98};//NV21图像宽度width=8,高度height=4int *pOld = old;int width = 8;int height = 4;int height2 = (int) (1.5 * height);//NV21 image rotate testint temp1[48] = {0};int *pRot = temp1;YUVImage nv21;nv21.rotateTest(pOld, width, height, 90, pRot);cout << "Original NV21 data:" << endl;nv21.showIamge(pOld, width, height);cout << "Rotate NV21 data:" << endl;nv21.showIamge(pRot, width, height);
}

下面是测试结果:

[外链图片转存中...(img-i90eW5tQ-1649641050032)] 原始数据 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sGJ6DdST-1649641050032)(//img-blog.csdn.net/20180321203852456?watermark/2/text/Ly9ibG9nLmNzZG4ubmV0L2Nnd2FuZ18xNTgw/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)] 旋转后的数据

之后,做了一些 NV21 图像平移,缩放,画矩形的操作,并输出执行时间消耗,可以在这里下载:
https://download.csdn.net/download/cgwang_1580/10392863

NV21格式图像旋转 c++,平移、缩放实现代码相关推荐

  1. [Python从零到壹] 三十八.图像处理基础篇之图像几何变换(平移缩放旋转)

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  2. OpenCV 图像旋转、平移、缩放

    本文是 OpenCV图像视觉入门之路的第7篇文章,本文详细的进行了图像的缩放 cv2.resize().旋转 cv2.flip().平移 cv2.warpAffine()等操作. OpenCV 图像旋 ...

  3. 应用OpenCV进行图像旋转和平移

    简 介: 本文中,你了解了了如何通过OpenCV完成对于图像的旋转和平移.我们首先通过 getRotationMatrix2D() 获取2D旋转矩阵,然后完成了对于图像的旋转.具体是通过warpAff ...

  4. C语言数字图像处理---1.5图像基本变换之平移缩放旋转

    本篇作为新年到来前的最后一篇,提前祝大家新年快乐! 图像几何变换又叫做图像基本变换,主要包括图像平移.图像缩放和图像旋转几个部分,当然还有图像镜像等简单的内容.图像基本变换是图像处理的基本内容,是学习 ...

  5. opencv warpAffine()函数详解 -- 图像旋转与平移

    简述 仿射变换是二维坐标间的线性变换,故而变换后的图像仍然具有原图的一些性质,包括"平直性"以及"平行性",常用于图像翻转(Flip).旋转(Rotations ...

  6. Opencv 基础(四):使用OpenCV进行图像旋转和平移

    如今,图像编辑变得越来越流行,因为手机有内置的功能,可以让你裁剪.旋转和更多的操作你的图像. 这篇文章中,我们将探索和学习这些图像编辑技术.具体来说,我们将学习如何: 旋转图像 移动图像 基本图像变换 ...

  7. 【OpenCV3】图像旋转与平移——cv::warpAffine()详解

    图像旋转和平移是图像处理中常用的一种操作,opencv2和opencv3中对图像的旋转和平移都是通过仿射变换函数cv::warpAffine()来实现的. 1.图像的旋转 图像的旋转具体实现分为两步: ...

  8. 【Android RTMP】NV21 图像旋转处理 ( 快速搭建 RTMP 服务器 Shell 脚本 | 创建 RTMP 服务器镜像 | 浏览器观看直播 | 前置 / 后置摄像头图像旋转效果展示 )

    文章目录 安卓直播推流专栏博客总结 一. 编写快速搭建 RTMP 服务器 Shell 脚本 二. RTMP 快速搭建方法 三.创建阿里云 RTMP 服务器镜像 四.浏览器查看直播内容 五.前置 / 后 ...

  9. 【Android RTMP】NV21 图像旋转处理 ( 图像旋转算法 | 后置摄像头顺时针旋转 90 度 | 前置摄像头顺时针旋转 90 度 )

    文章目录 安卓直播推流专栏博客总结 一. 后置摄像头顺时针旋转 90 度 二. 前置摄像头顺时针旋转 90 度 三. NV21 格式图像旋转代码 安卓直播推流专栏博客总结 Android RTMP 直 ...

最新文章

  1. IOS中Key-Value Coding (KVC)的使用详解
  2. 你知道数据中心宕机的真正成本吗?
  3. Linux 的文件和目录管理类命令
  4. Spring之SpringMVC(四)
  5. datatables 展开 折叠_【图说新机】9月折叠屏、屏下摄像头新机同时上市,该怎么选?...
  6. 国家开放大学2021春1050金融理论前沿课题题目
  7. PHP学习笔记(六)
  8. 外链引入css有哪些方式_快速收录的外链操作技巧
  9. 剑指offer面试题[4]-空格替换
  10. centos5.5+NAT+Squid透明代理总结
  11. 在CNN网络中roi从原图映射到feature map中的计算方法
  12. ubuntu上常用的软件安装
  13. vb/vb.net开发技巧荟萃(九)
  14. 名师出高徒!请关注领英上这十位活跃的大神
  15. 【PyTorch】6.1 正则化之weight_decay
  16. git stash 暂存恢复和文件误删恢复
  17. 教你低成本获取用户:利用数据精细化运营(附手绘图)
  18. 联想小新pro16锐龙版和酷睿版的区别 哪个好
  19. matlab实用小程序段 —— 串口发送和读取
  20. 企业做seo的优势在哪些地方

热门文章

  1. encodeURIComponent()有什么用?
  2. mht文件无法打开的解决办法
  3. java 挡泥板,Canyon推出Grail AL铝合金Gravel Bike
  4. 人生路上对我影响最大的老师
  5. 原创|我为什么不建议你等公司倒闭后,再找工作!
  6. pandas中的concat操作
  7. Ubuntu apt卸载
  8. Java 火车票订票系统
  9. 如何使用 Podman 签署和分发容器镜像
  10. 计算机网络安全 第二章 物理安全