我正在尝试使用 FFmpeg 模糊视频的某个部分(特别是模糊脸部)。
我一直在尝试结合使用时间线编辑和各种模糊滤镜,但我找不到仅模糊视频某一部分的方法。
我希望得到类似这样的结果:
-vf boxblur=enable='between(t,10,100)':width=20:height=20:x=400:y=200
其中width
/height
是模糊框的大小,x
/y
是模糊框的位置。
这样的事可能吗?
答案1
可以对片段/部分应用时间和空间模糊——假设您想要模糊的区域是静态位置。
原始黑色拉布拉多幼犬图像。
使用遮罩图像
您可以制作一个灰度蒙版图像来指示要模糊的区域。为了方便使用,它应该与要模糊的图像或视频的大小相同。
ffmpeg -i video.mp4 -i mask.png -filter_complex "[0:v][1:v]alphamerge,avgblur=10[alf];[0:v][alf]overlay[v]" -map "[v]" -map 0:a -c:v libx264 -c:a copy -movflags +faststart maskedblur.mp4
白色区域是模糊发生的地方,但这可以很容易地用否定过滤器例如:
[1:v]negate[mask];[0:v][mask]alphamerge,avgblur=10[alf]...
您可以使用格克过滤器生成诸如渐变的蒙版。
模糊特定区域(无蒙版)
ffmpeg -i input.mp4 -filter_complex "[0:v]crop=200:200:60:30,avgblur=10[fg];[0:v][fg]overlay=60:30[v]" -map "[v]" -map 0:a -c:v libx264 -c:a copy -movflags +faststart derpdogblur.mp4
笔记:60
覆盖层(和此示例中)中的 x 和 y 偏移数字30
必须与裁剪偏移相匹配。
此示例的作用:
- 将副本裁剪为要模糊的区域的大小。在此示例中:一个 200x200 像素的框,距离左上角右侧(
x
轴)60 像素,下方(轴)30 像素。y
- 使裁剪区域模糊。
- 使用相同的参数
x
覆盖模糊区域y
庄稼筛选。
对特定区域进行多重模糊处理(无蒙版)
ffmpeg -i input.mp4 -filter_complex "[0:v]crop=50:50:20:10,avgblur=10[b0];[0:v]crop=iw:30:(iw-ow)/2:ih-oh,avgblur=10[b1];[0:v]crop=100:100:120:80,avgblur=10[b2];[0:v][b0]overlay=20:10[ovr0];[ovr0][b1]overlay=(W-w)/2:H-h[ovr1];[ovr1][b2]overlay=120:80" -c:a copy -movflags +faststart output.mp4
特定区域不模糊(无遮罩)
ffmpeg -i input.mp4 -filter_complex "[0:v]avgblur=10[bg];[0:v]crop=200:200:60:30[fg];[bg][fg]overlay=60:30" -c:a copy -movflags +faststart output.mp4
附加内容
音频正在流已复制(重新混合)。无需重新编码,因此速度很快,而且质量也很好。
模糊区域将具有硬边缘。
如果你想模糊一段时间,请使用
enable
选项在 avgblur 或覆盖上。查看FFmpeg 过滤器文档用于其他模糊滤镜(boxblur、dblur、gblur、sab、smartblur、unsharp、yaepblur)。
一些相关问题:如何模糊视频中的短场景和如何添加像素化效果。
答案2
对于未获得如何指定持续时间的,这里有一个例子
ffmpeg -i derpdog.mp4 -filter_complex \
"[0:v]crop=200:100:60:30,boxblur=10:enable='between(t,60*2,60*2+10)'[fg]; \
[0:v][fg]overlay=60:30[v]" \
-map "[v]" -map 0:a -c:v libx264 -c:a copy -movflags +faststart derpdogblur.mp4
模糊将出现在 处x=60
,y=30
其中width=200
,height=100
从second=120
到second=130
答案3
对于不喜欢模糊的锐利边缘的情况,我制作了一个脚本,对不同阶段的模糊进行分层,以使边缘不锐利,它看起来像这样:
这是一个python脚本:
#!/usr/bin/env python3
import os,stat
def blur_softly(matrix,video_in="video_to_be_blurred.mp4",video_out=""):
if video_out == "":
video_out = video_in[:-4] + "_blurred" + video_in[-4:]
s0 = "ffmpeg -i " + video_in + " -filter_complex \\\n\"[0:v]null[v_int0]; \\\n"
s1 = ''
a = 0
for m in matrix:
blur = m[6]
multiple = m[7]
width = m[0]+blur*multiple*2
height = m[1]+blur*multiple*2
x_cord = m[2]-blur*multiple
y_cord = m[3]-blur*multiple
timein = m[4]
timeout = m[5]
step = m[8]
margin = m[9]
for i in range(blur):
ii = multiple*i
s0 = s0 + "[v_int0]crop="+str(width-2*ii+(margin//2)*2)+":"+str(height-2*ii+(margin//2)*2)+":"+str(x_cord+ii-margin//2)+":"+str(y_cord+ii-margin//2) + \
",boxblur="+str((i+1)*step)+":enable='between(t,"+str(timein)+","+str(timeout)+ \
")',crop="+str(width-2*ii)+ ":"+str(height-2*ii)+":"+str(margin//2)+":"+str(margin//2)+ "[blur_int" + str(i+1+a)+"]; \\\n"
s1 = s1 + "[v_int"+ str(i+a) +"][blur_int"+str(i+a+1)+"]overlay="+str(x_cord+ii)+":"+str(y_cord+ii)+":enable='between(t,"+str(timein)+","+str(timeout)+ ")'[v_int"+str(i+a+1)+"]; \\\n"
a += i+1
s = s0 + s1 + "[v_int"+str(a)+"]null[with_subtitles]\" \\\n-map \"[with_subtitles]\" -map 0:a -c:v libx264 -c:a copy -crf 17 -preset slow -y "+video_out+"\n"
print(s)
file_object = open('blur.sh', 'w')
file_object.write(s)
file_object.close()
st = os.stat('blur.sh')
os.chmod('blur.sh', st.st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
#w,h,x,y,timein,timeout,blur,multiple,step,margin
matrix = [[729,70,599,499,14.96,16.40,25,1,1,90],]
blur_softly(matrix,video_in="your_video.mp4",video_out="output_video.mp4")
您可以在最后一行和倒数第二行更改参数,引号之间的最后两个参数是视频和输出视频的路径(假设它们放在工作目录中)。在倒数第二行:
- 前两个数字表示应用最大模糊的初始区域的大小,
- 后两个表示其 x 和 y 坐标(左上角),
- 第三两个表示应用模糊的时间(以秒为单位),
- 本例中的“25”表示将有 25 个框叠加在一起)
- 下一个“1”表示更大的框,模糊程度更低,应该比其前身仅宽一个像素
- 第二个“1”表示模糊度应增加一,直到最大值 25(从上方)
- “30”表示应用模糊时要考虑的边距,因此增加该值会使模糊更多地尊重其周围环境。增加此值还可以解决类似以下错误文本
Invalid chroma radius value 21, must be >= 0 and <= 20
通过运行它,应该得到如下的输出(它被写入一个可以运行的文件中,并打印在可以复制粘贴和运行的输出上):
ffmpeg -i video_to_be_blurred.mp4 -filter_complex \
"[0:v]null[v_int0]; \
[v_int0]crop=869:210:529:429,boxblur=1:enable='between(t,14.96,16.4)',crop=779:120:45:45[blur_int1]; \
[v_int0]crop=867:208:530:430,boxblur=2:enable='between(t,14.96,16.4)',crop=777:118:45:45[blur_int2]; \
[v_int0]crop=865:206:531:431,boxblur=3:enable='between(t,14.96,16.4)',crop=775:116:45:45[blur_int3]; \
[v_int0]crop=863:204:532:432,boxblur=4:enable='between(t,14.96,16.4)',crop=773:114:45:45[blur_int4]; \
[v_int0]crop=861:202:533:433,boxblur=5:enable='between(t,14.96,16.4)',crop=771:112:45:45[blur_int5]; \
[v_int0]crop=859:200:534:434,boxblur=6:enable='between(t,14.96,16.4)',crop=769:110:45:45[blur_int6]; \
[v_int0]crop=857:198:535:435,boxblur=7:enable='between(t,14.96,16.4)',crop=767:108:45:45[blur_int7]; \
[v_int0]crop=855:196:536:436,boxblur=8:enable='between(t,14.96,16.4)',crop=765:106:45:45[blur_int8]; \
[v_int0]crop=853:194:537:437,boxblur=9:enable='between(t,14.96,16.4)',crop=763:104:45:45[blur_int9]; \
[v_int0]crop=851:192:538:438,boxblur=10:enable='between(t,14.96,16.4)',crop=761:102:45:45[blur_int10]; \
[v_int0]crop=849:190:539:439,boxblur=11:enable='between(t,14.96,16.4)',crop=759:100:45:45[blur_int11]; \
[v_int0]crop=847:188:540:440,boxblur=12:enable='between(t,14.96,16.4)',crop=757:98:45:45[blur_int12]; \
[v_int0]crop=845:186:541:441,boxblur=13:enable='between(t,14.96,16.4)',crop=755:96:45:45[blur_int13]; \
[v_int0]crop=843:184:542:442,boxblur=14:enable='between(t,14.96,16.4)',crop=753:94:45:45[blur_int14]; \
[v_int0]crop=841:182:543:443,boxblur=15:enable='between(t,14.96,16.4)',crop=751:92:45:45[blur_int15]; \
[v_int0]crop=839:180:544:444,boxblur=16:enable='between(t,14.96,16.4)',crop=749:90:45:45[blur_int16]; \
[v_int0]crop=837:178:545:445,boxblur=17:enable='between(t,14.96,16.4)',crop=747:88:45:45[blur_int17]; \
[v_int0]crop=835:176:546:446,boxblur=18:enable='between(t,14.96,16.4)',crop=745:86:45:45[blur_int18]; \
[v_int0]crop=833:174:547:447,boxblur=19:enable='between(t,14.96,16.4)',crop=743:84:45:45[blur_int19]; \
[v_int0]crop=831:172:548:448,boxblur=20:enable='between(t,14.96,16.4)',crop=741:82:45:45[blur_int20]; \
[v_int0]crop=829:170:549:449,boxblur=21:enable='between(t,14.96,16.4)',crop=739:80:45:45[blur_int21]; \
[v_int0]crop=827:168:550:450,boxblur=22:enable='between(t,14.96,16.4)',crop=737:78:45:45[blur_int22]; \
[v_int0]crop=825:166:551:451,boxblur=23:enable='between(t,14.96,16.4)',crop=735:76:45:45[blur_int23]; \
[v_int0]crop=823:164:552:452,boxblur=24:enable='between(t,14.96,16.4)',crop=733:74:45:45[blur_int24]; \
[v_int0]crop=821:162:553:453,boxblur=25:enable='between(t,14.96,16.4)',crop=731:72:45:45[blur_int25]; \
[v_int0][blur_int1]overlay=574:474:enable='between(t,14.96,16.4)'[v_int1]; \
[v_int1][blur_int2]overlay=575:475:enable='between(t,14.96,16.4)'[v_int2]; \
[v_int2][blur_int3]overlay=576:476:enable='between(t,14.96,16.4)'[v_int3]; \
[v_int3][blur_int4]overlay=577:477:enable='between(t,14.96,16.4)'[v_int4]; \
[v_int4][blur_int5]overlay=578:478:enable='between(t,14.96,16.4)'[v_int5]; \
[v_int5][blur_int6]overlay=579:479:enable='between(t,14.96,16.4)'[v_int6]; \
[v_int6][blur_int7]overlay=580:480:enable='between(t,14.96,16.4)'[v_int7]; \
[v_int7][blur_int8]overlay=581:481:enable='between(t,14.96,16.4)'[v_int8]; \
[v_int8][blur_int9]overlay=582:482:enable='between(t,14.96,16.4)'[v_int9]; \
[v_int9][blur_int10]overlay=583:483:enable='between(t,14.96,16.4)'[v_int10]; \
[v_int10][blur_int11]overlay=584:484:enable='between(t,14.96,16.4)'[v_int11]; \
[v_int11][blur_int12]overlay=585:485:enable='between(t,14.96,16.4)'[v_int12]; \
[v_int12][blur_int13]overlay=586:486:enable='between(t,14.96,16.4)'[v_int13]; \
[v_int13][blur_int14]overlay=587:487:enable='between(t,14.96,16.4)'[v_int14]; \
[v_int14][blur_int15]overlay=588:488:enable='between(t,14.96,16.4)'[v_int15]; \
[v_int15][blur_int16]overlay=589:489:enable='between(t,14.96,16.4)'[v_int16]; \
[v_int16][blur_int17]overlay=590:490:enable='between(t,14.96,16.4)'[v_int17]; \
[v_int17][blur_int18]overlay=591:491:enable='between(t,14.96,16.4)'[v_int18]; \
[v_int18][blur_int19]overlay=592:492:enable='between(t,14.96,16.4)'[v_int19]; \
[v_int19][blur_int20]overlay=593:493:enable='between(t,14.96,16.4)'[v_int20]; \
[v_int20][blur_int21]overlay=594:494:enable='between(t,14.96,16.4)'[v_int21]; \
[v_int21][blur_int22]overlay=595:495:enable='between(t,14.96,16.4)'[v_int22]; \
[v_int22][blur_int23]overlay=596:496:enable='between(t,14.96,16.4)'[v_int23]; \
[v_int23][blur_int24]overlay=597:497:enable='between(t,14.96,16.4)'[v_int24]; \
[v_int24][blur_int25]overlay=598:498:enable='between(t,14.96,16.4)'[v_int25]; \
[v_int25]null[with_subtitles]" \
-map "[with_subtitles]" -map 0:a -c:v libx264 -c:a copy -crf 17 -slow preset -y video_to_be_blurred_blurred.mp4
答案4
由于您具体询问的是视频中模糊脸部的问题,而不是使用 ffmpeg 模糊区域的问题:
这是污损该项目将视频分成几帧,使用 OpenCV 和训练有素的神经网络检测人脸,并对这些位置应用模糊处理。
结果一般,对于任何真正重要的匿名化来说,它都无法使用,因为有很多误报。但如果有一张清晰可见、没有遮挡的脸,不在视频的边缘,它就完成了任务。
Deface 的一些简单改进可以修复误报/阳性,请参阅项目的票证。因此,如果您恰好是一名程序员,我鼓励您分叉并实现这些改进 :)