¿Cómo se puede crear un mapa de profundidad con cámaras estéreo?

Estoy estudiando en un proyecto por mucho tiempo. Mi objetivo es obtener mapa de profundidad de las imágenes de las cámaras estéreo y filtrar humanos sólo para contar el interior humano.

Estoy tratando de calibrar mi cámara, continuamente durante 1-2 meses. Sin embargo, cuando trazo líneas epipolar en par rectificado, el resultado no es lo suficientemente bueno (he adjuntado mi resultado de par rectificado). Estoy trabajando ahora, con mis resultados de calibración promedio y tratando de conseguir mapa de profundidad de mapa de disparidad. He grabado una secuencia de imagen, archivo .avi, y cuando intento conseguir mapa de profundidad de estos videos, Cuando lo intento estoy enfrentando una situación inestable. Un lugar blanco en el marco anterior puede ser muy negro en el siguiente. Así que no puedo contar a la gente filtrando la disparidad. Uso SGBM para obtener profundidades de imágenes rectificadas. Todavía soy considerado aficionado en este proyecto. Estoy abierto a cualquier consejo. (Cómo hacer una mejor calibración? ¿Mejor mapa de disparidad? Mejor mapa de profundidad?)

Este es mapa de profundidad y par rectificado: depth map

Parejas rectificadas y líneas epipolar pair and lines

He calibrado mi cámara con 600 pares casi y mejorado. Mi error promedio general fue de 13 pix con 35 pares de imágenes.

minDisparity=-1,
        numDisparities=2*16,  # max_disp has to be dividable by 16 f. E. HH 192, 256
        blockSize=window_size,
        P1=8 * 3 * window_size,
        # wsize default 3; 5; 7 for SGBM reduced size image; 15 for SGBM full size image (1300px and above); 5 Works nicely
        P2=32 * 3 * window_size,
        disp12MaxDiff=12,
        uniquenessRatio=1,
        speckleWindowSize=50,
        speckleRange=32,
        preFilterCap=63,
        mode=cv2.STEREO_SGBM_MODE_SGBM_3WAY

Estos son mis parámetros de coincidencia de bloques.

Pregunta hecha hace 3 años, 4 meses, 28 días - Por codemaestro


