写在前面
如果您对音视频技术感兴趣,可以订阅我的专题:音视频专辑
也可以关注我的账户: 张芳涛,我后期会发布更多的音视频以及图像处理方面的文章。
正文
色彩校正通常表示图像版本,如调整亮度,色彩平衡(红色,绿色和蓝色通道),伽马,色调,饱和度等。FFmpeg中的这些修改是通过为各种滤镜指定适当的参数来提供的,因此包括理论介绍。
使用查找表进行视频修改
FFmpeg包含3个视频滤镜,可以生成查找表(LUT),将每个像素分量输入值绑定到输出值。 新值将应用于输入视频帧并编码到输出。
这个表格不太好弄,我把它拆了
描述 | lut过滤器创建一个查找表,用于将每个像素分量输入值绑定到输出值并将其应用于输入视频。 该滤镜在输入时需要YUV或RGB像素格式。 与每个选项相关的确切组件取决于输入中的格式 lutrgb过滤器与lut过滤器相同,但在输入中需要RGB像素格式 lutyuv滤镜与lut滤镜相同,但输入中需要YUV像素格式 |
---|---|
语法 | lut=[c0=expr[:c1=expr[:c2=expr[:c3=expr]]]] lutrgb=[r=expr[:g=expr[:b=expr[:a=expr]]]] lutyuv=[y=expr[:u=expr[:v=expr[:a=expr]]]] |
下面的表格是关于参数的解释
lut过滤器 | lutrgb过滤器 | lutyuv过滤器 |
---|---|---|
c0|第一个像素的组件 | r|红色部分 | y|Y或亮度组件 |
c1|第二像素组件 | g|绿色部分 | u|U或Cb组件 |
c2|第三像素组件 | b|蓝色部分 | v|V或Cr组件 |
c3|第四,与α相同 | a|透明度部分 | a|透明度部分 |
表达式expr中可用的变量和函数。
w, h | 输入的宽度和高度 |
---|---|
val | 像素元素的输入值 |
clipval | 输入值在minval-maxval范围内被剪切 |
maxval | 像素组件的最大值 |
minval | 像素组件的最小值 |
negval | 在minval - maxval范围内对像素组件值进行了否定值; negval = maxval - clipval + minval |
clip(val) | 在minval - maxval范围内的val中计算值 |
gammaval(γ) | 在minval - maxval范围内的计算的伽玛校正值 |
注意: | 所有表达式的默认值为val(像素输入值),因此默认情况下输出没有变化 |
转换为单色(黑白)图像
将彩色输入更改为仅包含黑白色彩的单色输出,对于单色监视器上的播放非常有用。 要在B&W中显示SMPTE条形图,我们可以使用以下命令之一:
ffplay -f lavfi -i smptebars -vf lut=c1=128:c2=128
ffplay -f lavfi -i smptebars -vf lutyuv=u=128:v=128
我的测试命令:
ffplay -f lavfi -i smptebars -vf lut=c1=128:c2=128
- 显示结果:
ffplay -f lavfi -i smptebars -vf lutyuv=u=128:v=128
- 显示结果:
色彩空间简介
要正确使用lutrgb
和lutyuv
滤镜,请在表格中比较RGB
和YUV
色彩空间:
RGB | YUV (Y'CbCr) | |
---|---|---|
描述 | 添加红色、绿色和蓝色光的加色空间 | 图像被划分为1个亮度和2个色度分量 |
组件 | R = 红色通道 | Y' = luma (亮度) |
组件 | G = 绿色通道 | U = Y' - B = Cb (luma- 蓝色) |
组件 | B = 蓝色通道 | V = Y' - R = Cr (luma - 红色) |
用途 | 电脑、数码相机等 | 电视、视频等 |
插图 |
所有颜色都可以通过3种基本颜色的组合来创建:红色,绿色和蓝色。 为了将这一事实适应数字视频,开发了色彩模型和色彩空间,以指定如何以数字形式呈现色彩的标准。 基本颜色空间是RGB(红 - 绿 - 蓝),其中任何颜色表示为混合这三种颜色的各种强度的结果,通常以0到255(256 = 216)或十六进制 从x00
到xff
。
YUV色彩空间及其衍生物
当彩电被发明出来的时候,彩色电视就必须在黑白电视机上播放。基于人眼对绿色的敏感程度,对红色的敏感度降低,对蓝色的敏感度更低,开发出了一种新的颜色空间YUV和后来的Y'CbCr。
- Y'是伽马校正的绿色的亮度
- Cr是红色减去亮度的色度分量
- Cb是蓝色减去亮度的色度分量
Luma(亮度)和chroma(色度)
亮度和亮度分别表示图像的亮度(无色部分),亮度用于视频工程和色彩理论(CIE,ICC等)中的亮度,详情见下表:
亮度 | 色度 | |
---|---|---|
定义 | 伽马校正的R'G'B'视频分量的加权和 | 线性RGB视频分量的加权总和 |
符号 | Y'(主要符号表示伽马校正) | Y |
CCIR 601的公式 | Y' = 0.299 R' + 0.587 G' + 0.114 B' | Y = 0.299 R + 0.587 G + 0.114 B |
Rec. BT 709的公式 | Y' = 0.2126 R' + 0.7152 G' + 0.0722 B' | Y = 0.2126 R + 0.7152 G + 0.0722 B |
******* | R,G和B的系数来自许多人的颜色敏感度测试的平均值 | ******* |
色度和色度表示图像的颜色部分,术语色度主要用于色彩理论,术语色度用于视频工程中,尤其是色度二次采样。 色度通常分为两个分量('
表示伽马校正):
- U = B' - Y'或U = C B(蓝色 - 亮度)
- V = R'-Y'或V = C R(红色 - 亮度)
像素格式
色彩空间理论在像素格式的计算机上实现(在第2章中列出)。 常见像素格式包括:rgb8,rgb24,rgba(不透明度为alpha),yuv420p,yuv422p等。例如,要仅显示rgbtestsrc为蓝色,我们将红色和绿色分量设置为零:
ffplay -f lavfi -i rgbtestsrc -vf lutrgb=r=0:g=0
- 这个我自己测试了没毛病。
RGB像素格式修改
要改变RGB输入格式的特定通道,我们使用lutrgb滤波器。 它通过将r,g和b参数的值设置为0到255(255以上的任何值被认为是255)来调整色彩平衡,常用组合的使用说明了接下来的两幅图像。
色彩均衡
要调整红色,绿色或蓝色通道的亮度,我们设置一个从0到255的数字,并将其输入为lutrgb滤镜的r,g或b参数。 我们还可以对输入值进行分(减)或乘(增),例如将蓝色强度加倍,我们可以使用表达式lutrgb = b = val * 2
。
YUV像素格式的修改
要修改YUV格式的组件,我们使用lutyuv过滤器。 y参数调整亮度(亮度),u参数调整蓝色平衡,v参数调整红色平衡。 这些参数的常见组合说明接下来的两个图像。
亮度校正
在RGB颜色模型中,亮度由三种颜色组合而成,在YUV (Y'CbCr)模型中直接与Y (luma)参数设置。例如,要将亮度调整到90%的输入,我们可以使用lutyuv=y=val*0.9
的表达式。
色调和饱和度设置
表示RGB色彩空间的另一种方法是HSB(HSV),色相饱和度 - 亮度(色调 - 饱和度值)色彩空间。 它使用圆柱坐标系统代替线性立方体,其中色相是围绕中心垂直轴的角度,饱和度是与该轴的距离。 对于色调和饱和度调整,FFmpeg提供了一个表格中描述的色调过滤器:
描述 | 调整输入帧的色调和饱和度 |
---|---|
语法 | hue[=h=expr[:s=expr]] |
参数的描述 | |
h, H | 色度角度,默认值为0.0 |
s | 浮点数范围从-10到10,默认值为1.0 |
表达式expr中可用的变量 | |
n | 输入帧的帧数,数字从0开始 |
pts | 输入帧的呈现时间戳,以时基为单位表示 |
r | 输入视频的帧速率,NaN如果未知 |
t | 时间戳用秒表示,NaN如果未知 |
tb | 输入视频的时间基准 |
其他语法是hue = hue:saturation ,其中色调和饱和度是数字,而不是表达式。 |
色调是从0到360度范围内的角度,并且由CIE定义为“刺激可以被描述为与被描述为红色,绿色,蓝色和黄色的刺激类似或不同的程度”。 例如,要将输入的色调调整为60度,我们可以使用以下命令:
ffplay -i coconut.jpg -vf hue=60
我的测试命令:
ffplay -i /Users/zhangfangtao/Desktop/fruit.jpg -vf hue=60
ffplay -i /Users/zhangfangtao/Desktop/fruit.jpg -vf hue=120
ffplay -i /Users/zhangfangtao/Desktop/fruit.jpg -vf hue=180
ffplay -i /Users/zhangfangtao/Desktop/fruit.jpg -vf hue=240
- 显示的效果(从左往右依次是原图,hue=60,120,180,240):
要调整图像饱和度,我们将s
参数设置为足够的值,例如,将饱和度增加到值5,我们可以使用以下命令:
ffplay -i strawberry.jpg -vf hue=s=5
下一张图片说明了值-10,-5,0,5和10的用法。请注意值0导致单色(黑白)图像。
我的测试命令:
ffplay -i /Users/zhangfangtao/Desktop/ornage.jpeg -vf hue=s=-10
ffplay -i /Users/zhangfangtao/Desktop/ornage.jpeg -vf hue=s=-5
ffplay -i /Users/zhangfangtao/Desktop/ornage.jpeg -vf hue=s=0
ffplay -i /Users/zhangfangtao/Desktop/ornage.jpeg -vf hue=s=5
ffplay -i /Users/zhangfangtao/Desktop/ornage.jpeg -vf hue=s=10
-
显示的效果(从左向右依次是原图,hue=s=-10,-5,0,5,10):
在2个窗口中比较
许多图像和视频编辑器在各种设置中提供了第二个窗口来比较输入如何改变。 为了提供与FFmpeg类似的比较,我们可以在过滤器图片中使用4个过滤链的过滤器和叠加过滤器。
2个窗口水平比较
这种类型的比较已经在第1章中的过滤器,过滤链和过滤器图单元里面有介绍。 第一个过滤链将输入分成两个输出,分别标记为[1]和[2],第二个过滤链为两个标记为[A]的窗口创建一个填充,第三个将过滤器应用于输出[2],结果标记为[B]。 第四个过滤链将修改后的输入([B])叠加到新的打击垫上([A])。 下一个示例使用lutrgb过滤器来说明此方法:
ffplay -f lavfi -i testsrc -vf ^ split[1][2];[1]pad=iw*2[A];[2]lutrgb=g=256[B];[A][B]overlay=w
我的测试命令:
ffplay -f lavfi -i testsrc -vf "split[1][2];[1]pad=iw*2[A];[2]lutrgb=g=256[B];[A][B]overlay=w"
- 显示结果
2个窗口垂直比较
为了在垂直的窗口中提供比较,只有第二次和第四个filtergraph被改变,其他参数在水平比较中保持不变。在第二个filtergraph中,我们将ih(输入高度)乘以2作为y参数,在第四个filtergraph中,我们为y参数指定x参数和h(输入高度)为零。为了演示此方法,下一个示例将与前面的相同图像进行比较,只是修改了windows的位置(该更改下划线):
ffplay -f lavfi -i testsrc -vf ^ split[1][2];[1]pad=iw:ih*2[A];[2]lutrgb=g=256[B];[A][B]overlay=0:h
我的测试命令:
ffplay -f lavfi -i testsrc -vf "split[1][2];[1]pad=iw:ih*2[A];[2]lutrgb=g=256[B];[A][B]overlay=0:h"
- 显示效果:
窗口之间的空间
如果我们需要两个窗口之间的空间,例如10个像素,我们指定它:
- 在第二个filterchain,如pad=iw:ih*2+10。
- 在第四个filterchain,如叠加=0:h+10为50像素空间的水平比较我们指定。
- 在第二个filterchain: pad=iw*2+10。
- 在第四个filterchain: overlay=w+10。
第一次修改版本
若要将修改后的版本放在水平位置,我们可以使用以下命令:
ffplay -f lavfi -i testsrc -vf ^ split[1][2];[1]pad=iw*2:ih:iw[A];[2]lutrgb=g=256[B];[A][B]overlay
与顶部的修改输入的垂直比较是用命令创建的:
ffplay -f lavfi -i testsrc -vf split[1][2];[1]pad=iw:ih*2:0:ih[A];[2]lutrgb=g=256[B];[A][B]overlay
我的测试命令:
ffplay -f lavfi -i testsrc -vf "split[1][2];[1]pad=iw*2:ih:iw[A];[2]lutrgb=g=256[B];[A][B]overlay"
- 显示效果:
ffplay -f lavfi -i testsrc -vf "split[1][2];[1]pad=iw:ih*2:0:ih[A];[2]lutrgb=g=256[B];[A][B]overlay"
- 效果图:
没有输入的修改版本
下一个命令显示两个修改后的输入,没有输入本身,第二个过滤器包含第二个过滤器,它修改了第一个窗口的内容:
ffplay -f lavfi -i testsrc -vf split[1][2]; ^ [1]pad=iw*2,lutrgb=b=256[A];[2]lutrgb=g=256[B];[A][B]overlay=w
我的测试命令:
ffplay -f lavfi -i testsrc -vf "split[1][2];[1]pad=iw*2,lutrgb=g=256[A];[2]lutrgb=g=256[B];[A][B]overlay=w"
- 显示效果
比较三个窗口
在一个复杂的视频编辑中,可以将输入与2个修改同时进行比较。为了在3个窗口中显示比较,我们使用了带有6个过滤链的filtergraph
。
三个窗口水平比较
为了创建一个水平3的窗口比较,可以指定6个filterchains
:
- 1.filterchain将输入拆分为3个相同的输出,标记为[1], [2], [3]
- 2.filterchain从[1]输入一个宽度为3倍的pad,输出为[a]
- 3.filterchain通过一些过滤器(s)修改[2]输入,输出被标记为[B]
- 4.filterchain通过一些过滤器(s)修改[3]输入,输出被标记为[C]
- 5.filterchain覆盖[B]输入[A],其中x坐标为w,输出为[D]
- 6.filterchain覆盖[C]输入[D],其中x坐标为w*2(2倍输入宽度)
例如,下一个命令将testsrc模式与修改的u组件(2)进行比较。与修改的v组件(3)。窗口):
ffplay -f lavfi -i testsrc -vf ^ split=3[1][2][3];[1]pad=iw*3[A];[2]lutyuv=u=val*1.5[B];^ [3]lutyuv=v=val*1.5[C];[A][B]overlay=w[D];[D][C]overlay=w*2
我的测试命令如下:
ffplay -f lavfi -i testsrc -vf "split=3[1][2][3];[1]pad=iw*3[A];[2]lutrgb=u=val*1.5[B];[3]lutyuv=v=val*1.5[C];[A][B]overlay=w[D];[D][C]overlay=w*2"
- 显示效果:
三个窗口垂直比较
对于纵向比较,我们改变下一个过滤链:
2.filterchain -在衬垫过滤宽度参数为输入宽度,高度参数为输入高度乘以3:pad=iw:ih*3。
5.filterchain -在叠加滤波器x参数为零时,y参数为输入高度:叠加=0:h。
-
6.filterchain -在叠加滤波器x参数为零时,y参数为输入高度乘以2:叠加=0。
ffplay -f lavfi -i testsrc -vf ^ split=3[1][2][3];[1]pad=iw:ih*3[A];^ [2]lutyuv=u=val*1.5[B];[3]lutyuv=v=val*1.5[C];^ [A][B]overlay=0:h[D];[D][C]overlay=0:h*2
我的测试命令:
ffplay -f lavfi -i testsrc -vf "split=3[1][2][3];[1]pad=iw:ih*3[A];[2]lutyuv=u=val*1.5[B];[3]lutyuv=v=val*1.5[C];[A][B]overlay=0:h[D];[D][C]overlay=0:h*2"
- 效果图:
在中间窗口输入
下一个命令将输入放置到中间,对filterchains的修改与前面的示例类似(将不变输入的x坐标设置为输入宽度:iw
):
ffplay -f lavfi -i testsrc -vf ^ split=3[1][2][3];[1]pad=iw*3:ih:iw[A];[2]lutyuv=u=val*1.5[B];^ [3]lutyuv=v=val*1.5[C];[A][B]overlay[D];[D][C]overlay=w*2
我的测试命令:
ffplay -f lavfi -i testsrc -vf "split=3[1][2][3];[1]pad=iw*3:ih:iw[A];[2]lutyuv=u=val*1.5[B];[3]lutyuv=v=val*1.5[C];[A][B]overlay[D];[D][C]overlay=w*2"
- 效果图:
要将输入垂直放置到中间,我们可以使用以下命令:
ffplay -f lavfi -i testsrc -vf ^ split=3[1][2][3];[1]pad=iw:ih*3:0:ih[A];[2]lutyuv=u=val*1.5[B];^ [3]lutyuv=v=val*1.5[C];[A][B]overlay[D];[D][C]overlay=0:h*2
我的测试命令:
ffplay -f lavfi -i testsrc -vf "split=3[1][2][3];[1]pad=iw:ih*3:0:ih[A];[2]lutrgb=u=val*1.5[B];[3]lutyuv=v=val*1.5[C];[A][B]overlay[D];[D][C]overlay=0:h*2"
在2个和3个窗口中进行亮度矫正
下面的例子演示了2和3窗口预览的亮度调整。要在亮度是输入值1.5倍的版本旁边显示图像,我们可以使用以下命令:
ffplay -i apple.avi -vf ^ split[1][2];[1]pad=iw*2[A];[2]lutyuv=y=val*1.5[B];[A][B]overlay=w
我的测试命令:
ffplay -i /Users/zhangfangtao/Desktop/ornage.jpeg -vf "split[1][2];[1]pad=iw*2[A];[2]lutyuv=y=val*1.5[B];[A][B]overlay=w"
下一个例子是之前的3-windows版本,中间添加了一个修改后的版本,其中输入亮度的倍数为1.2:
ffplay -i apple.avi -vf ^ split=3[1][2][3];[1]pad=iw*3[A];[2]lutyuv=y=val*1.2[B];^ [3]lutyuv=y=val*1.5[C];[A][B]overlay=w[D];[D][C]overlay=w*2
我的测试命令:
ffplay -i /Users/zhangfangtao/Desktop/ornage.jpeg -vf "split=3[1][2][3];[1]pad=iw*3:ih:iw[A];[2]lutyuv=y=val*1.2[B];[3]lutyuv=y=val*1.5[C];[A][B]overlay[D];[D][C]overlay=w*2"
- 效果图:
要将输入定位到中央窗口,我们可以使用以下命令:
ffplay -i apple.avi -vf ^ split=3[1][2][3];[1]pad=iw*3:ih:iw[A];[2]lutyuv=y=val*1.2[B];^ [3]lutyuv=y=val*1.5[C];[A][B]overlay[D];[D][C]overlay=w*2
我的测试命令:
ffplay -i /Users/zhangfangtao/Desktop/ornage.jpeg -vf "split=3[1][2][3];[1]pad=iw*3:ih:iw*2[A];[2]lutyuv=y=val*1.2[B];[3]lutyuv=y=val*1.5[C];[A][B]overlay[D];[D][C]overlay=w"
- 效果图
如果我们想要3的输入。窗口,只有两个过滤链从上一个示例修改:
- 2.filterchain: pad过滤器的x参数值设为iw*2。
- 6.filterchain:覆盖过滤器的x参数设置为w(输入宽度)
下一个命令显示第三个窗口中的输入:
ffplay -i apple.avi -vf ^ split=3[1][2][3];[1]pad=iw*3:ih:iw*2[A];[2]lutyuv=y=val*1.2[B];^ [3]lutyuv=y=val*1.5[C];[A][B]overlay[D];[D][C]overlay=w
在4个窗口中进行比较
为了得到更好的结果和各种实验,我们可以同时对输入进行3个修改。为了在4个窗口中显示比较,filtergraph包含8个filterchains:
- 1.filterchain将输入分割为4个相同的输出,标记为[1], [2], [3], [4]
- 2.filterchain从[1]输入一个具有双倍宽度和双倍高度的衬垫,输出被标记为[a]
- 3.filterchain通过一些过滤器(s)修改[2]输入,输出被标记为[B]
- 4.filterchain通过一些过滤器(s)修改[3]输入,输出被标记为[C]
- 5.filterchain修改[4]输入带有一些过滤器,输出被标记为[D]
- 6.filterchain覆盖[B]输入[A]输入,其中x坐标为输入宽度,输出标签为[E]
- 7.filterchain覆盖[C]输入[E]输入,其中x为0,y为输入高度,输出标签为[F]
-
8.filterchain覆盖[D]输入[F]输入,其中x坐标为输入宽度,y为输入高度。
例如,下一个命令将番茄与特定颜色通道值加倍的版本进行比较。右上方的窗口加强了红色通道,在底部左侧的绿色通道和右下方的蓝色通道:
ffplay -i tomato.mpg -vf split=4[1][2][3][4];[1]pad=iw*2:ih*2[A];^ [2]lutrgb=r=val*2[B];[3]lutrgb=g=val*2[C];[4]lutrgb=b=val*2[D];^ [A][B]overlay=w[E];[E][C]overlay=0:h[F];[F][D]overlay=w:h
我的测试命令:
ffplay -i /Users/zhangfangtao/Desktop/ornage.jpeg -vf "split=4[1][2][3][4];[1]pad=iw*2:ih*2[A]; [2]lutrgb=r=val*2[B];[3]lutrgb=g=val*2[C];[4]lutrgb=b=val*2[D]; [A][B]overlay=w[E];[E][C]overlay=0:h[F];[F][D]overlay=w:h"
-
效果图: