Estimación de flujo óptico (1) Introducción y funcionamiento del flujo óptico

¡Hoy es el 29 del Año Nuevo Lunar, y las coplas del Festival de Primavera se publicarán mañana! Se puede considerar como un artículo apresurado de hace unos años (no he publicado nada durante mucho tiempo o.o), y también se puede considerar como el comienzo de mi propia investigación sobre la parte de aprendizaje profundo de la estimación de flujo óptico. , pasantías, trabajo y otras cosas se amontonan como una montaña frente a mí. ¡Espero que todo vaya bien el próximo año!

1. El concepto básico del flujo óptico

1. Flujo óptico y campo de flujo óptico

(1) flujo óptico

El flujo óptico Algunas personas también definen la tasa de cambio instantáneo de escala de grises/brillo de un píxel específico en una imagen plana bidimensional como flujo óptico ( Optical flow can also be defined as the distribution of apparent velocities of movement of brightness pattern in an image.) , cuando el intervalo de tiempo es muy Horas (como entre dos fotogramas consecutivos de un vídeo) también equivalen al desplazamiento del punto de proyección de un punto espacial en el plano de la imagen . En términos generales, el flujo óptico es causado por el movimiento del propio objeto en primer plano en la escena, el movimiento de la cámara o el movimiento conjunto de los dos, lo que resulta en un movimiento relativo.

Hablando claramente También se puede entender como el flujo de intensidades de píxeles en una imagen. El flujo óptico expresa el cambio de la imagen y, debido a que contiene la información del movimiento del objetivo, el observador puede utilizarlo para determinar el movimiento del objetivo.

La imagen X (fotograma t-1) y la imagen Y (fotograma t) son generalmente dos fotogramas adyacentes en el flujo de video, y la posición de un determinado píxel A en la imagen X es ( x 1 , y 1 ) (x_1, y_1 )( X1,y1) , la posición en la imagen Y después del movimiento es( x 2 , y 2 ) (x_2,y_2)( X2,y2) , entoncesel flujo óptico de este punto de píxel A se puede calcular como( ux , uy ) = ( x 2 , y 2 ) − ( x 1 , y 1 ) (u_x,u_y) = (x_2,y_2) - (x_1 , y_1)( tux,tutu)=( X2,y2)( X1,y1) , vector( ux , uy ) (u_x,u_y)( tux,tutu) es el flujo óptico generado por el píxel, que incluye movimiento en la dirección xey en la dirección y, y el valor del flujo óptico es un valor de punto flotante de subpíxel. Como se muestra en la Figura 1 a continuación, el punto A en la imagen de la izquierda se mueve hacia la imagen de la derecha, y la flecha indica el vector de flujo óptico del punto A entre dos marcos adyacentes.
inserte la descripción de la imagen aquí

(2) campo de flujo óptico

La colección de una serie El campo de flujo óptico se refiere a un campo de velocidad instantáneo bidimensional (2D) compuesto por una serie de píxeles en la imagen. El vector de velocidad bidimensional es la proyección del vector de velocidad tridimensional del punto visible en el objeto de destino. En la superficie de imagen En términos generales, el campo de movimiento tridimensional Corresponde a un campo de flujo óptico formado en una imagen bidimensional por proyección.
inserte la descripción de la imagen aquí

2. Método de flujo óptico y campo deportivo.

(1) campo de deportes

El campo de deportes es en realidad el movimiento de objetos en el mundo real tridimensional. Una serie de vectores de movimiento constituyen el campo de deportes , que se puede utilizar para describir el estado real de movimiento de los objetos. El campo de movimiento en el espacio se proyecta en un plano de imagen bidimensional (ojos humanos o cámara) para representar un campo de flujo óptico. La relación entre el campo de movimiento y el campo de flujo óptico se muestra en la siguiente figura.
inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