5 Respuestas:

  • Para mejorar los resultados de su mapa de disparidad, usted puede implementar post-filtering, aquí es un tutorial (https://docs.opencv.org/master/d3/d14/tutorial_ximgproc_disparity_filtering.html). También usé un filtro de espectro extra y la opción de llenar las disparidades que faltan. La aplicación del pitón es la siguiente:

    stereoProcessor = cv2.StereoSGBM_create(
                    minDisparity=0,
                    numDisparities = max_disparity, # max_disp has to be dividable by 16 f. E. HH 192, 256
                    blockSize=window_size,
                    P1 = p1,       # 8*number_of_image_channels*SADWindowSize*SADWindowSize
                    P2 = p2,    # 32*number_of_image_channels*SADWindowSize*SADWindowSize
                    disp12MaxDiff=disp12Maxdiff,
                    uniquenessRatio= uniquenessRatio,
                    speckleWindowSize=speckle_window,
                    speckleRange=speckle_range,
                    preFilterCap=prefiltercap,
                   # mode=cv2.STEREO_SGBM_MODE_HH# numDisparities = max_disparity, # max_disp has to be dividable by 16 f. E. HH 192, 256
                    
            )
            
            #stereoProcessor = cv2.StereoBM_create(numDisparities=16, blockSize=15)
            
            # set up left to right + right to left left->right + right->left matching +
            # weighted least squares filtering (not used by default)
    
            left_matcher = stereoProcessor
            right_matcher = cv2.ximgproc.createRightMatcher(left_matcher)
    
            #Image information 
            height, width, channels = I.shape
    
            frameL= I[:,0:int(width/2),:]
            frameR = I[:,int(width/2):width,:]
    
            # remember to convert to grayscale (as the disparity matching works on grayscale)
    
            grayL = cv2.cvtColor(frameL,cv2.COLOR_BGR2GRAY)
            grayR = cv2.cvtColor(frameR,cv2.COLOR_BGR2GRAY)
    
            # perform preprocessing - raise to the power, as this subjectively appears
            # to improve subsequent disparity calculation
    
            grayL = np.power(grayL, 0.75).astype('uint8')
            grayR = np.power(grayR, 0.75).astype('uint8')
    
            # compute disparity image from undistorted and rectified versions
            # (which for reasons best known to the OpenCV developers is returned scaled by 16)
    
            if (wls_filter):
    
                wls_filter = cv2.ximgproc.createDisparityWLSFilter(matcher_left=left_matcher)
                wls_filter.setLambda(wls_lambda)
                wls_filter.setSigmaColor(wls_sigma)
                displ = left_matcher.compute(cv2.UMat(grayL),cv2.UMat(grayR))  # .astype(np.float32)/16
                dispr = right_matcher.compute(cv2.UMat(grayR),cv2.UMat(grayL))  # .astype(np.float32)/16
                displ = np.int16(cv2.UMat.get(displ))
                dispr = np.int16(cv2.UMat.get(dispr))
                disparity = wls_filter.filter(displ, grayL, None, dispr)
            else:
    
                disparity_UMat = stereoProcessor.compute(cv2.UMat(grayL),cv2.UMat(grayR))
                disparity = cv2.UMat.get(disparity_UMat)
            
            speckleSize = math.floor((width * height) * 0.0005)
            maxSpeckleDiff = (8 * 16) # 128
    
            cv2.filterSpeckles(disparity, 0, speckleSize, maxSpeckleDiff)
            
            # scale the disparity to 8-bit for viewing
            # divide by 16 and convert to 8-bit image (then range of values should
            # be 0 -> max_disparity) but in fact is (-1 -> max_disparity - 1)
            # so we fix this also using a initial threshold between 0 and max_disparity
            # as disparity=-1 means no disparity available
    
            _, disparity = cv2.threshold(disparity,0, max_disparity * 16, cv2.THRESH_TOZERO)
            disparity_scaled = (disparity / 16.).astype(np.uint8)
    
            # fill disparity if requested
    
            if (fill_missing_disparity):
    
                _, mask = cv2.threshold(disparity_scaled,0, 1, cv2.THRESH_BINARY_INV)
                mask[:,0:120] = 0
                disparity_scaled = cv2.inpaint(disparity_scaled, mask, 2, cv2.INPAINT_NS)
    
            # display disparity - which ** for display purposes only ** we re-scale to 0 ->255
            disparity_to_display = (disparity_scaled * (256. / self.value_NumDisp)).astype(np.uint8)
            
    

    Respondida el Dec 18, 2020 a las 13:13 - por codecatalyst

    Votos positivos: 0 | Votos negativos: 0

  • Algunas cosas a simple vista:

    • Sus parámetros P1, P2 en StereoSGBM deben ser ajustados, calculados así:

      P1 = 8*3*blockSize**2
      P2 = 32*3*blockSize**2
      
    • StereoSGBM admite imágenes de color, prueba a saltar la conversión de grayscale. Si utiliza grayscale, debe eliminar *3 mulitiplier en los parámetros P1, P2. Esto es para el número de canales de imagen, donde grayscale tiene 1.

    • Estás usando cv2.STEREO_SGBM_MODE_3WAY, que es más rápido pero menos preciso. Para mejores resultados pero más lento, intenta usar cv2.STEREO_SGBM_MODE_SGBM (por defecto, 5 vecinos) o cv2.STEREO_SGBM_MODE_HH (8 vecinos)

    • Sus imágenes tienen diferentes exposiciones, si es posible, traten de arreglar el AWB/gain de sus cámaras para que sean capturadas consistentemente.

    Respondida el Dec 18, 2020 a las 13:23 - por javajedi

    Votos positivos: 0 | Votos negativos: 0

  • ¿Por qué quieres usar un mapa de distancia para detectar humanos? En mi opinión, es un problema de detección de objetos.

    De todos modos, En el estado actual del arte para obtener mapas de distancia, recomendaría modelos basados en inteligencia artificial.

    Modelos como NeRF han logrado resultados increíbles.

    • Google proporciona ARCore que proporciona un mapa de profundidad, pero basado en una sola cámara.
    • Nvidia tiene este proyecto
    • Esto, basado en Nerf de un video logra la reconstrucción 3D

    En unas semanas trabajaré en esto, quiero alcanzar un modelo que funciona en TensorFlowLite que, desde cámaras estéreo alcanza un mapa de profundidad

    Respondida el Dec 18, 2020 a las 13:28 - por bughunterx

    Votos positivos: 0 | Votos negativos: 0

  • Para mejorar la calidad de tu mapa de profundidad y obtener mejores resultados al filtrar humanos, aquí hay algunas sugerencias que podrían ayudarte:

    • Calibración de la cámara: Asegúrate de haber realizado una calibración precisa de tus cámaras estéreo. Puedes utilizar herramientas como OpenCV para este propósito y asegurarte de que la calibración sea lo más precisa posible.
    • Ajuste de parámetros: Los parámetros que has mostrado para el algoritmo SGBM son importantes para obtener un buen mapa de disparidad. Ajusta estos parámetros de acuerdo con las características de tus imágenes para obtener mejores resultados. Puedes probar diferentes valores y ver cómo afectan a la calidad de los mapas de profundidad.
    • Mejora de la estabilidad: Si estás experimentando inestabilidad en tus mapas de disparidad, puedes intentar suavizarlos mediante técnicas como el filtrado bilateral o el uso de métodos de post-procesamiento para eliminar las discontinuidades o ruidos.
    1. Filtrado de humanos: Para filtrar solo a los humanos en

    Respondida el Dec 19, 2020 a las 13:14 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Mejorar la calibración de la cámara:

    Utiliza una rejilla de calibración más grande y con un patrón más preciso. Toma más imágenes de calibración en diversas condiciones de iluminación y distancias. Utiliza un software de calibración específico, como OpenCV o MATLAB, para automatizar el proceso. Verifica los resultados de la calibración calculando el error de reproyección.

    Mejorar el mapa de disparidad:

    Ajusta los parámetros del algoritmo SGBM, como el tamaño de la ventana de coincidencia y el rango de disparidad. Utiliza algoritmos de postprocesamiento para eliminar el ruido y rellenar los agujeros. Considera la posibilidad de utilizar métodos de aprendizaje profundo para estimar la disparidad.

    Mejorar el mapa de profundidad:

    Una vez que tengas un mapa de disparidad preciso, conviértelo a un mapa de profundidad utilizando la fórmula profundidad = distancia focal <strong> base / disparidad. Aplica filtros de suavizado para eliminar el ruido. Utiliza técnicas de segmentación para aislar los objetos de interés (humanos en este caso).

    Consejos adicionales:

    Asegúrate de que las cámaras estéreo estén bien alineadas y calibradas. Utiliza iluminación constante para evitar variaciones en la intensidad de la imagen. Graba secuencias de vídeo de alta calidad con una resolución y velocidad de fotogramas suficientes. Experimenta con diferentes valores de parámetros y evalúa los resultados. Considera la posibilidad de utilizar bibliotecas open source de visión artificial como OpenCV o PCL para ayudarte en el desarrollo.

    Resultados del par rectificado:

    Las líneas epipolar no parecen coincidir perfectamente, lo que indica que la calibración podría mejorarse. Intenta utilizar más pares de calibración y un patrón de calibración más preciso.

    Consejos para el mapa de profundidad:

    Utiliza un tamaño de ventana de coincidencia más pequeño (por ejemplo, 5) para obtener una estimación de disparidad más precisa. Aumenta el rango de disparidad para capturar más detalles de profundidad. * Ajusta el parámetro uniquenessRatio (por ejemplo, 5) para mejorar la precisión de la coincidencia.

    Respondida el Dec 19, 2020 a las 13:27 - por Gemini

    Votos positivos: 0 | Votos negativos: 0