FFmpeg - применить размытие на лице
Я пытаюсь размыть часть видео с помощью FFmpeg (особенно для размытия лица).
Я пытался использовать комбинацию редактирования временной шкалы и различных фильтров размытия, но я не могу найти способ размыть только часть видео.
Я надеюсь на что-то вроде:
-vf boxblur=enable='between(t,10,100)':width=20:height=20:x=400:y=200
куда width
/height
размер размытой коробки и x
/y
расположение размытой коробки.
Возможно ли что-то подобное?
4 ответа
Можно применить временное и пространственное размытие к сегменту / сечению - предполагая, что область, которую вы хотите размыть, является статическим местоположением.
Оригинальное черное лабораторное изображение щенка.
Используя изображение маски
Оттенки серого PNG маскируют изображение и получаются размытые изображения.
Вы можете сделать изображение в градациях серого, чтобы указать область размытия. Для простоты использования он должен быть того же размера, что и изображение или видео, которые вы хотите размыть.
Пример использования alphamerge, boxblur и overlay:
ffmpeg -i video.mp4 -i mask.png -filter_complex "[0:v][1:v]alphamerge,boxblur=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,boxblur=10[alf]...
Вы можете использовать фильтр geq для создания маски, такой как градиент.
Размытие определенной области (без маски)
ffmpeg -i derpdog.mp4 -filter_complex \
"[0:v]crop=200:200:60:30,boxblur=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 и y в оверлее (60
а также 30
в этом примере) должен соответствовать смещению обрезки.
Что делает этот пример:
- Обрежьте копию, чтобы получить размер области, которая будет размыта. В этом примере: поле размером 200x200 пикселей, 60 пикселей справа (
x
ось) и 30 пикселей вниз (y
ось) от верхнего левого угла. - Размыть обрезанную область.
- Наложить размытую область, используя тот же
x
а такжеy
параметры из фильтра обрезки.
Многократные размытия на определенных участках (без маски)
Размытые области вверху слева, около центра и снизу.
"[0:v]crop=50:50:20:10,boxblur=10[b0]; \
[0:v]crop=iw:30:(iw-ow)/2:ih-oh,boxblur=10[b1]; \
[0:v]crop=100:100:120:80,boxblur=10[b2]; \
[0:v][b0]overlay=20:10[ovr0]; \
[ovr0][b1]overlay=(W-w)/2:H-h[ovr1]; \
[ovr1][b2]overlay=120:80"
Удельная площадь не размыта (без маски)
"[0:v]boxblur=10[bg];[0:v]crop=200:200:60:30[fg];[bg][fg]overlay=60:30"
Дополнительные вещи
Аудио воспроизводится в потоковом режиме (переупаковывается). Нет перекодирования, поэтому оно быстрое и сохраняет качество.
Размытая область будет иметь твердый край.
Размытую область можно перемещать, если вы хорошо разбираетесь в арифметических выражениях или видите фильтры sendcmd или zmq.
Если вы хотите размыть в течение определенного времени, используйте
enable
вариант на boxblur или наложение.См. Документацию FFmpeg Filters для других фильтров размытия (sab, smartblur, unsharp).
Некоторые связанные вопросы: Как размыть короткую сцену в видео и Как добавить пиксельный эффект.
Для которых не удалось указать продолжительность, вот пример
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
Для случая, когда кому-то не нравится острый край размытия, я создал скрипт, который разбивает слои на разные этапы размытия, чтобы край не был резким и выглядел так:
Это скрипт на 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
Поскольку вы спрашиваете конкретно о размытии лица в видео, а не о размытии региона с помощью ffmpeg:
Есть проект Deface , который разбивает видео на кадры, распознает лица с помощью OpenCV и обученной нейронной сети и применяет к этим местам размытие.
Результаты так себе, его нельзя использовать для какой-либо серьезной анонимизации там, где это действительно важно, потому что очень много ложноотрицательных результатов. Но не по краю видео хорошо видно незакрытое лицо, оно делает свою работу.
Несколько простых улучшений Deface могут исправить ложноотрицательные/положительные результаты, см. билеты проекта. Так что, если вы программист, я советую вам создать и реализовать их :)