De lo anterior se puede ver que la relación entre el vector de flujo óptico y el vector de movimiento es muy estrecha, pero los dos no son completamente consistentes, o no hay necesariamente una correspondencia completa entre el campo deportivo y su campo de flujo óptico. Porque la generación de flujo óptico se debe al movimiento relativo entre el objeto y la cámara, y este movimiento relativo no es completamente igual al estado de movimiento real. Hay un ejemplo común en la vida: las barberías a menudo usan letreros giratorios para atraer clientes (como se muestra en la figura a continuación). En este momento, desde la perspectiva del campo de flujo óptico, los letreros giran hacia arriba, pero desde la perspectiva del campo de deportes Por lo que parece, el letrero en realidad se mueve horizontalmente. Por lo tanto, el campo de flujo óptico no es estrictamente igual a su campo deportivo , pero esta situación es poco común. En la mayoría de los casos, el rendimiento de los dos es consistente. Entonces supondremos que el campo de flujo óptico corresponde al campo deportivo , que es también Nuestra aplicación a problemas relacionados con vectores de movimiento brinda la posibilidad.
inserte la descripción de la imagen aquí

(2) método de flujo óptico

Debido a que es muy difícil calcular y analizar directamente el campo de movimiento en un espacio tridimensional, y el campo de movimiento corresponde al campo de flujo óptico formado en la imagen bidimensional por proyección, y el flujo óptico es esencialmente la proyección de la movimiento del objeto de la escena tridimensional al plano de la imagen bidimensional Los cambios de brillo de los píxeles representados no solo contienen la información de movimiento del objeto observado, sino que también contienen información rica sobre la estructura tridimensional de la escena. Por lo tanto, los objetos en movimiento se pueden analizar a través del análisis de flujo óptico , y el método de flujo óptico ha surgido como lo requieren los tiempos y se ha convertido en una herramienta importante para analizar objetos en movimiento en la visión por computadora.

El método de flujo óptico utiliza los cambios de píxeles en la secuencia de imágenes en el dominio del tiempo y la correlación entre cuadros adyacentes para encontrar la relación correspondiente entre el cuadro anterior y el cuadro actual, a fin de calcular la distancia de los objetos entre cuadros adyacentes. Un método de información de movimiento, es decir, un método para estimar el estado de movimiento real de un objeto (campo de flujo óptico => campo de movimiento) a partir de datos de imágenes bidimensionales . El propósito de estudiar el campo de flujo óptico es aproximar el campo de movimiento que no se puede obtener directamente de las imágenes de secuencia y estimar la velocidad y la dirección del movimiento del objeto de acuerdo con el cambio de intensidad del valor de gris del píxel en la imagen. En un caso ideal general, el campo de flujo óptico debería corresponder al campo de movimiento.

3. Flujo óptico disperso y flujo óptico denso

El resultado ideal de un cálculo de flujo óptico es una correlación estimada de la velocidad de cada píxel en las dos imágenes, o de manera equivalente, un vector de desplazamiento para cada píxel en una imagen, que indica la posición relativa de ese píxel en la otra imagen, si este método se utiliza para cada píxel de la imagen, generalmente se denomina " flujo óptico denso "; si solo se rastrea un subconjunto de ciertos puntos de la imagen , se denomina " flujo óptico disperso ".

(1) flujo óptico denso

El flujo óptico denso es un método de cálculo de flujo óptico que realiza cálculos de coincidencia punto por punto para una imagen o un área específica Calcula el desplazamiento de todos los puntos en la imagen para formar un campo de flujo óptico denso. A través de este denso campo de flujo óptico, se puede realizar el registro de imágenes a nivel de píxel. Debido a que el vector de flujo óptico es denso, el efecto de su registro es obviamente mejor que el del registro de flujo óptico disperso. Sin embargo, sus efectos secundarios también son relativamente obvios. Debido a que es necesario calcular el desplazamiento de cada píxel, la cantidad de cálculo también es obviamente grande y la puntualidad es deficiente.

(2) Flujo óptico escaso

El flujo óptico disperso un conjunto de puntos para el seguimiento . Este conjunto de puntos debe tener preferiblemente algunas características obvias, como puntos de esquina de Harris, etc. ., para que el seguimiento sea relativamente estable y confiable. El seguimiento disperso es mucho menos costoso computacionalmente que el seguimiento denso.
inserte la descripción de la imagen aquí

4. Estimación de flujo óptico

