├── 图像数字化 ├── 视觉感知.md ├── 品质与噪声.md ├── 彩色图像 │ ├── README.md │ └── YUV.md ├── 采样与量化.md └── README.md ├── 图像分割 └── README.md ├── 开发框架 └── SDL │ └── README.md ├── 图像数据压缩 ├── PNG.md └── README.md ├── 图像数据结构 └── README.md ├── SVG ├── 动画.md ├── README.md └── 图形.md ├── README.md ├── 图像预处理 └── README.md └── FFmpeg ├── 视频加水印.md ├── FFplay.md └── README.md /图像数字化/视觉感知.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /图像分割/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /图像数字化/品质与噪声.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /开发框架/SDL/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /图像数字化/彩色图像/README.md: -------------------------------------------------------------------------------- 1 | # 彩色图像 2 | -------------------------------------------------------------------------------- /图像数据压缩/PNG.md: -------------------------------------------------------------------------------- 1 | # PNG 2 | 3 | # Links 4 | 5 | - https://mp.weixin.qq.com/s/wxpKVTn-ar3b7aok3CQIBA 6 | -------------------------------------------------------------------------------- /图像数据结构/README.md: -------------------------------------------------------------------------------- 1 | # 图像数据结构 2 | 3 | 数据和算法是任何程序的两个基本的相关部分。数据的组织通常在很大程度上影响着算法的选择和实现的简洁性,因此,在写程序时数据结构的选择是一个重要问题[Wirth, 1976]。 4 | -------------------------------------------------------------------------------- /SVG/动画.md: -------------------------------------------------------------------------------- 1 | # Svg 动画 2 | 3 | # Links 4 | 5 | - [SVG 动画精髓](https://parg.co/bNB):本文主要是讲解关于 SVG 的一些高级动画特效,比如 SVG 动画标签,图形渐变,路径动画,线条动画,SVG 裁剪等。 6 | -------------------------------------------------------------------------------- /图像数字化/采样与量化.md: -------------------------------------------------------------------------------- 1 | # 采样与量化 2 | 3 | 为了用计算机来处理,图像必须用合适的离散数据结构来表达, 例如矩阵。传感器获取的图像是平面上两个坐标的连给函数 $f(x, y)$ 图像数字化是指将 $f(x, y)$ 采样(sampled)为一个 $M$ 行 $N$ 列的矩阵。图像量化(quantization)给每个连续的样本数值一个整数数字,图像函数 $f(x, y)$ 的连续范围被划分为 $K$ 个区间。采样及量化越精细(即,$M, N, K$ 越大),对连续函数 $f(x, y)$ 的近似就越好。 4 | 5 | 图像函数采样有两个问题,其一是确定采样的间隔,即相邻两个采样图像点的距离,其二是设置采样点。 6 | 7 | # 采样 8 | 9 | 一个连续图像在采样点(sampling point)处被数字化。这些采样点是在平面上排列的,称它们的几何关系为栅格(grid)。因此数字图像是一个数据结构,通常是矩阵。在实践中,栅格一般是方的或者是正六边形的。 10 | 11 | ![方形栅格与正六边形栅格](https://s1.ax1x.com/2020/11/05/B2w55Q.png) 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 图像与媒体 2 | 3 | 图像和信号常用数学模型来描述。信号是一个依赖于具有某种物理意义的变量的函数,它可以是一维的(例如,依赖于时间)、二维的(例如,依赖于面上的两个坐标量)、三维的(例如,描述空间中的一个物体)或高维的。对于单色的图像,一个标量函数可能就足够了,但是对于诸如由三个分量组成的彩色图像就需要使用矢量函数。 4 | 5 | 我们要处理的函数可以分为连续的、离散的或数字的。连续函数具有连续的定义域和值域;如果定义域是离散的,我们得到的是离散函数;而如果值域也是离散的,我们就得到数字函数。 6 | 7 | 图像(Image)这一词我们通常在直观上理解其意义,例如,人类眼睛视网膜上的图像,或者 TV 摄像机抓取的图像。这可以表示为两个变量的一个连续(图像)函数 f(x,y),其中(x,y 是平面的坐标;或者可能是三个变量的连续函数 f(x,y,),其中 t 是时间在绝大多数应用中,包括我们日常生活中遇到的和本书中所要介绍的,这种表示是合理的。尽管如此,值得注意的是一幅“图像”有多种获的方式。我们将会注意到彩色是标准,即便在我们从单色图像的角度介绍算法时也是如此,但是我们也无将自己限定在可见光谱上。工作在红外谱段的摄像机现在已经很普通了(例如,用于夜间监视)。也可以使用其他电磁(EM)谱段部分,例如,可以广泛获得的太赫兹成像。进一步,在电磁(EM)谱段(即,“光)之外的图像获取也已经很普通了:在医学领域,数据集由核磁共振(MR)、计算机断层扫描摄影(CT)超声等形成。所有这些方法都产生大的数据矩阵,需要分析和理解而这些矩阵越来越多的是三维或更高维的。 8 | 9 | # Links 10 | 11 | > - https://zhuanlan.zhihu.com/p/71915244 数字图像处理 12 | -------------------------------------------------------------------------------- /图像预处理/README.md: -------------------------------------------------------------------------------- 1 | # 图像预处理 2 | 3 | 预处理是指在处于最低抽象层次的图像上所进行的操作,这时处理的输入和输出都是亮度图像。这些图标图像是与传感器抓取到的原始数据同类的,通常是用图像函数值的矩阵表示的亮度图像。 4 | 5 | 预处理并不会增加图像的信息量。如果信息用熵来度量,那么预处理一般都会降低图像的信息量。因此,从信息理论的角度来看,最好的预处理是没有预处理,避免预处理的最好途径是着力于高质量的图像获取。然而,预处理在很多情况下是非常有用的,因为它有助于抑制与特殊的图像处理或分析任务无关的信息。因此,预处理的目的是改善图像数据,抑制不需要的变形或者增强某些对于后续处理重要的图像特征。考虑到图像的几何变换(比如旋转、变尺度、平移)使用类似的技术,这里我们将它看作预处理方法。 6 | 7 | 图像预处理方法按照在计算新像素亮度时所使用的像素邻域的大小分为四类:处理像素亮度变换、几何变换、使用待处理像素一个局部邻域的预处理方法、有关整个图像知识的图像复原技术。另一种角度是将图像预处理分为图像增强(Image Enhancement)、覆盖像素亮度变换以及图像复原(Image Restoration)。多数图像中存在着相当可观的信息冗余,这使得图像预处理方法可以利用图像数据本身来学习一些统计意义上的图像特征。这些特征或者用于抑预料之外的退化如噪声,或者用于图像增强。实际图像中的属于个物体的相邻像素基本上具有相同的或类似的亮度值,因此如果一个失真了的像素可以从图像中被挑出来的话,它一般可以用其邻接像素的平均值来复原。 8 | 9 | 如果图像预处理的目标是矫正图像的某种退化,那么先验信息的性质就很重要: 10 | 11 | - 第一类方法不使用有关退化性质的知识,仅假设退化的非常一般性的特征 12 | - 第二类方法假设具有有关图像获取设备的特性和获取图像时所处条件的知识。噪声的性质(通常是指其频域特征)有时是知道的。 13 | - 第三类方法使用有关图像中待搜索物体的知识,这样可以相当程度地简化预处理。如果事先无法获得有关物体的知识,可以在处理的过程中估计。如下的策略是可能的。首先对图像做粗处理以便减小数据量,找到图像物体。这样得到的图像信息被用于产生对图像物体属性的假设,然后在更高分辨率图像上检验该假设。如此地反复迭代直至出现的知识被证实或被拒绝。这个反馈可能会超出预处理,由于分割也产生有关物体的语义知识,因此反馈可以在物体分割之后启动。 14 | -------------------------------------------------------------------------------- /图像数据压缩/README.md: -------------------------------------------------------------------------------- 1 | # 图像数据压缩 2 | 3 | 由于用来表示图像的数据数量通常很大,图像处理也往往具有很大难度。在技术上,图像的分辨率(空间上和灰度级别上)在不断增加,谱段(spectral band)的数量也在增加,因而需要限制由此带来的数据屋。我们来伯一个遥感领域的例子,其中图像数据压缩是一个很重要的问题。日本高级地球观测卫星(ADEOS, Advanced Earth Observing Satellite)能够在彩色谱段以 8 米的空问分辨率、在多谱段以 16 米的空间分辨率对地球表面进行观测,它的数据传送速率高达 120Mb/s。因此,这样的遥感数据所需要的存储介质数量是非常大的。 4 | 5 | 有着 3D 和 4D 数据的医学图像处理的情况与此类似。比如,单独一个从头到脚的 64 探测器(64-detector)的 CT 全身拆描可以在 10 秒内完成。这样的 CT 装肯可以传输分辨率高达 $0.5 \mathrm{mm}^{3}$ 的立体图像。在这个分辨率下的一个全身扫描对应 于将近 2GB 的数据 ($512 \times 512 \times 3600 \times 2$ 字节)。用于对小动物做研究的显微 CT (micro-CT ) 扫描也能获得 类似大小的数据文件。有一个可以减少必要的存储介质数量的方法,那就是处理压缩过的图像数据。 6 | 7 | 数据压缩方法可以分为两大主要类别:信息保持压缩能够保证进行无错的数据重建(无损压缩);而有信息丢失( with loss of information)的压缩方法则不能完整地保持信息(有损压缩)。在图像处理中,一个详确的重建实际上不是十分必要的,所以对的需求比较弱,但是图像数据压缩不应造成图像的明显改变。在重建图像中数据压缩的成功性通常以最小均方差(MSE, Mean Square Error)、信噪比等来衡量,尽管这些全局性的误差衡量方法并不总是能反映主观上的图像质量 8 | 9 | 图像数据压缩设计由两部分组成。首先第一部必须确定图像数据的性质;为这一目的服务的通常有灰度直方图、图像熵、各种相关函数等。第二部分相对于量测到的图像性质形成合适的压缩技术设计。有损的信息数据压缩方法在图像处理中非常典型,因此我们要相当详细地讨论这类方法。尽管有损压缩技术也可以提供具有非常好的重建质量的实质性图像压缩,但是出于某些考虑,它们的应用可能会遭到禁止例如,在医疗成像方面,诊断通常是基于可视图像的检查,因此不能容忍任何信息损失,必须使用信息保持技术。 10 | -------------------------------------------------------------------------------- /图像数字化/README.md: -------------------------------------------------------------------------------- 1 | # 图像数字化 2 | 3 | 图像函数的值对应于图像点的亮度。函数值也可以表示其他物理量(温度、压力分布、离观察者的距离等)。亮度(brightness)集成了不同的光学量,将亮度作为一个基本量使我们得以避免对图像的成像过程进行描述。人类眼睛视网膜或者 TV 摄像传感器上的图像本身是两维的(2D)。我们将这种记录了明亮度信息的 2D 图像称为亮度图像(intensity image)。图像传感器上的 2D 图像通常是三维(3D)场景的投影结果。这一过程的最简单的数学模型就是所谓的针孔摄像机。 4 | 5 | 2D 亮度图像是 3D 场景的透视投影(perspective projection),这一过程由针孔摄像机拍摄的图像来表达。在下图中,图像平面被相对于 XY 平面反折过来了,以便避免使用具有负坐标的镜像图像;x,y,z 的量是世界坐标系中 3D 场景点 X 的坐标,f 是从针孔到图像平面的距离。通常称 f 为焦距,因为在镜头中它具有相似的含义。镜头近似于针孔摄像机而广为应用。投影后的点 u 具有 2D 图像坐标平面中的坐标$(u,v)$,根据相似三角形很容易导出: 6 | 7 | ![透视投影几何](https://s1.ax1x.com/2020/11/05/B2tn8x.md.png) 8 | 9 | 非线性的透视投影常被近似为线性的平行(parallel)(或正交(orthographic)) 投影(projection), 其 中 $f \rightarrow \infty$ 。隐含地,$z \rightarrow \infty$ 表明正交投影是远处物体透视投影的极限情况。当 3D 物体经透视投影映射到摄像机平面后,由于这样的变换不是一对一的,因而大量的信息消失了通过一幅图像来识别和重构 3D 场景中的体是个病态问题。可以预料,这不是一个简单的任务,涉及到试图建立图像中点的深度( depth)这个中间表达层次。目标是恢复完整的 3D 表达,比如计算机图形学中的表达,即,独立于视点的表达,表示在物体坐标系中而不是在观察者坐标系中。如果这样的表达可以恢复,则物体的任何视角的亮度图像可以用标准的计算机图形学技术合成出来。 10 | 11 | 图像处理通常考虑的是静态(static)图像,时间 t 作为常量。单色的静态图像是用连续的图像函数 f(x,y) 来表示的,其中的变量是平面的两个坐标。本书所考虑的图像除非特别声明大多数是指单色的静态图像。通常把这里所讲的技术推广到多光谱的情况下是显而易见的。计算机化的图像处理使用的数字图像函数通常表示成矩阵的形式,因此其坐标是整数。图像函数的定义域是平面的一个区域 R: 12 | 13 | $$ 14 | R=\left\{(x, y), 1 \leqslant x \leqslant x_{n}, 1 \leqslant y \leqslant y_{n}\right\} 15 | $$ 16 | 17 | 其中 $x_m$,$y_n$ 表示最大的图像坐标。图像函数具有有限的域由于假定图像函数在域 R 外的值为零,可以使用无限求和或积分的形式。尽管矩阵中使用的(行、列、左上原点)定位方式在数字图像处理中也常用到,但是习惯上采用的图像坐标方向仍然是普通的笛卡尔形式(横轴 x、纵轴 y、左下原点)图像函数的值域也是有限的,按照惯例,在单色图像中最低值对应于黑,而最高值对应于白。在它们之间的亮度值是灰阶(gray-level)。 18 | 19 | 数字图像的品质随着空间、频谱、辐射计量、时间分辨率增长而提高。空间分辨率( spatial resolution)是由图像平面上图像采样点间的接近程度确的,频谱分辨率( spectral resolution)是由传感器获得的光线频率带宽决定的,辐射计量分辨率( radiometrie resolution)对应于可区分的灰阶数量,时间分辨率(timeresolution)取决于图像获取的时间采样间隔。时间分辨率问题在动态图像分析中是重要的,其中处理的是图像的时间序列。图像 f(x,y) 可作为确定的函数或者是随机过程的实现来看待。图像描述中的数学工具根植于线性系统理论、积分变换、离散数学以及随机过程理论中。 20 | -------------------------------------------------------------------------------- /FFmpeg/视频加水印.md: -------------------------------------------------------------------------------- 1 | 以下是一些使用 FFmpeg 为视频添加文字水印的常用方法和示例: 2 | 3 | ### 1. 基础命令示例 4 | 5 | ```bash 6 | # 添加简单文字水印 7 | ffmpeg -i input.mp4 -vf "drawtext=text='Your Text':x=10:y=10:fontsize=24:fontcolor=white" -codec:a copy output.mp4 8 | 9 | # 添加带背景的文字水印 10 | ffmpeg -i input.mp4 -vf "drawtext=text='Your Text':fontsize=24:fontcolor=white:box=1:boxcolor=black@0.5:boxborderw=5:x=10:y=10" -codec:a copy output.mp4 11 | ``` 12 | 13 | ### 2. 常用参数说明 14 | 15 | ```bash 16 | drawtext 参数选项: 17 | fontsize # 字体大小 18 | fontcolor # 字体颜色 19 | fontfile # 字体文件路径 20 | x # X 坐标位置 21 | y # Y 坐标位置 22 | box # 是否显示背景框 23 | boxcolor # 背景框颜色 24 | alpha # 透明度 25 | ``` 26 | 27 | ### 3. 实用示例 28 | 29 | 1. **添加时间戳水印** 30 | 31 | ```bash 32 | ffmpeg -i input.mp4 -vf "drawtext=text='%{pts\:hms}':x=10:y=10:fontsize=24:fontcolor=white" -codec:a copy output.mp4 33 | ``` 34 | 35 | 2. **添加多行文字** 36 | 37 | ```bash 38 | ffmpeg -i input.mp4 -vf "drawtext=text='Line 1':x=10:y=10:fontsize=24:fontcolor=white,drawtext=text='Line 2':x=10:y=40:fontsize=24:fontcolor=white" -codec:a copy output.mp4 39 | ``` 40 | 41 | 3. **居中显示文字** 42 | 43 | ```bash 44 | ffmpeg -i input.mp4 -vf "drawtext=text='Centered Text':fontsize=24:fontcolor=white:x=(w-text_w)/2:y=(h-text_h)/2" -codec:a copy output.mp4 45 | ``` 46 | 47 | ### 4. 相关 GitHub 项目推荐 48 | 49 | 1. [video-watermark](https://github.com/h2non/video-watermark) 50 | 51 | - Node.js 库,支持添加图片和文字水印 52 | - 基于 FFmpeg 53 | 54 | 2. [FFmpeg-video-watermark](https://github.com/leixiaohua1020/FFmpeg-video-watermark) 55 | 56 | - 提供多种水印添加示例 57 | - 包含详细的中文注释 58 | 59 | 3. [ffmpeg-watermark](https://github.com/protyposis/ffmpeg-watermark) 60 | 61 | - 简单的水印添加脚本 62 | - 支持批量处理 63 | 64 | ### 5. 进阶使用示例 65 | 66 | 1. **添加动态移动的文字** 67 | 68 | ```bash 69 | ffmpeg -i input.mp4 -vf "drawtext=text='Moving Text':x='if(gte(t,0), mod(0.5*t\*(w+tw), w+tw)-tw, NAN)':y=50:fontsize=24:fontcolor=white" -codec:a copy output.mp4 70 | ``` 71 | 72 | 2. **添加带渐变效果的文字** 73 | 74 | ```bash 75 | ffmpeg -i input.mp4 -vf "drawtext=text='Fading Text':x=10:y=10:fontsize=24:fontcolor=white@0.5:enable='between(t,0,5)'" -codec:a copy output.mp4 76 | ``` 77 | 78 | 3. **使用自定义字体** 79 | 80 | ```bash 81 | ffmpeg -i input.mp4 -vf "drawtext=fontfile=/path/to/font.ttf:text='Custom Font':x=10:y=10:fontsize=24:fontcolor=white" -codec:a copy output.mp4 82 | ``` 83 | 84 | 这些命令和项目可以帮助你实现各种文字水印效果。记得根据实际需求调整参数,比如字体大小、位置、颜色等。 85 | -------------------------------------------------------------------------------- /SVG/README.md: -------------------------------------------------------------------------------- 1 | # SVG 2 | 3 | SVG 指可伸缩矢量图形 (Scalable Vector Graphics),用来定义用于网络的基于矢量的图形,它在放大或改变尺寸的情况下其图形质量不会有所损失。Svg 使用 XML 格式定义图形,与诸如 DOM 和 XSL 之类的 W3C 标准是一个整体。 4 | 5 | # 语法定义 6 | 7 | SVG 基础语法如下: 8 | 9 | ```xml 10 | 11 | 13 | 14 | 16 | 17 | ``` 18 | 19 | 第一行包含了 XML 声明。请注意 standalone 属性,该属性规定此 SVG 文件是否是独立的,或含有对外部文件的引用。standalone=”no” 意味着 SVG 文档会引用一个外部文件,这里即是 DTD 文件。第二和第三行引用了这个外部的 SVG DTD。该 DTD 位于 “http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"。该 DTD 位于 W3C,含有所有允许的 SVG 元素。 20 | 21 | SVG 代码以 `` 元素开始,包括开启标签 `` 和关闭标签。这是根元素。width 和 height 属性可设置此 SVG 文档的宽度和高度。version 属性可定义所使用的 SVG 版本,xmlns 属性可定义 SVG 命名空间。SVG 的 `` 用来创建一个圆。cx 和 cy 属性定义圆中心的 x 和 y 坐标。如果忽略这两个属性,那么圆点会被设置为 (0, 0)。r 属性定义圆的半径。stroke 和 stroke-width 属性控制如何显示形状的轮廓,fill 属性设置形状内的颜色。 22 | 23 | ## 可见区域与缩放 24 | 25 | viewport 表示 SVG 可见区域的大小,或者可以想象成舞台大小,画布大小。 26 | 27 | ```html 28 | 29 | ``` 30 | 31 | 上面的 SVG 代码定义了一个视区,宽 500 单位,高 300 单位。viewBox 顾名思意是“视区盒子”的意思,`viewBox="x, y, width, height" // x:左上角横坐标,y:左上角纵坐标,width:宽度,height:高度`: 32 | 33 | ```html 34 | 40 | 41 | 42 | ``` 43 | 44 | SVG 就像是我们的显示器屏幕,viewBox 就是截屏工具选中的那个框框,最终的呈现就是把框框中的截屏内容再次在显示器中全屏显示。 45 | 46 | ![viewBox 缩放实例](https://image.zhangxinxu.com/image/blog/201408/2014-08-27_105046-viewbox.gif) 47 | 48 | ## HTML 中使用 49 | 50 | - 使用 `` 标签,所有主要浏览器都支持,并允许使用脚本;不推荐在 HTML4 和 XHTML 中使用。 51 | 52 | ```html 53 | 54 | ``` 55 | 56 | - 使用 `` 标签,所有主要浏览器都支持,并支持 HTML4,XHTML 和 HTML5 标准;不过不允许使用脚本。 57 | 58 | ```html 59 | 60 | ``` 61 | 62 | - 直接在 HTML 嵌入 SVG 代码。 63 | 64 | ```html 65 | 66 | 67 | 68 | 76 | 77 | 78 | 79 | ``` 80 | -------------------------------------------------------------------------------- /SVG/图形.md: -------------------------------------------------------------------------------- 1 | # SVG 图形 2 | 3 | ## 矩形 4 | 5 | 矩形的属性如下: 6 | 7 | 1.rect 元素的 width 和 height 属性可定义矩形的高度和宽度 8 | 2.style 属性用来定义 CSS 属性 9 | 3.CSS 的 fill 属性定义矩形的填充颜色(rgb 值、颜色名或者十六进制值) 10 | 4.CSS 的 stroke-width 属性定义矩形边框的宽度 11 | 5.CSS 的 stroke 属性定义矩形边框的颜色 12 | 6.x 属性定义矩形的左侧位置(例如,x=”0” 定义矩形到浏览器窗口左侧的距离是 0px) 13 | 7.y 属性定义矩形的顶端位置(例如,y=”0” 定义矩形到浏览器窗口顶端的距离是 0px) 14 | 8.CSS 的 fill-opacity 属性定义填充颜色透明度(合法的范围是:0 - 1) 15 | 9.CSS 的 stroke-opacity 属性定义笔触颜色的透明度(合法的范围是:0 - 1) 16 | 10.CSS opacity 属性用于定义了元素的透明值 (范围: 0 到 1)。 17 | 11.rx 和 ry 属性可使矩形产生圆角。 18 | 19 | ```html 20 | 21 | 30 | 31 | ``` 32 | 33 | ## 圆形 34 | 35 | cx 和 cy 属性定义圆点的 x 和 y 坐标。如果省略 cx 和 cy,圆的中心会被设置为(0, 0),r 属性定义圆的半径。 36 | 37 | ```html 38 | 39 | 40 | 41 | ``` 42 | 43 | ## 椭圆 44 | 45 | CX 属性定义的椭圆中心的 x 坐标,CY 属性定义的椭圆中心的 y 坐标;RX 属性定义的水平半径,RY 属性定义的垂直半径。 46 | 47 | ```html 48 | 49 | 50 | 51 | 52 | 53 | ``` 54 | 55 | ## 直线 56 | 57 | 直线的属性如下: 58 | 59 | 1.x1 属性在 x 轴定义线条的开始 60 | 2.y1 属性在 y 轴定义线条的开始 61 | 3.x2 属性在 x 轴定义线条的结束 62 | 4.y2 属性在 y 轴定义线条的结束 63 | 64 | ```html 65 | 66 | 73 | 74 | ``` 75 | 76 | ## 多边形 77 | 78 | points 属性定义多边形每个角的 x 和 y 坐标。 79 | 80 | ```html 81 | 82 | 86 | 87 | ``` 88 | 89 | # 路径 90 | 91 | 所有命令均允许小写字母。大写表示绝对定位,小写表示相对定位。 92 | 93 | ```sh 94 | M = moveto 95 | L = lineto 96 | H = horizontal lineto 97 | V = vertical lineto 98 | C = curveto 99 | S = smooth curveto 100 | Q = quadratic Bézier curve 101 | T = smooth quadratic Bézier curveto 102 | A = elliptical Arc 103 | Z = closepath 104 | ``` 105 | 106 | # Links 107 | 108 | - https://www.villainhr.com/page/2017/04/17/SVG%20%E5%BF%AB%E9%80%9F%E5%85%A5%E9%97%A8 109 | -------------------------------------------------------------------------------- /FFmpeg/FFplay.md: -------------------------------------------------------------------------------- 1 | # FFplay 使用指南 2 | 3 | #### FFplay 是什么 4 | 5 | - ffplay 是一个使用了 ffmpeg 和 sdl 库的简单的可移植的媒体播放器。 6 | 7 | ``` 8 | 命令行:ffplay [选项] ['输入文件'] 9 | ``` 10 | 11 | #### FFplay 使用示例 12 | 13 | - 播放 test.mkv,播放完成后自动退出 14 | 15 | ```shell 16 | ffplay -autoexit test.mkv 17 | ``` 18 | 19 | - 以 320 × 240 的大学播放 test.mkv 20 | 21 | ```shell 22 | ffplay -x 320 -y 240 test.mkv 23 | ``` 24 | 25 | #### 通用选项 26 | 27 | ``` 28 | '-L' 显示 license 29 | '-h, -?, -help, --help [arg]' 打印帮助信息;可以指定一个参数 arg,如果不指定,只打印基本选项 30 | 可选的 arg 选项: 31 | 'long' 除基本选项外,还将打印高级选项 32 | 'full' 打印一个完整的选项列表,包含 encoders, decoders, demuxers, muxers, filters 等的共享以及私有选项 33 | 'decoder=decoder_name' 打印名称为 "decoder_name" 的解码器的详细信息 34 | 'encoder=encoder_name' 打印名称为 "encoder_name" 的编码器的详细信息 35 | 'demuxer=demuxer_name' 打印名称为 "demuxer_name" 的 demuxer 的详细信息 36 | 'muxer=muxer_name' 打印名称为 "muxer_name" 的 muxer 的详细信息 37 | 'filter=filter_name' 打印名称为 "filter_name" 的过滤器的详细信息 38 | 39 | '-version' 显示版本信息 40 | '-formats' 显示有效的格式 41 | '-codecs' 显示 libavcodec 已知的所有编解码器 42 | '-decoders' 显示有效的解码器 43 | '-encoders' 显示有效的编码器 44 | '-bsfs' 显示有效的比特流过滤器 45 | '-protocols' 显示有效的协议 46 | '-filters' 显示 libavfilter 有效的过滤器 47 | '-pix_fmts' 显示有效的像素格式 48 | '-sample_fmts' 显示有效的采样格式 49 | '-layouts' 显示通道名称以及标准通道布局 50 | '-colors' 显示认可的颜色名称 51 | '-hide_banner' 禁止打印欢迎语;也就是禁止默认会显示的版权信息、编译选项以及库版本信息等 52 | ``` 53 | 54 | #### 主要选项 55 | 56 | ``` 57 | '-x width' 强制以 "width" 宽度显示 58 | '-y height' 强制以 "height" 高度显示 59 | '-an' 禁止音频 60 | '-vn' 禁止视频 61 | '-ss pos' 跳转到指定的位置(秒) 62 | '-t duration' 播放 "duration" 秒音/视频 63 | '-bytes' 按字节跳转 64 | '-nodisp' 禁止图像显示(只输出音频) 65 | '-f fmt' 强制使用 "fmt" 格式 66 | '-window_title title' 设置窗口标题(默认为输入文件名) 67 | '-loop number' 循环播放 "number" 次(0将一直循环) 68 | '-showmode mode' 设置显示模式 69 | 可选的 mode: 70 | '0, video' 显示视频 71 | '1, waves' 显示音频波形 72 | '2, rdft' 显示音频频带 73 | 默认值为 'video',你可以在播放进行时,按 "w" 键在这几种模式间切换 74 | 75 | '-i input_file' 指定输入文件 76 | ``` 77 | 78 | #### 高级选项 79 | 80 | ``` 81 | '-sync type' 设置主时钟为音频、视频、或者外部。默认为音频。主时钟用来进行音视频同步 82 | '-threads count' 设置线程个数 83 | '-autoexit' 播放完成后自动退出 84 | '-exitonkeydown' 任意键按下时退出 85 | '-exitonmousedown' 任意鼠标按键按下时退出 86 | '-acodec codec_name' 强制指定音频解码器为 "codec_name" 87 | '-vcodec codec_name' 强制指定视频解码器为 "codec_name" 88 | '-scodec codec_name' 强制指定字幕解码器为 "codec_name" 89 | ``` 90 | 91 | #### 快捷键 92 | 93 | ``` 94 | 'q, ESC' 退出 95 | 'f' 全屏 96 | 'p, SPC' 暂停 97 | 'w' 切换显示模式(视频/音频波形/音频频带) 98 | 's' 步进到下一帧 99 | 'left/right' 快退/快进 10 秒 100 | 'down/up' 快退/快进 1 分钟 101 | 'page down/page up' 跳转到前一章/下一章(如果没有章节,快退/快进 10 分钟) 102 | 'mouse click' 跳转到鼠标点击的位置(根据鼠标在显示窗口点击的位置计算百分比) 103 | ``` 104 | -------------------------------------------------------------------------------- /FFmpeg/README.md: -------------------------------------------------------------------------------- 1 | # FFmpeg 2 | 3 | FFmpeg 的名称来自 MPEG 视频编码标准,前面的“FF”代表“Fast Forward”,FFmpeg 是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。可以轻易地实现多种视频格式之间的相互转换。包括如下几个部分: 4 | 5 | - libavformat:用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能,包含 demuxers 和 muxer 库。 6 | - libavcodec:用于各种类型声音/图像编解码。 7 | - libavutil:包含一些公共的工具函数。 8 | - libswscale:用于视频场景比例缩放、色彩映射转换。 9 | - libpostproc:用于后期效果处理。 10 | - [ffmpeg](https://github.com/feixiao/ffmpeg/blob/master/src/B_FFmpeg使用指南.md):是一个命令行工具,用来对视频文件转换格式,也支持对电视卡实时编码。 11 | - ffsever:是一个 HTTP 多媒体实时广播流服务器,支持时光平移。 12 | - [ffplay](https://github.com/feixiao/ffmpeg/blob/master/src/B_FFplay使用指南.md):是一个简单的播放器,使用 ffmpeg 库解析和解码,通过 SDL 显示。 13 | - [ffprobe](https://github.com/feixiao/ffmpeg/blob/master/src/C_FFprobe使用指南.md):收集多媒体文件或流的信息,并以人和机器可读的方式输出。 14 | 15 | # 基础术语 16 | 17 | - 容器(Container):一种文件格式,比如 flv,mkv 等。包含下面 5 种流以及文件头信息。 18 | 19 | - 流(Stream):一种视频数据信息的传输方式,5 种流:音频,视频,字幕,附件,数据。 20 | 21 | - 帧(Frame):帧代表一幅静止的图像,分为 I 帧,P 帧,B 帧。 22 | 23 | - 编解码器(Codec):是对视频进行压缩或者解压缩,CODEC = COde(编码)+DECode(解码)。 24 | 25 | - 复用/解复用(mux/demux):把不同的流按照某种容器的规则放入容器,这种行为叫做复用(mux)。把不同的流从某种容器中解析出来,这种行为叫做解复用(demux)。 26 | 27 | - 帧率:帧率也叫帧频率,帧率是视频文件中每一秒的帧数,肉眼想看到连续移动图像至少需要 15 帧。 28 | 29 | - 码率:比特率(也叫码率,数据率)是一个确定整体视频/音频质量的参数,秒为单位处理的字节数,码率和视频质量成正比,在视频文件中中比特率用 bps 来表达。 30 | 31 | # 命令参数 32 | 33 | FFmpeg 使用方法 34 | 35 | ```​ 36 | ffmpeg [全局选项] {[输入文件选项] -i ‘输入文件’} ... {[输出文件选项] ‘输出文件’} 37 | ``` 38 | 39 | 主要选项 40 | 41 | ```sh 42 | ‘-f fmt (input/output)’ 43 | 强制输入或输出文件格式。通常,输入文件的格式是自动检测的, 44 | 输出文件的格式是通过文件扩展名来进行猜测的,所有该选项大 45 | 多数时候不需要。 46 | ‘-i filename (input)’ 47 | 输入文件名 48 | ‘-y (global)’ 49 | 覆盖输出文件而不询问 50 | ‘-n (global)’ 51 | 不覆盖输出文件,如果一个给定的输出文件已经存在,则立即 52 | 退出 53 | ‘-c[:stream_specifier] codec (input/output,per-stream)’ 54 | ‘-codec[:stream_specifier] codec (input/output,per-stream)’ 55 | 为一个或多个流选择一个编码器(当使用在一个输出文件之前时) 56 | 或者一个解码器(当使用在一个输入文件之前时)。codec 是一个 57 | 编码器/解码器名称或者一个特定值“copy”(只适用输出)。 58 | ‘-t duration (output)’ 59 | 当到达 duration 时,停止写输出。 60 | duration 可以是一个数字(秒),或者使用hh:mm:ss[.xxx]形式。 61 | -to 和 -t 是互斥的,-t 优先级更高。 62 | ‘-to position (output)’ 63 | 在 position 处停止写输出。 64 | duration 可以是一个数字(秒),或者使用hh:mm:ss[.xxx]形式。 65 | -to 和 -t 是互斥的,-t 优先级更高。 66 | ‘-fs limit_size (output)’ 67 | 设置文件大小限制,以字节表示 68 | ‘-ss position (input/output)’ 69 | 当作为输入选项时(在 -i 之前),在输入文件中跳转到 position。 70 | 需要注意的是,在大多数格式中,不太可能精确的跳转,因此, 71 | ffmpeg 将跳转到 position 之前最接近的位置。当进行转码 72 | 并且 ‘-accurate_seek’ 打开时(默认),位于跳转点和 position 73 | 之间的额外部分将被解码并且丢弃。当做流拷贝或者当使用 74 | ‘-noaccurate_seek’时,它将被保留下来。 75 | 当作为输出选项时(在输出文件名前),解码但是丢弃输入,直到 76 | 时间戳到达 position。 77 | position 可以是秒或者 hh:mm:ss[.xxx] 形式 78 | ‘-itsoffset offset (input)’ 79 | 设置输入时间偏移。offset 将被添加到输入文件的时间戳。指定 80 | 一个正偏移,意味着相应的流将被延时指定时间。 81 | ‘-timestamp date (output)’ 82 | 在容器中设置录音时间戳 83 | ‘-metadata[:metadata_specifier] key=value (output,per-metadata)’ 84 | 设置metadata key/value对 85 | ‘-target type (output)’ 86 | 指定目标文件类型(vcd, svcd, dvd, dv, dv50)。 87 | type 可以带有 pal-, ntsc- 或 film- 前缀,以使用相应的标准。 88 | 所有的格式选项(bitrate, codecs, buffer sizes)将自动设定。 89 | ‘-dframes number (output)’ 90 | 设置要录制数据帧的个数。这是 -frames:d 的别名 91 | ‘-frames[:stream_specifier] framecount (output,per-stream)’ 92 | framecount 帧以后,停止写流。 93 | ‘-q[:stream_specifier] q (output,per-stream)’ 94 | ‘-qscale[:stream_specifier] q (output,per-stream)’ 95 | 使用固定质量范围(VBR)。 96 | ‘-filter[:stream_specifier] filtergraph (output,per-stream)’ 97 | 创建filtergraph 指定的过滤图,并使用它来过滤流。 98 | ‘-filter_script[:stream_specifier] filename (output,per-stream)’ 99 | 该选项与‘-filter’相似,唯一的不同是,它的参数是一个存放 100 | 过滤图的文件的名称。 101 | ‘-pre[:stream_specifier] preset_name (output,per-stream)’ 102 | 指定匹配流的预设 103 | ‘-stats (global)’ 104 | 打印编码进程/统计信息。默认打开,可以使用 -nostats 禁用。 105 | ‘-stdin’ 106 | 开启标准输入交互。默认打开,除非标准输入作为一个输入。 107 | 可以使用 -nostdin 禁止。 108 | ‘-debug_ts (global)’ 109 | 打印时间戳信息。默认关闭。 110 | ‘-attach filename (output)’ 111 | 添加一个附件到输出文件中 112 | ‘-dump_attachment[:stream_specifier] filename (input,per-stream)’ 113 | 提取匹配的附件流到filename指定的文件中。 114 | ``` 115 | 116 | ## 视频选项 117 | 118 | ```sh 119 | ‘-vframes number (output)’ 120 | 设置录制视频帧的个数。这是 -frames:v 的别名 121 | ‘-r[:stream_specifier] fps (input/output,per-stream)’ 122 | 设置帧率(Hz 值,分数或缩写) 123 | ‘-s[:stream_specifier] size (input/output,per-stream)’ 124 | 设置帧大小。格式为 ‘wxh’ (默认与源相同) 125 | ‘-aspect[:stream_specifier] aspect (output,per-stream)’ 126 | 设置视频显示长宽比 127 | ‘-vn (output)’ 128 | 禁止视频录制 129 | ‘-vcodec codec (output)’ 130 | 设置视频 codec。这是 -codec:v 的别名 131 | ‘-pass[:stream_specifier] n (output,per-stream)’ 132 | 选择pass number (1 or 2)。用来进行双行程视频编码。 133 | ‘-passlogfile[:stream_specifier] prefix (output,per-stream)’ 134 | 设置 two-pass 日志文件名前缀,默认为“ffmpeg2pass”。 135 | ‘-vf filtergraph (output)’ 136 | 创建 filtergraph 指定的过滤图,并使用它来过滤流。 137 | ‘-pix_fmt[:stream_specifier] format (input/output,per-stream)’ 138 | 设置像素格式。 139 | ‘-sws_flags flags (input/output)’ 140 | 设置软缩放标志 141 | ‘-vdt n’ 142 | 丢弃阈值 143 | ‘-psnr’ 144 | 计算压缩帧的 PSNR 145 | ‘-vstats’ 146 | 复制视频编码统计信息到‘vstats_HHMMSS.log’ 147 | ‘-vstats_file file’ 148 | 复制视频编码统计信息到 file 149 | ‘-force_key_frames[:stream_specifier] time[,time...] (output,per-stream)’ 150 | ‘-force_key_frames[:stream_specifier] expr:expr (output,per-stream)’ 151 | 在指定的时间戳强制关键帧 152 | ‘-copyinkf[:stream_specifier] (output,per-stream)’ 153 | 当进行流拷贝时,同时拷贝开头的非关键帧 154 | ‘-hwaccel[:stream_specifier] hwaccel (input,per-stream)’ 155 | 使用硬件加速来解码匹配的流 156 | ‘-hwaccel_device[:stream_specifier] hwaccel_device (input,per-stream)’ 157 | 选择硬件加速所使用的设备。该选项只有‘-hwaccel’同时指定时才有意义。 158 | ``` 159 | 160 | ## 音频选项 161 | 162 | ``` 163 | ‘-aframes number (output)’ 164 | 设置录制音频帧的个数。这是 -frames:a 的别名 165 | ‘-ar[:stream_specifier] freq (input/output,per-stream)’ 166 | 设置音频采样率。 167 | ‘-aq q (output)’ 168 | 设置音频质量。这是 -q:a 的别名 169 | ‘-ac[:stream_specifier] channels (input/output,per-stream)’ 170 | 设置音频通道数。 171 | ‘-an (output)’ 172 | 禁止音频录制 173 | ‘-acodec codec (input/output)’ 174 | 设置音频codec。这是-codec:a的别名 175 | ‘-sample_fmt[:stream_specifier] sample_fmt (output,per-stream)’ 176 | 设置音频采样格式 177 | ‘-af filtergraph (output)’ 178 | 创建filtergraph 所指定的过滤图,并使用它来过滤流 179 | 高级选项 180 | ‘-map [-]input_file_id[:stream_specifier][,sync_file_id[:stream_specifier]] | [linklabel] (output)’ 181 | 指定一个或多个流作为输出文件的源。 182 | 命令行中的第一个 -map 选项,指定输出流0的源, 183 | 第二个 -map 选项,指定输出流1的源,等等。 184 | ‘-map_channel [input_file_id.stream_specifier.channel_id|-1][:output_file_id.stream_specifier]’ 185 | 将一个给定输入的音频通道映射到一个输出。 186 | ‘-map_metadata[:metadata_spec_out] infile[:metadata_spec_in] (output,per-metadata)’ 187 | 设置下一个输出文件的 metadata 信息。 188 | ‘-map_chapters input_file_index (output)’ 189 | 从索引号为 input_file_index 的输入文件中拷贝章节到下一个输出文件中。 190 | ‘-timelimit duration (global)’ 191 | ffmpeg 运行 duration 秒后推出 192 | ‘-dump (global)’ 193 | 将每一个输入包复制到标准输出 194 | ‘-hex (global)’ 195 | 复制包时,同时复制负载 196 | ‘-re (input)’ 197 | 以本地帧率读取数据。主要用来模拟一个采集设备, 198 | 或者实时输入流(例如:当从一个文件读取时). 199 | ‘-vsync parameter’ 200 | 视频同步方法 201 | ‘-async samples_per_second’ 202 | 音频同步方法 203 | ‘-shortest (output)’ 204 | 当最短的输入流结束时,终止编码 205 | ‘-muxdelay seconds (input)’ 206 | 设置最大解封装-解码延时 207 | ‘-muxpreload seconds (input)’ 208 | 设置初始解封装-解码延时 209 | ‘-streamid output-stream-index:new-value (output)’ 210 | 为一个输出流分配一个新的stream-id。 211 | ‘-bsf[:stream_specifier] bitstream_filters (output,per-stream)’ 212 | 为匹配的流设置比特流过滤器 213 | ‘-filter_complex filtergraph (global)’ 214 | 定义一个复杂的过滤图 215 | ‘-lavfi filtergraph (global)’ 216 | 定义一个复杂的过滤图。相当于‘-filter_complex’ 217 | ‘-filter_complex_script filename (global)’ 218 | 该选项类似于‘-filter_complex’,唯一的不同是 219 | 它的参数是一个定义过滤图的文件的文件名 220 | ‘-accurate_seek (input)’ 221 | 打开或禁止在输入文件中的精确跳转。默认打开。 222 | ``` 223 | -------------------------------------------------------------------------------- /图像数字化/彩色图像/YUV.md: -------------------------------------------------------------------------------- 1 | # YUV 2 | 3 | YUV 是一种颜色编码方方式,通常由彩色摄像机进行取像,然后把取得的彩色图像信号经过分色、分别放大校正后得到 RGB,再经过矩阵变换得到亮度信号 Y 和两个色差信号 B-Y(即 U)、R-Y(即 V),最后将亮度和色差三个信号分别编码,用同一信道发送出去。这种色彩的表示方法就是所谓的 YUV 色彩空间表示。采用 YUV 色彩空间的重要性就是它的亮度信号 Y 和色度信号 U、V 是分离的。 4 | 5 | 相对于 RGB 颜色空间,设计 YUV 的目的就是为了编码、传输的方便,减少带宽占用和信息出错。人眼的视觉特点是对亮度更铭感,对位置、色彩相对来说不铭感。在视频编码系统中为了降低带宽,可以保存更多的亮度信息(luma),保存较少的色差信息(chroma)。Y’UV、YUV、YCbCr、YPbPr 几个概念其实是一回事儿。由于历史关系,Y’UV、YUV 主要是用在彩色电视中,用于模拟信号表示。YCbCr 是用在数字视频、图像的压缩和传输,如 MPEG、JPEG。今天大家所讲的 YUV 其实就是指 YCbCr。Y 表示亮度(luma),CbCr 表示色度(chroma)。 6 | 7 | YUV 中“Y”表示明亮度(Luminance 或 Luma),也就是灰阶值;而“U”和“V” 表示的则是色度(Chrominance 或 Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。“亮度”是透过 RGB 输入信号来建立的,方法是将 RGB 信号的特定部分叠加到一起。“色度”则定义了颜色的两个方面 ─ 色调与饱和度,分别用 Cr 和 Cb 来表示。其中,Cr 反映了 RGB 输入信号红色部分与 RGB 信号亮度值之间的差异。而 Cb 反映的是 RGB 输入信号蓝色部分与 RGB 信号亮度值之间的差异。 8 | 9 | # YUV 采样 10 | 11 | 对于一个 w 宽、h 高的像素图,在水平方向,一行有 w 个像素;在垂直方向,一列有 h 个像素,整个图形有 `w * h` 个像素。我们把这个像素叫做图形像素。如果用 YCbCr 像素格式来表示像素图,那么要搞清楚亮度和图形像素的关系,色度和图形像素的关系。 12 | 13 | ![yuv 数字解释](https://s3.ax1x.com/2020/11/13/D9BMnS.png) 14 | 15 | 如上图中所示,左侧一列,每一个小矩形是图形像素表示,黑框矩形是色度像素表示,小黑点是表示色度像素值(Cb+Cr),表示图形像素和色度像素在水平和垂直方向的比例关系。比如, 16 | 17 | - 4:4:0 水平方向是 1/1,垂直方向是 1/2,表示一个色度像素对应了两个图形像素。 18 | - 4:2:2 水平方向是 1/2,垂直方向是 1/1,表示一个色度像素对应了两个图形像素。 19 | - 4:2:0 水平方向是 1/2,垂直方向是 1/2,表示一个色度像素对应了四个图形像素。 20 | 21 | 右侧一列是二次采样模式记号表示, 是 J:a:b 模式,实心黑色圆圈表示包含色度像素(Cb+Cr),空心圆圈表示不包含色度像素。对于 J:a:b 模式,主要是围绕参考块的概念定义的,这个参考块是一个 J x 2 的矩形,J 通常是 4。这样,此参考块就是宽度有 4 个像素、高度有 2 个像素的矩形。a 表示参考块的第一行包含的色度像素样本数,b 表示在参考块的第二行包含的色度像素样本数。 22 | 23 | - 4:4:0 参考块第一行包含四个色度样本,第二行没有包含色度样本。 24 | - 4:2:2 参考块第一行包含两个色度样本,第二行也包含两个色度样本,他们是交替出现。 25 | - 4:2:0 参考块第一行包含两个色度样本,第二行没有包含色度样本。 26 | 27 | 现在我们发现 yuv444,yuv422,yuv420 yuv 等像素格式的本质是:每个图形像素都会包含亮度值,但是某几个图形像素会共用一个色度值,这个比例关系就是通过 4 x 2 的矩形参考块来定的。这样很容易理解类似 yuv440,yuv420 这样的格式了。 28 | 29 | - 4:4:4 表示没有对色度通道进行缩减采样。 30 | - 4:2:2 意味着 2:1 的水平缩减采样,没有垂直下采样。每扫描一行,每两个 U 或 V 采样包含四个 Y 采样。 31 | - 4:2:0 表示 2:1 水平缩减采样,2:1 垂直缩减采样。 32 | - 4:1:1 表示 4:1 水平缩减采样,没有垂直下采样。每个扫描线对于每个 U 或 V 采样包含四个 Y 采样。4:1:1 采样比其他格式少见。 33 | 34 | 换句话说来说,可以理解为: 35 | 36 | - YUV 4:4:4 采样,每一个 Y 对应一组 UV 分量。 37 | - YUV 4:2:2 采样,每两个 Y 共用一组 UV 分量。 38 | - YUV 4:2:0 采样,每四个 Y 共用一组 UV 分量。 39 | 40 | 下面三个图分别是各自的采集方式: 41 | 42 | ![YUV 采集方式](https://s3.ax1x.com/2020/11/15/DFVtcq.png) 43 | 44 | # YUV 存储 45 | 46 | 下面的图给出了常见的 YUV 码流的存储方式,并在存储方式后面附有取样每个像素点的 YUV 数据的方法,其中,Cb、Cr 的含义等同于 U、V。 47 | 48 | ## YUVY 格式(属于 YUV422) 49 | 50 | ![img](https://images2017.cnblogs.com/blog/682616/201802/682616-20180209155346982-258986689.png) 51 | 52 | YUYV 为 YUV422 采样的存储格式中的一种,相邻的两个 Y 共用其相邻的两个 Cb、Cr,分析,对于像素点 Y'00、Y'01 而言,其 Cb、Cr 的值均为 Cb00、Cr00,其他的像素点的 YUV 取值依次类推。 53 | 54 | ## UYVY 格式(属于 YUV422) 55 | 56 | ![img](https://images2017.cnblogs.com/blog/682616/201802/682616-20180209155417170-837281930.png) 57 | 58 | UYVY 格式也是 YUV422 采样的存储格式中的一种,只不过与 YUYV 不同的是 UV 的排列顺序不一样而已,还原其每个像素点的 YUV 值的方法与上面一样。 59 | 60 | ## YUV422P(属于 YUV422) 61 | 62 | ![img](https://images2017.cnblogs.com/blog/682616/201802/682616-20180209155457982-968223311.png) 63 | 64 | YUV422P 也属于 YUV422 的一种,它是一种 Plane 模式,即打包模式,并不是将 YUV 数据交错存储,而是先存放所有的 Y 分量,然后存储所有的 U(Cb)分量,最后存储所有的 V(Cr)分量,如上图所示。其每一个像素点的 YUV 值提取方法也是遵循 YUV422 格式的最基本提取方法,即两个 Y 共用一个 UV。比如,对于像素点 Y'00、Y'01 而言,其 Cb、Cr 的值均为 Cb00、Cr00。 65 | 66 | 平面格式是指用三个不同的数组来表示 YCbCr 的三个 Component,每一个 Component 都是通过不同的平面表示。为此,每一个 Component 会对应一个 plane。yuv420p 也叫 i420 就是 yuv420 planar 表示。yuv420p 一共有三个平面分别是 Y,U,V,每一个平面都是用 8 bit 二进制数字表示,我们把 8 bit 称作位深度。 67 | 68 | 如果用 yuv420p 来表示分辨率为 `1280 * 720` 的图片,需要占用多少存储空间呢? 69 | 70 | - 每一个像素都需要一个 luma 值,即 y。那么总共需要 `1280 * 720 = 921600 bytes`。 71 | - 每四个像素需要一个 chroma u 值,那么总共需要 `1280 * 720 / 4 = 230400 bytes`。 72 | - 每四个像素需要一个 chroma v 值,那么总共需要 `1280 * 720 / 4 = 230400 bytes`。 73 | 74 | 把 y、u、v 三个 plane 加起来就是:921600 + 230400 + 230400 = 1382400 bytes。 75 | 76 | ## YV12,YU12 格式(属于 YUV420) 77 | 78 | ![img](https://images2017.cnblogs.com/blog/682616/201802/682616-20180209155537466-578129036.png) 79 | 80 | ## NV12、NV21(属于 YUV420) 81 | 82 | ![img](https://images2017.cnblogs.com/blog/682616/201802/682616-20180209155555263-1405762791.png) 83 | 84 | NV12 和 NV21 属于 YUV420 格式,是一种 two-plane 模式,即 Y 和 UV 分为两个 Plane,但是 UV(CbCr)为交错存储,而不是分为三个 plane。其提取方式与上一种类似,即 Y'00、Y'01、Y'10、Y'11 共用 Cr00、Cb00 85 | 86 | ## yuv420p 和 yuv420 的区别 87 | 88 | 二者在存储格式上有区别: 89 | 90 | - yuv420p:yyyyyyyy uuuuuuuu vvvvv 91 | - yuv420:yuv yuv yuv 92 | 93 | yuv420P,Y,U,V 三个分量都是平面格式,分为 I420 和 YV12。I420 格式和 YV12 格式的不同处在 U 平面和 V 平面的位置不同。在 I420 格式中,U 平面紧跟在 Y 平面之后,然后才是 V 平面(即:YUV);但 YV12 则是相反(即:YVU)。YUV420SP, Y 分量平面格式,UV 打包格式, 即 NV12。NV12 与 NV21 类似,U 和 V 交错排列,不同在于 UV 顺序。 94 | 95 | ```s 96 | I420: YYYYYYYY UU VV =>YUV420P 97 | YV12: YYYYYYYY VV UU =>YUV420P 98 | NV12: YYYYYYYY UVUV =>YUV420SP 99 | NV21: YYYYYYYY VUVU =>YUV420SP 100 | ``` 101 | 102 | # YUV 格式与 RGB 格式的换算 103 | 104 | - RGB 转换成 YUV 105 | 106 | ``` 107 | Y = (0.257 * R) + (0.504 * G) + (0.098 * B) + 16 108 | Cr = V = (0.439 * R) - (0.368 * G) - (0.071 * B) + 128 109 | Cb = U = -( 0.148 * R) - (0.291 * G) + (0.439 * B) + 128 110 | ``` 111 | 112 | - YUV 转换成 RGB 113 | 114 | ``` 115 | B = 1.164(Y - 16) + 2.018(U - 128) 116 | G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) 117 | R = 1.164(Y - 16) + 1.596(V - 128) 118 | ``` 119 | 120 | RGB 取值范围均为 0255,Y=0255,U=-122+122,V=-157+157,简化后的换算公式 121 | 122 | - RGB 转 YUV 123 | 124 | ``` 125 | Y = 0.299R + 0.587G + 0.114B 126 | U'= (BY)*0.565 127 | V'= (RY)*0.713 128 | ``` 129 | 130 | - YUV 转 RGB 131 | 132 | ``` 133 | R = Y + 1.403V' 134 | G = Y - 0.344U' - 0.714V' 135 | B = Y + 1.770U' 136 | ``` 137 | 138 | # 压缩格式(Packed formats) 139 | 140 | 压缩格式是指用一个数组表示 YCbCr,每一个 component 是交替出现的。 141 | 142 | ## ffmpeg 中对 yuv420p 像素格式大小计算 143 | 144 | yuv420p 的格式描述在 libavutil/pixdesc.c 的 173 行。 145 | 146 | ```text 147 | 173 static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { 148 | 174 [AV_PIX_FMT_YUV420P] = { 149 | 175 .name = "yuv420p", // 像素格式名称 150 | 176 .nb_components = 3, // 表示有三个 component,也是三个 plane 151 | 177 .log2_chroma_w = 1, // 表示色度(chroma) 像素和图形像素的水平比例关系 152 | 178 .log2_chroma_h = 1, // 表示色度(chroma) 像素和图形像素的垂直比例关系 153 | 179 .comp = { 154 | 180 { 0, 1, 0, 0, 8, 0, 7, 1 }, /* Y 平面,step 是 1,位深度是8 bit */ 155 | 181 { 1, 1, 0, 0, 8, 0, 7, 1 }, /* U 平面,step 是 1,位深度是8 bit */ 156 | 182 { 2, 1, 0, 0, 8, 0, 7, 1 }, /* V 平面,step 是 1,位深度是8 bit */ 157 | 183 }, 158 | 184 .flags = AV_PIX_FMT_FLAG_PLANAR, 159 | 185 }, 160 | ``` 161 | 162 | 所有的 YUV 像素格式表示都在 av_pix_fmt_descriptors 表中完成,我可以把这叫做像素格式描述表。 163 | 164 | yuv420p 像素格式在水平方向(行)大小计算在 libavutil/imgutils.c 的 54 行。 165 | 166 | ```text 167 | 53 static inline 168 | 54 int image_get_linesize(int width, int plane, 169 | 55 int max_step, int max_step_comp, 170 | 56 const AVPixFmtDescriptor *desc) 171 | 57 { 172 | 58 int s, shifted_w, linesize; 173 | 59 174 | 60 if (!desc) 175 | 61 return AVERROR(EINVAL); 176 | 62 177 | 63 if (width < 0) 178 | 64 return AVERROR(EINVAL); 179 | // max_step_comp 的取值:0:y,1:u,2:v。对于 y 平面,每一个图形像素需要一个亮度值, 180 | // 所以这里比例因子是 0;对于 u、v 平面来说,色度像素和图形像素在水平和垂直方向都是 2/1 的关系, 181 | // 所以计算行的时候,比例因子取像素格式描述表中的 log2_chroma_w。对于 yuv420p 来说,取值是 1, 182 | // 因为是通过移位运算完成的,右移 1 位,相当于是除以 2。 183 | 65 s = (max_step_comp == 1 || max_step_comp == 2) ? desc->log2_chroma_w : 0; 184 | 66 shifted_w = ((width + (1 << s) - 1)) >> s; 185 | 67 if (shifted_w && max_step > INT_MAX / shifted_w) 186 | 68 return AVERROR(EINVAL); 187 | 69 linesize = max_step * shifted_w; 188 | 70 189 | // 如果像素描述表中的单位是 bit,那么这里转换成 bytes,右移 3 位,就是除以 8。 190 | 71 if (desc->flags & AV_PIX_FMT_FLAG_BITSTREAM) 191 | 72 linesize = (linesize + 7) >> 3; 192 | 73 return linesize; 193 | 74 } 194 | ``` 195 | 196 | yuv420p 像素格式在垂直方向(列)大小计算在 libavutil/imgutils.c 的 111 行。 197 | 198 | ```text 199 | 111 int av_image_fill_pointers(uint8_t *data[4], enum AVPixelFormat pix_fmt, int height, 200 | 112 uint8_t *ptr, const int linesizes[4]) 201 | 113 { 202 | 114 int i, total_size, size[4] = { 0 }, has_plane[4] = { 0 }; 203 | 115 204 | 116 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); 205 | 117 memset(data , 0, sizeof(data[0])*4); 206 | 118 207 | 119 if (!desc || desc->flags & AV_PIX_FMT_FLAG_HWACCEL) 208 | 120 return AVERROR(EINVAL); 209 | 121 210 | 122 data[0] = ptr; 211 | 123 if (linesizes[0] > (INT_MAX - 1024) / height) 212 | 124 return AVERROR(EINVAL); 213 | 125 size[0] = linesizes[0] * height; 214 | 126 215 | 127 if (desc->flags & AV_PIX_FMT_FLAG_PAL || 216 | 128 desc->flags & FF_PSEUDOPAL) { 217 | 129 data[1] = ptr + size[0]; /* palette is stored here as 256 32 bits words */ 218 | 130 return size[0] + 256 * 4; 219 | 131 } 220 | 132 221 | 133 for (i = 0; i < 4; i++) 222 | 134 has_plane[desc->comp[i].plane] = 1; 223 | 135 224 | 136 total_size = size[0]; 225 | 137 for (i = 1; i < 4 && has_plane[i]; i++) { 226 | // i 的取值:0:y,1:u,2:v。对于 y 平面,每一个图形像素需要一个亮度值, 227 | // 所以这里比例因子是 0;对于 u、v 平面来说,色度像素和图形像素在水平和垂直方向都是 2/1 的关系, 228 | // 所以计算列的时候,比例因子取像素格式描述表中的 log2_chroma_h。对于 yuv420p 来说,取值是 1, 229 | // 因为是通过移位运算完成的,右移 1 位,相当于是除以 2。 230 | 138 int h, s = (i == 1 || i == 2) ? desc->log2_chroma_h : 0; 231 | 139 data[i] = data[i-1] + size[i-1]; 232 | 140 h = (height + (1 << s) - 1) >> s; 233 | 141 if (linesizes[i] > INT_MAX / h) 234 | 142 return AVERROR(EINVAL); 235 | // 每一平面的行和列做乘法,就是像素总数。 236 | 143 size[i] = h * linesizes[i]; 237 | 144 if (total_size > INT_MAX - size[i]) 238 | 145 return AVERROR(EINVAL); 239 | // 每一个平面的像素数相加,就是图片占用的像素总数。 240 | 146 total_size += size[i]; 241 | 147 } 242 | 148 243 | 149 return total_size; 244 | 150 } 245 | ``` 246 | --------------------------------------------------------------------------------