FFmpeg - Aplicar desfoque no rosto

25

Estou tentando desfocar uma parte do vídeo usando o FFmpeg (especificamente para desfocar um rosto).

Eu tenho tentado usar uma combinação de edição da linha do tempo e os vários filtros de desfocagem, mas não consigo encontrar uma maneira de desfocar apenas uma seção do vídeo.

Espero algo como:

-vf boxblur=enable='between(t,10,100)':width=20:height=20:x=400:y=200

Onde width/ heighté o tamanho da caixa desfocada e x/ yé o local da caixa desfocada.

É algo assim possível?

occvtech
fonte

Respostas:

33

É possível aplicar o desfoque temporal e espacial a um segmento / seção - assumindo que a área que você deseja desfocar seja um local estático.

Filhote de labrador preto
Imagem original do filhote de cachorro preto do laboratório.

Usando uma imagem de máscara

insira a descrição da imagem aquiinsira a descrição da imagem aqui
Imagem em máscara de escala de cinza PNG e imagem borrada resultante.

Você pode criar uma imagem de máscara em escala de cinza para indicar a área a desfocar. Para facilitar o uso, ele deve ter o mesmo tamanho da imagem ou do vídeo que você deseja desfocar.

Exemplo usando alphamerge , boxblur , e sobreposição de :

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
  • A área branca é onde o desfoque ocorrerá, mas isso pode ser facilmente revertido com o filtro de negação, por exemplo:[1:v]negate[mask];[0:v][mask]alphamerge,boxblur=10[alf]...

  • Você pode usar o filtro geq para gerar uma máscara, como um gradiente.

Desfocar área específica (sem máscara)

Filhote de laboratório preto com efeito de desfoque

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

Nota: Os números de deslocamento x e y na sobreposição ( 60e 30neste exemplo) devem corresponder às compensações de corte.

O que este exemplo faz:

  1. Corte a cópia para ter o tamanho da área a ser desfocada. Neste exemplo: uma caixa de 200 x 200 pixels com 60 pixels à direita ( xeixo) e 30 pixels abaixo ( yeixo) no canto superior esquerdo.
  2. Desfoque a área cortada.
  3. Sobreponha a área desfocada usando o mesmo xe os yparâmetros do filtro de corte .

Vários borrões em áreas específicas (sem máscara)

insira a descrição da imagem aqui
Áreas borradas no canto superior esquerdo, próximo ao centro e inferior.

"[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"

Área específica não desfocada (sem máscara)

insira a descrição da imagem aqui

"[0:v]boxblur=10[bg];[0:v]crop=200:200:60:30[fg];[bg][fg]overlay=60:30"

Coisas adicionais

llogan
fonte
Muito obrigado pela sua resposta. Tudo isso faz muito sentido. Como nota lateral, também fez o filtro de divisão finalmente fazer sentido! Além disso, através de expressões aritméticas, seria possível mover dinamicamente a caixa desfocada em torno da imagem? Ou seja, com o objetivo de desfocar o rosto de alguém enquanto ele se move de maneira não linear?
occvtech
Obrigado novamente! Eu vou dar um tempo nisso. Sei que um editor não linear seria 1000 vezes mais fácil aqui, mas espero processar em lote vários arquivos e não quero esperar o processo de importação / quadro-chave / exportação. Obrigado novamente!
Octvtech 16/04
1
o FFMPEG oferece outras formas além de caixas, como círculos?
Sun
@LordNeckbeard Estou usando cmd e eu quero usar Exemplo 1, mas quando eu executar o código eu recebo este erroUnrecognized option '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 output.mp4'. Error splitting the argument list: Option not found
Jim
1
@ Jim notei que meu comando de exemplo estava faltando uma citação. Seu comando deve ser algo parecido com isto:ffmpeg -i input.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 output.mp4
llogan
0

No caso de alguém não gostar da borda afiada do embaçamento, criei um script que envolve diferentes estágios do embaçamento, para que a borda não fique afiada e fique assim:Softly_blurred_image

Em vez disso:Imagem original

É um script 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")

Você pode alterar os parâmetros na última e na penúltima linha, os dois últimos parâmetros entre aspas são o caminho para o seu vídeo e o vídeo de saída (supondo que eles estejam no diretório de trabalho). Na penúltima linha:

  • os dois primeiros números indicam o tamanho da área inicial à qual o desfoque máximo será aplicado,
  • os dois segundos indicam as coordenadas xey das mesmas,
  • os terceiros dois indicam os tempos em segundos em que o desfoque deve ser aplicado,
  • "25" neste exemplo indica que haverá 25 caixas aplicadas umas sobre as outras)
  • o próximo "1" indica que caixas maiores com menos desfoque devem ser apenas um pixel mais largo que seus antecessores
  • o segundo "1" indica que o desfoque deve aumentar em um até o máximo de 25 (de cima)
  • "30" indica a margem que é levada em consideração para a aplicação do desfoque. Portanto, aumentar isso faz com que o desfoque respeite mais o ambiente. Aumentar esse valor também resolve o erro da mensagem de texto, comoInvalid chroma radius value 21, must be >= 0 and <= 20

Ao executá-lo, deve-se obter uma saída como a seguinte (ela é gravada em um arquivo que pode ser executado e impresso na saída que pode ser copiada e executada):

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
sup
fonte
Se alguém souber de uma maneira mais fácil de obter bordas borradas, eu estaria interessado. Além disso, isso é bastante lento.
sup
Aplique um desfoque de caixa à máscara antes de mesclá-la.
Gyan 22/02
@Gyan O que você quer dizer? Eu acho que já estou fazendo isso.
sup
Enfim, aprimorei o código mais adiante, ainda não tenho certeza de que estou fazendo o que você recomendou.
sup