La estimación del flujo óptico es un método para establecer/computar el campo de flujo óptico entre dos fotogramas de imágenes. Los métodos comunes de estimación de flujo óptico incluyen métodos basados ​​en gradientes, métodos basados ​​en emparejamiento, métodos basados ​​en aprendizaje profundo, métodos basados ​​en energía, etc. En los siguientes estudios, nos centraremos en métodos de investigación basados ​​en aprendizaje profundo. De la introducción anterior, se puede ver que el problema central de la estimación del flujo óptico es cómo hacer coincidir los píxeles correspondientes de dos imágenes, para calcular el vector de flujo óptico correspondiente.
inserte la descripción de la imagen aquí

2. Representación y visualización del flujo óptico

1. Método de representación de flujo óptico

El resultado de la estimación del flujo óptico es una matriz del mismo tamaño que la imagen original双通道 , que generalmente se representa mediante una matriz tridimensional de coma flotante [alto, ancho, 2] . Entre ellos, el primer canal (alto, ancho, 0) representa el vector de desplazamiento en dirección x (dirección horizontal o dirección del vector de fila de imagen) del píxel en (alto, ancho); y el segundo canal (alto, ancho, 1) representa (alto, ancho) el vector de desplazamiento en la dirección y (dirección vertical o dirección del vector de la columna de la imagen) del píxel. Para tener cuidado con:

  • El valor numérico en la matriz de flujo óptico indica la compensación, y los valores positivos y negativos indican la dirección de compensación
  • El objeto de aplicación final de la matriz de flujo óptico son las coordenadas de píxel (x, y) del marco de imagen bidimensional , no el valor de píxel en (x, y)
  • Los valores en la matriz de flujo óptico son números de punto flotante, no enteros. Esto significa que después de la operación de deformación de flujo óptico, las coordenadas de píxeles de la imagen del cuadro t-1 pueden no caer exactamente en las coordenadas enteras de la imagen del cuadro t, y es posible que se requiera otro procesamiento.

2. Visualización de flujo óptico

​El resultado del cálculo del flujo óptico es una matriz de números de punto flotante tridimensional de dos canales. En muchos casos, necesitamos visualizar el resultado del flujo óptico para reflejar intuitivamente el estado de movimiento del objeto. Como un campo vectorial, el campo de flujo óptico necesita mostrar la magnitud y la dirección de cada vector al mismo tiempo cuando se visualiza Por lo tanto, existen dos métodos comunes de visualización de flujo óptico de la siguiente manera:

(1) diagrama de flecha de flujo óptico

​El método de visualización más simple es usar flechas para representar el flujo óptico, donde la dirección y la longitud de la flecha representan la dirección y el tamaño de cada vector de flujo óptico , como se muestra en la siguiente figura. La ventaja de usar flechas para representar el flujo óptico es que es simple e intuitivo, pero también tiene algunas deficiencias. En primer lugar, de esta manera, el flujo óptico de cada píxel se representa con flechas una por una. Cuando se aumenta la resolución de la imagen y los píxeles del flujo óptico son muy densos, la representación completa del flujo óptico no se puede lograr en un número limitado. área; en segundo lugar, con el aumento en la densidad de la flecha hará que la imagen sea muy desordenada. Por lo tanto, el diagrama de flechas de flujo óptico es generalmente adecuado para la visualización de flujo óptico disperso .
inserte la descripción de la imagen aquí

(2) diagrama de cromaticidad de flujo óptico

Para el flujo óptico denso, podemos colorear el flujo óptico con el resultado del cálculo del flujo óptico a través del modelo de color y visualizarlo en forma de mapa de pseudocolor (mapa de color RGB) . Entre ellos, el matiz (o matiz, es decir, diferentes colores) indica la dirección del movimiento , la saturación (o intensidad del matiz, es decir, la profundidad del color) indica la velocidad del movimiento o el tamaño del desplazamiento , y el La posición más central representa que no hay movimiento y se produce un desplazamiento, hacia arriba El color es blanco. Hay dos métodos principales para convertir los resultados del cálculo del flujo óptico en un diagrama de cromaticidad, que presentaremos a continuación.La rueda de colores para la referencia de visualización de todo el diagrama de cromaticidad es la siguiente:
inserte la descripción de la imagen aquí

(1) conversión de modelo de color HSV

