FFmpeg - Aplicar desenfoque sobre la cara

25

Estoy tratando de desenfocar una parte de un video usando FFmpeg (específicamente para desenfocar una cara).

He estado tratando de usar una combinación de edición de línea de tiempo y varios filtros de desenfoque, pero no puedo encontrar una manera de desenfocar solo una sección del video.

Estoy esperando algo como:

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

Donde width/ heightes el tamaño del cuadro borroso y x/ yson la ubicación del cuadro borroso.

¿Es posible algo así?

occvtech
fuente

Respuestas:

34

Es posible aplicar un desenfoque temporal y espacial a un segmento / sección, suponiendo que el área que desea desenfocar sea una ubicación estática.

Cachorro de laboratorio negro
Imagen original de cachorro de laboratorio negro.

Usando una imagen de máscara

ingrese la descripción de la imagen aquíingrese la descripción de la imagen aquí
Imagen de máscara PNG en escala de grises y la imagen borrosa resultante.

Puede crear una imagen de máscara de escala de grises para indicar el área que se va a desenfocar. Para facilitar su uso, debe ser del mismo tamaño que la imagen o el video que desea desenfocar.

Ejemplo utilizando alphamerge , boxblur , y superposición :

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
  • El área blanca es donde se producirá el desenfoque, pero esto se puede revertir fácilmente con el filtro de negación, por ejemplo:[1:v]negate[mask];[0:v][mask]alphamerge,boxblur=10[alf]...

  • Puede usar el filtro geq para generar una máscara como un gradiente.

Desenfoque de área específica (sin máscara)

Cachorro de laboratorio negro con efecto de desenfoque

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: Los números de desplazamiento xey en superposición ( 60y 30en este ejemplo) deben coincidir con los desplazamientos de recorte.

Lo que hace este ejemplo:

  1. Recorte la copia para que tenga el tamaño del área que se va a desenfocar. En este ejemplo: un cuadro de 200x200 píxeles que está a 60 píxeles a la derecha ( xeje) y 30 píxeles hacia abajo ( yeje) desde la esquina superior izquierda.
  2. Desenfoque el área recortada.
  3. Superponga el área borrosa usando los mismos parámetros xy ydel filtro de recorte .

Múltiples desenfoques sobre áreas específicas (sin máscara)

ingrese la descripción de la imagen aquí
Áreas borrosas en la parte superior izquierda, cerca del 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 no borrosa (sin máscara)

ingrese la descripción de la imagen aquí

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

Cosas adicionales

lema
fuente
Muchas gracias por su respuesta. Todo eso tiene mucho sentido. Como nota al margen, ¡también hizo que el filtro dividido tuviera sentido finalmente! Además, ¿podría ser posible mediante expresiones aritméticas mover dinámicamente el cuadro borroso alrededor de la imagen? ¿IE con el propósito de desenfocar la cara de alguien mientras se mueve de manera no lineal?
occvtech
¡Gracias de nuevo! Voy a echarle un vistazo. Sé que un editor no lineal sería 1000 veces más fácil aquí, pero espero procesar por lotes múltiples archivos y no quiero esperar el proceso de importación / fotograma clave / exportación. ¡Gracias de nuevo!
occvtech
1
¿FFMPEG ofrece otras formas además de cajas, como círculos?
Dom
@LordNeckbeard Estoy usando cmd y quiero usar el Ejemplo 1, pero cuando ejecuto el código obtengo este errorUnrecognized 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, noté que a mi comando de ejemplo le faltaba una cita. Tu comando debería verse así: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

Para el caso en que a uno no le gusta el borde afilado del desenfoque, hice un script que superpone diferentes etapas de desenfoque para que el borde no sea nítido y se vea así:Softly_blurred_image

En lugar de esto:Imagen original

Es un script de 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")

Puede cambiar los parámetros en las últimas y penúltimas líneas, los dos últimos parámetros entre las marcas de cuatación son la ruta de su video y el video de salida (suponiendo que se coloquen en el directorio de trabajo). En la penúltima línea:

  • los primeros dos números indican el tamaño del área inicial a la que se aplicará el desenfoque máximo,
  • los segundos dos indican las coordenadas x e y de los mismos,
  • los terceros dos indican los tiempos en segundos cuando se debe aplicar el desenfoque,
  • "25" en este ejemplo indica que habrá 25 cuadros aplicados uno encima del otro)
  • el siguiente "1" indica que los cuadros más grandes con menos desenfoque deberían ser solo un píxel más anchos que sus predecesores
  • el segundo "1" indica que el desenfoque debería aumentar en uno hasta un máximo de 25 (desde arriba)
  • "30" indica el margen que se tiene en cuenta para aplicar el desenfoque, por lo que aumentar esto hace que el desenfoque respete más su entorno. El aumento de este valor también resuelve el error enviado por mensaje de texto comoInvalid chroma radius value 21, must be >= 0 and <= 20

Al ejecutarlo, se debe obtener una salida como la siguiente (se escribe en un archivo que se puede ejecutar e imprimir en la salida que se puede copiar y ejecutar):

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
cenar
fuente
Si alguien sabe de una manera más fácil de lograr bordes borrosos, me interesaría. Además, esto es bastante lento.
sup
Aplique un cuadro borroso a la máscara antes de fusionarla.
Gyan
@Gyan ¿Qué quieres decir? Creo que ya estoy haciendo eso.
Sup
De todos modos, mejoré el código más adelante, todavía no estoy seguro de estar haciendo lo que me recomendó.
sup