HSV es un método para representar el espacio de color RGB como un cono, donde H representa tono (tono, tipo de color), S representa saturación (intensidad de tono, profundidad de color) y V representa valor (brillo). Los tres componentes principales del modelo HSV se presentan a continuación:

  • H (tono, tono): este parámetro se representa mediante un ángulo y el rango de valores es de 0°~360°. Si comienza desde el rojo y cuenta en sentido antihorario, el rojo es 0°, el verde es 120° y el azul es 240°. Sus colores complementarios son: el amarillo es 60°, el cian es 180°, el violeta es 300°;
  • S (saturación, intensidad del matiz): Escala radial, el rango de valores es 0,0~1,0. La saturación indica el grado en que el color se acerca al color espectral, y cualquier color puede considerarse como el resultado de mezclar cierto color espectral con blanco. Entre ellos, cuanto mayor sea la proporción de color espectral, mayor será el grado de color cercano al color espectral, mayor será la saturación de color y más profundo el color.
  • V (luminosidad, brillo): dirección vertical, el rango de valores es 0,0 (negro, inferior) ~ 1,0 (blanco, superior), lo que indica el brillo del color.
    inserte la descripción de la imagen aquí

Al usar Los pasos específicos son:

  • Primero, el tamaño del flujo óptico debe normalizarse y luego la dirección del flujo óptico debe asignarse al componente de tono H. Debido a que el campo de flujo óptico es una matriz tridimensional de dos canales, el vector en cada posición se puede expresar como coordenadas (x, y) en el sistema de coordenadas cartesianas. Luego, podemos convertir aún más el sistema de coordenadas cartesianas xey en coordenadas polares, donde el ángulo polar actan2(y,x) representa la dirección (asignada al tono del modelo HSV)
  • Luego, la magnitud del flujo óptico se asigna al componente de saturación S, cuanto mayor sea el flujo óptico, mayor será la saturación, y el lugar donde el flujo óptico es 0 se muestra en blanco. En el sistema de coordenadas polares, el radio polar (la raíz cuadrada de x e y) representa el tamaño del desplazamiento
  • Finalmente, la componente de luminancia V se puede unificar a un solo valor. Por ejemplo, para que la imagen sea más fácil de observar, se puede fijar en el 255 más brillante. Finalmente, convierta la representación del modelo HSV en un mapa de pseudo-color en formato RGB para su visualización.

Los artículos de referencia y los códigos de muestra son los siguientes:

inserte la descripción de la imagen aquí

def viz_flow(flow):
    # 色调H:用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°
    # 饱和度S:取值范围为0.0~1.0
    # 亮度V:取值范围为0.0(黑色)~1.0(白色)
    h, w = flow.shape[:2]
    hsv = np.zeros((h, w, 3), np.uint8)
    # cv2.cartToPolar(x, y[, magnitude[, angle[, angleInDegrees]]]) → magnitude, angle
    #	- params x,y:直角坐标系的横坐标、纵坐标,ndarray 多维数组,浮点型。默认为弧度制
    #	- return magnitude, angle:极坐标系下的极径值、极角值,ndarray 多维数组,与输入的 x, y 具有相同的尺寸和数据类型
    mag, ang = cv2.cartToPolar(flow[...,0], flow[...,1])
    hsv[...,0] = ang*180/np.pi/2 # 弧度转化为角度
    hsv[...,1] = cv2.normalize(mag,None,0,255,cv2.NORM_MINMAX) #标准化
    # flownet是将V赋值为255, 此函数遵循flownet,饱和度S代表像素位移的大小,亮度都为最大,便于观看
    # 也有的光流可视化讲s赋值为255,亮度代表像素位移的大小,整个图片会很暗,很少这样用
    hsv[...,2] = 255
    # cv2.cvtColor(frame,COLOR_STYLE) 改变图像的颜色空间,opencv中默认的颜色空间是BGR
    # backward conversions HSV to RGB/BGR with H range 0..180 if 8 bit image
    bgr = cv2.cvtColor(hsv,cv2.COLOR_HSV2BGR)
    return bgr

(2) Conversión del sistema de color Munsell

Este método utiliza el sistema de color Munsell (MunsellColor System, Wiki ) para transformar los resultados del flujo óptico. MunsellColor System es un sistema de descripción de color creado por el artista estadounidense Albert H. Munsell (Albert H. Munsell, 1858-1918) en 1898. Utiliza un cilindro para dividir aproximadamente el espacio de color, y usted puede comprender el conocimiento específico por sí mismo. . Este método se ha utilizado en muchos artículos (FlowNet, PWC-Net, etc.) para visualizar los resultados de los cálculos de flujo óptico y ha recibido mucha verificación.
inserte la descripción de la imagen aquí

Los artículos de referencia y los códigos de muestra son los siguientes:

import numpy as np

def make_colorwheel():
    """
    Generates a color wheel for optical flow visualization as presented in:
        Baker et al. "A Database and Evaluation Methodology for Optical Flow" (ICCV, 2007)
        URL: http://vision.middlebury.edu/flow/flowEval-iccv07.pdf
    Code follows the original C++ source code of Daniel Scharstein.
    Code follows the the Matlab source code of Deqing Sun.
    Returns:
        np.ndarray: Color wheel
    """

    RY = 15
    YG = 6
    GC = 4
    CB = 11
    BM = 13
    MR = 6

    ncols = RY + YG + GC + CB + BM + MR
    colorwheel = np.zeros((ncols, 3))
    col = 0

    # RY
    colorwheel[0:RY, 0] = 255
    colorwheel[0:RY, 1] = np.floor(255*np.arange(0,RY)/RY)
    col = col+RY
    # YG
    colorwheel[col:col+YG, 0] = 255 - np.floor(255*np.arange(0,YG)/YG)
    colorwheel[col:col+YG, 1] = 255
    col = col+YG
    # GC
    colorwheel[col:col+GC, 1] = 255
    colorwheel[col:col+GC, 2] = np.floor(255*np.arange(0,GC)/GC)
    col = col+GC
    # CB
    colorwheel[col:col+CB, 1] = 255 - np.floor(255*np.arange(CB)/CB)
    colorwheel[col:col+CB, 2] = 255
    col = col+CB
    # BM
    colorwheel[col:col+BM, 2] = 255
    colorwheel[col:col+BM, 0] = np.floor(255*np.arange(0,BM)/BM)
    col = col+BM
    # MR
    colorwheel[col:col+MR, 2] = 255 - np.floor(255*np.arange(MR)/MR)
    colorwheel[col:col+MR, 0] = 255
    return colorwheel


def flow_uv_to_colors(u, v, convert_to_bgr=False):
    """
    Applies the flow color wheel to (possibly clipped) flow components u and v.
    According to the C++ source code of Daniel Scharstein
    According to the Matlab source code of Deqing Sun
    Args:
        u (np.ndarray): Input horizontal flow of shape [H,W]
        v (np.ndarray): Input vertical flow of shape [H,W]
        convert_to_bgr (bool, optional): Convert output image to BGR. Defaults to False.
    Returns:
        np.ndarray: Flow visualization image of shape [H,W,3]
    """
    flow_image = np.zeros((u.shape[0], u.shape[1], 3), np.uint8)
    colorwheel = make_colorwheel()  # shape [55x3]
    ncols = colorwheel.shape[0]
    rad = np.sqrt(np.square(u) + np.square(v))
    a = np.arctan2(-v, -u)/np.pi
    fk = (a+1) / 2*(ncols-1)
    k0 = np.floor(fk).astype(np.int32)
    k1 = k0 + 1
    k1[k1 == ncols] = 0
    f = fk - k0
    for i in range(colorwheel.shape[1]):
        tmp = colorwheel[:,i]
        col0 = tmp[k0] / 255.0
        col1 = tmp[k1] / 255.0
        col = (1-f)*col0 + f*col1
        idx = (rad <= 1)
        col[idx]  = 1 - rad[idx] * (1-col[idx])
        col[~idx] = col[~idx] * 0.75   # out of range
        # Note the 2-i => BGR instead of RGB
        ch_idx = 2-i if convert_to_bgr else i
        flow_image[:,:,ch_idx] = np.floor(255 * col)
    return flow_image


def flow_to_color(flow_uv, clip_flow=None, convert_to_bgr=False):
    """
    Expects a two dimensional flow image of shape.
    Args:
        flow_uv (np.ndarray): Flow UV image of shape [H,W,2]
        clip_flow (float, optional): Clip maximum of flow values. Defaults to None.
        convert_to_bgr (bool, optional): Convert output image to BGR. Defaults to False.
    Returns:
        np.ndarray: Flow visualization image of shape [H,W,3]
    """
    assert flow_uv.ndim == 3, 'input flow must have three dimensions'
    assert flow_uv.shape[2] == 2, 'input flow must have shape [H,W,2]'
    if clip_flow is not None:
        flow_uv = np.clip(flow_uv, 0, clip_flow)
    u = flow_uv[:,:,0]
    v = flow_uv[:,:,1]
    rad = np.sqrt(np.square(u) + np.square(v))
    rad_max = np.max(rad)
    epsilon = 1e-5
    u = u / (rad_max + epsilon)
    v = v / (rad_max + epsilon)
    return flow_uv_to_colors(u, v, convert_to_bgr)

3. Deformación de flujo óptico

warp se puede traducir como distorsión, deformación y mapeo El significado de la operación de deformación de flujo óptico es aplicar el flujo óptico calculado al cuadro de imagen de destino para obtener el cuadro de imagen resultante después de que el flujo óptico afecta la compensación o la transformación de movimiento. . Por ejemplo, si hay un flujo óptico de t->t+1 cuadro de imagen, lo aplicamos al cuadro de imagen t, entonces el resultado ideal debería ser el cuadro de imagen t+1, y todo el proceso de transformación es una especie de operación de deformación de flujo óptico. La deformación de flujo óptico incluye principalmente deformación hacia adelante y deformación hacia atrás , que se presentarán a continuación.
inserte la descripción de la imagen aquí

1. deformación hacia adelante

​Si hay dos fotogramas de imágenes adyacentes (o izquierda y derecha) I 1 , I 2 I_1,I_2I1,I2,对应I 1 → I 2 I_1 \rightarrow I_2I1I2El flujo óptico Flujo es F 1 → 2 F_{1\rightarrow2}F1 2(El flujo óptico es la relación de desplazamiento de los puntos correspondientes en las dos imágenes), luego, bajo la operación de deformación hacia adelante, el valor de píxel de la imagen del primer cuadro I 1 ( x , y ) I_1(x,y)I1( X ,y ) aparecerá en el segundo cuadro de la imagenI 2 ( ( x , y ) + F 1 → 2 ) I_2((x,y)+F_{1\rightarrow2})I2(( x ,y )+F1 2) 坐标位置上,即 I 1 ( x , y ) = I 2 ( x + Δ x , y + Δ y ) I_1(x,y) = I_2(x+\Delta x,y+\Delta y) I1( X ,y )=I2( X+Δx , _y+Δ y ),其中F 1 → 2 ( x , y ) = ( Δ x , Δ y ) F_{1\rightarrow2}(x,y) = (\Delta x,\Delta y)F1 2( X ,y )=( Δ x ,y ) _ _

La deformación hacia adelante se puede entender simplemente como "deformación/distorsión hacia adelante", es decir, la dirección de transformación de la imagen es la misma que la dirección del flujo del flujo óptico , lo cual es consistente con nuestro pensamiento cognitivo inherente. Por ejemplo, use I 1 → I 2 I_1\rightarrow I_2I1I2El flujo óptico será I 1 I_1I1Transformar a I 2 I_2I2perspectiva, esta es una deformación hacia adelante;
inserte la descripción de la imagen aquí

​La idea de la deformación hacia adelante es atravesar cada punto , a través del flujo óptico FS source → D estino F_{Source\rightarrow Destination}source imagep_sourceFFuente Destino _ _ _ _ _ _ _ _ _El desplazamiento de coordenadas en el punto medio se obtiene p_sourceproyectando su valor de píxel en Si las coordenadas no son números enteros, generalmente se redondea hacia arriba o se selecciona el vecino más cercano . Su código de implementación simple es el siguiente:destination imagep_destinationp_destination

im1 = torch.zeros_like(im0)
B = im0.shape[0]
H = im0.shape[2]
W = im0.shape[3]
round_flow = torch.round(flow)
for b in range(B):
    # 遍历source image中的每个点p_source
	for h in range(H):
		for w in range(W):
            # 获取投影到destination image中的对应坐标点p_destination,采用四舍五入取整
			x = w + int(round_flow[b, h, w, 0])
			y = h + int(round_flow[b, h, w, 1])
            # 判断映射位置是否在有效范围内,若在则赋值,否则保留zero
			if x >= 0 and x < W and y >= 0 and y < H:
				im1[b, :, y, x] = im0[b, :, h, w]
return im1

​La implementación y la idea de la deformación hacia adelante es muy simple, pero también trae muchos problemas:

  • Problema de agujeros: la relación de mapeo de la deformación directa no es inyectiva ni sobreyectiva, sino una asignación aleatoria discretizada. Esto conducirá a destination imagealgunas posiciones en las que no haysource image puntos proyectados desde él tienen múltiplessource image puntos proyectados desde Su solución se considera de la siguiente manera:

    • Mapeo multipunto: para la situación en la que se asignan varios puntos a un punto al mismo tiempo, podemos elegir el punto con el "rango de movimiento" más grande , porque el "rango de movimiento" suele ser el primer plano, el primer plano se mueve más, y el primer plano está principalmente reservado.
    • Mapeo sin sentido: esta situación generalmente se considera manejada por interpolación. Sin embargo, como marco proyectado, los puntos en cada posición no están distribuidos uniformemente. Es difícil usar directamente el algoritmo de interpolación bilinealdestination image que requiere una posición lineal fija. La forma más fácil es usar directamente el vecino más cercano o redondear hacia arriba.

    Por supuesto, también hay algunas personas que se especializan en cómo resolver el problema de los vacíos de deformación hacia adelante y han propuesto muchas ideas y métodos nuevos, como el artículo softmax-splatting .

  • Limitaciones técnicas: debido a que el vecino más cercano o el método de redondeo se usa a menudo para tomar puntos en la deformación hacia adelante, esto hace que sea imposible usar el algoritmo de propagación hacia atrás en la deformación hacia adelante, lo que hace que su aplicación en el aprendizaje profundo no sea obvia.

  • Seguridad de subprocesos: si se encuentra en un escenario paralelo y de subprocesos múltiples, la versión CUDA aún tiene problemas de seguridad de subprocesos, lo que afecta la velocidad

2. deformación hacia atrás

​Si hay dos fotogramas de imágenes adyacentes (o izquierda y derecha) I 1 , I 2 I_1,I_2I1,I2,对应I 2 → I 1 I_2 \rightarrow I_1I2I1El flujo óptico Flujo es F 2 → 1 F_{2\rightarrow1}F2 1, luego, bajo la operación de deformación hacia atrás, el punto de píxel I 2 ( x , y ) I_2(x,y) de la imagen del segundo cuadroI2( X ,y ) estará en el primer cuadro de la imagenI 1 ( ( x , y ) + F 2 → 1 ) I_1((x,y)+F_{2\rightarrow1})I1(( x ,y )+F2 1) Encuentre el valor dentro del rango de posición de las coordenadas (equivalente a I 1 I_1I1se sabe, yo 2 yo_2I2是未知的),即 I 2 ( x , y ) = I 1 ( x + Δ x , y + Δ y ) I_2(x,y) = I_1(x+\Delta x,y+\Delta y) I2( X ,y )=I1( X+Δx , _y+Δy),其中 F 2 → 1 ( x , y ) = ( Δ x , Δ y ) F_{2\rightarrow1}(x,y) = (\Delta x,\Delta y) F2 1( X ,y )=( Δ x ,Δy ) . _ Tenga en cuentala situación de que las coordenadas de mapeo no son números enteroscuando se buscan valores, sino porqueI 1 I_1I1se sabe, yo 2 yo_2I2es desconocido, estamos para I 2 I_2I2Cada coordenada ( x , y ) de (x,y)( X ,y ) enI 1 I_1I1 ( x + Δ x , y + Δ y ) (x+\Delta x,y+\Delta y) ( X+Δx , _y+Δ y ) , por lo quelas coordenadas que no son números enteros se puedenencontrarI 1 I_1I1El cálculo se aproxima mediante interpolación bilineal dentro del rango , por lo que no se producirá el problema del agujero de la deformación hacia adelante.

La deformación hacia atrás se puede entender como "deformación/distorsión hacia atrás", es decir, la dirección de transformación de la imagen es opuesta a la dirección del flujo óptico , que es exactamente diferente de nuestro pensamiento cognitivo inherente. Por ejemplo, use I 2 → I 1 I_2\rightarrow I_1I2I1El flujo óptico será I 1 I_1I1Transformar a I 2 I_2I2; o use I 1 → I 2 I_1\rightarrow I_2I1I2El flujo óptico, será I 2 I_2I2Transformar a I 1 I_1I1perspectiva, esta es una especie de urdimbre hacia atrás;
inserte la descripción de la imagen aquí

​La idea de la deformación hacia atrás es atravesar cada punto en el recorrido , a través del flujo óptico FD destino → Fuente F_{Destino\rightarrow Fuente}destination imagep_destinationFDestino Fuente _ _ _ _ _ _ _ _ _Calcula el punto correspondiente de un punto p_destinationtal que el valor de píxel de es igual al valor de . Si las coordenadas no son números enteros, generalmente se utiliza la interpolación bilineal para aproximar el cálculo ( es conocido y referenciado), por lo que no habrá problemas. Su código de implementación simple es el siguiente:Source imagep_sourcep_destinationp_sourcep_sourceSource ImageForward Warping

def backward_warp(self, x, flo):
        """
        warp an image/tensor (im2) back to im1, according to the optical flow(im1->im2)
        x: [B, C, H, W] (im2)
        flo: [B, 2, H, W] flow
        """
        B, C, H, W = x.size()
        # mesh grid 
        xx = torch.arange(0, W).view(1,-1).repeat(H,1)
        yy = torch.arange(0, H).view(-1,1).repeat(1,W)
        xx = xx.view(1,1,H,W).repeat(B,1,1,1)
        yy = yy.view(1,1,H,W).repeat(B,1,1,1)
        grid = torch.cat((xx,yy),1).float()

        if x.is_cuda:
            grid = grid.cuda()
        vgrid = Variable(grid) + flo

        # scale grid to [-1,1] 
        vgrid[:,0,:,:] = 2.0*vgrid[:,0,:,:].clone() / max(W-1,1)-1.0
        vgrid[:,1,:,:] = 2.0*vgrid[:,1,:,:].clone() / max(H-1,1)-1.0

        vgrid = vgrid.permute(0,2,3,1)  
        # 双线性插值 functional.grid_sample
        output = nn.functional.grid_sample(x, vgrid)
        # implementational hack in PyTorch0.2 for the warping function.
        mask = torch.autograd.Variable(torch.ones(x.size())).cuda()
        mask = nn.functional.grid_sample(mask, vgrid)

        # if W==128:
            # np.save('mask.npy', mask.cpu().data.numpy())
            # np.save('warp.npy', output.cpu().data.numpy())
        
        mask[mask<0.9999] = 0
        mask[mask>0] = 1
        
        return output*mask

​La implementación y las ideas de la deformación hacia atrás también son muy claras, principalmente cómo usar la interpolación de manera razonable para procesar datos. La deformación hacia atrás también tiene algunas ventajas y desventajas de la siguiente manera:

  • Optimización del algoritmo: la deformación hacia atrás introduce varias interpolaciones para calcular las coordenadas , lo que no hará que la imagen se divida ni cause agujeros, y la deformación hacia atrás puede realizar cálculos de propagación hacia atrás , lo que hace que la aplicación de la deformación hacia atrás sea más extensa y simple, especialmente en profundidad en el campo de estudio.
  • Problema de efecto fantasma: la deformación hacia atrás causará problemas de efecto fantasma en la imagen . Esto se debe a que esta transformación que no conserva el orden hará que la relación posicional entre los píxeles cambie antes y después del mapeo. Cuando el primer plano y el fondo tienen un movimiento relativo, habrá mucho La razón esencial de esta ambigüedad e información inválida es la oclusión formada por el movimiento relativo . Una solución general al problema de las imágenes fantasma es introducir una máscara de oclusión para refinar la imagen .

Los artículos de referencia son los siguientes:

4. Aplicación de flujo óptico

El flujo óptico se usa ampliamente en escenas como la interpolación de cuadros de video, la detección de oclusión, la estimación de movimiento y algunos cálculos de indicadores (como el análisis de indicadores de tensión cardíaca en medicina).La tecnología de flujo óptico ha logrado buenos resultados en estas aplicaciones. Y con el desarrollo continuo, además de la tecnología de flujo óptico tradicional, algunas tecnologías de flujo óptico basadas en el aprendizaje profundo también están madurando, brindando cada vez más comodidad a la vida de las personas.

Supongo que te gusta

Origin blog.csdn.net/qq_40772692/article/details/128743758
Recomendado
Clasificación