Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

trying to get 3d depth from stero images to work

So I've been tumbling down a rabbit whole and I'm at a loss. In Python (the code is below) I've been following many tutorials, and trying to convert the C++ examples to python. At first I was getting transformation matrices that would basically turn the image into a Salvador Dali picture. But buy not using the sample checkerboard and switching to one that has different row and column numbers I've been able to get something that looks to be ok. I take images of the checkerboard displayed on an iPAD(5, retina screen) as it will guarantee the image is flat and my printer sucks. But the disparity map I get might as well be white noise, it contains zero form of the image. The images are my test checkerboard images which is me holding an ipad in front of a wall. But when I try it with more complicated images I still basically get white noise. the photos are 3584x2016

What am I doing wrong? What should I try next?

import numpy as npimport cv2 as cv
from matplotlib import pyplot as plt
import glob
from PIL import Image

def convertPILToCV(pil_image_in):
    '''
        This will take a PIL loaded image, anc return it as CV image.
        Image should be converted to RGB first.
    :param pil_image_in: a PIL Iamge object seeks to the current image
    :return: a cv image representation in BGR
    '''
    open_cv_image = np.array(pil_image)
    # Convert RGB to BGR
    img_cv = open_cv_image[:, :, ::-1].copy()
    return img_cv


def findCornersInCVImage(cv_image_in):
    '''
        this will convert the image to grey, then return findchessboardcorners
    :param cv_image_in:
    :return: ret, corners from the findChessboardCorners and grey image
    '''
    gray = cv.cvtColor(cv_image_in, cv.COLOR_BGR2GRAY)
    #  scale_percent = 50  # percent of original size
    #  width = int(img.shape[1] * scale_percent / 100)
    #  height = int(img.shape[0] * scale_percent / 100)
    #  dim = (width, height)
    # resize image
    #  gray = cv.resize(gray, dim, interpolation=cv.INTER_AREA)

    # gray = cv.bitwise_not(gray)
    # grey_shape = gray.shape[::-1]
    # cv.imshow('gray', gray)
    # Find the chess board corners

    ret, corners = cv.findChessboardCorners(gray, (check_rows, check_columns), flags)

    return ret, corners, gray


check_columns = 7
check_rows = 9

# termination criteria
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objpL = np.zeros((check_rows*check_columns,3), np.float32)
objpL[:,:2] = np.mgrid[0:check_rows,0:check_columns].T.reshape(-1,2)
objpR = np.zeros((check_rows*check_columns,3), np.float32)
objpR[:,:2] = np.mgrid[0:check_rows,0:check_columns].T.reshape(-1,2)


# Arrays to store object points and image points from all the images.
objpointsL = [] # 3d point in real world space
imgpointsL = [] # 2d points in image plane.
objpointsR = [] # 3d point in real world space
imgpointsR = [] # 2d points in image plane.

images = glob.glob(r'F:\3D_calib\*.mpo')
# images = [r'F:\3D_calib\DSCF1901.JPG']
grey_shape = []

flags = cv.CALIB_CB_ADAPTIVE_THRESH
flags =  flags | cv.CALIB_CB_NORMALIZE_IMAGE

for fname in images:
    print("inspecting " + fname)
    imgMPO = Image.open(fname)
    pil_image = imgMPO.convert('RGB')
    cv_imgL = convertPILToCV(pil_image)
    imgMPO.seek(1)  # key other eye
    cv_imgR = convertPILToCV(pil_image)

    grey_shape = cv_imgL.shape[::-1]

    retL, cornersL, greyL = findCornersInCVImage(cv_imgL)
    retR, cornersR, greyR = findCornersInCVImage(cv_imgR)
    # If found, add object points, image points (after refining them)
    if retL == True:
        print("corners found L")
    if retR == True:
        print("corners found R")
    if retL == True and retR == True:
        objpointsL.append(objpL)
        objpointsR.append(objpR)

        corners2L = cv.cornerSubPix(greyL,cornersL,(11,11),(-1,-1),criteria)
        imgpointsL.append(corners2L)
        corners2R = cv.cornerSubPix(greyR, cornersR, (11, 11), (-1, -1), criteria)
        imgpointsR.append(corners2R)          

# now I get the correction matrix
image_size = grey_shape[1:]
ret, mtxL, distL, mtxR, distR, rvecs, tvecs, evecs, fvecs = cv.stereoCalibrate(objpointsL, imgpointsL, imgpointsR,
                                                                               None, None, None, None,image_size ,
                                                                               flags=cv.CALIB_FIX_ASPECT_RATIO |
                                                                               cv.CALIB_ZERO_TANGENT_DIST |
                                                                               cv.CALIB_SAME_FOCAL_LENGTH |
                                                                               cv.CALIB_RATIONAL_MODEL)


# now I need to rectify it
R1, R2, P1, P2, Q, ROI1, ROI2 = cv.stereoRectify(mtxL, distL, mtxR, distR, image_size, rvecs, tvecs)

#precalc remap maps
map1L, map2L = cv.initUndistortRectifyMap(mtxL, distL, R1, P1, image_size, cv.CV_16SC2)
map1R, map2R = cv.initUndistortRectifyMap(mtxR, distR, R2, P2, image_size, cv.CV_16SC2)

numDisparities = 16
blockSize = 50
stereo = cv.StereoSGBM_create(numDisparities=numDisparities, blockSize=blockSize)

for fname in images:
    print("inspecting " + fname)
    imgMPO = Image.open(fname)
    pil_image = imgMPO.convert('RGB')
    cv_imgL = convertPILToCV(pil_image)
    imgMPO.seek(1)  # key other eye
    cv_imgR = convertPILToCV(pil_image)
    cv_imgLremap = cv.remap(cv_imgL, map1L, map2L, cv.INTER_AREA)
    cv_imgRremap = cv.remap(cv_imgR, map1R, map2R, cv.INTER_AREA)

    disparity = stereo.compute(cv_imgLremap, cv_imgRremap)
    plt.imshow(disparity, 'gray')

trying to get 3d depth from stero images to work

So I've been tumbling down a rabbit whole and I'm at a loss. In Python (the code is below) I've been following many tutorials, and trying to convert the C++ examples to python. At first I was getting transformation matrices that would basically turn the image into a Salvador Dali picture. But buy not using the sample checkerboard and switching to one that has different row and column numbers I've been able to get something that looks to be ok. I take images of the checkerboard displayed on an iPAD(5, retina screen) as it will guarantee the image is flat and my printer sucks. But the disparity map I get might as well be white noise, it contains zero form of the image. The images are my test checkerboard images which is me holding an ipad in front of a wall. But when I try it with more complicated images I still basically get white noise. the photos are 3584x2016

What am I doing wrong? What should I try next?

updates: I tried flipping my columns and row counts in case it was a issue with thing getting flipped at one point, it just gave me a pure grey disparity map.

import numpy as npimport cv2 as cv
from matplotlib import pyplot as plt
import glob
from PIL import Image

def convertPILToCV(pil_image_in):
    '''
        This will take a PIL loaded image, anc return it as CV image.
        Image should be converted to RGB first.
    :param pil_image_in: a PIL Iamge object seeks to the current image
    :return: a cv image representation in BGR
    '''
    open_cv_image = np.array(pil_image)
    # Convert RGB to BGR
    img_cv = open_cv_image[:, :, ::-1].copy()
    return img_cv


def findCornersInCVImage(cv_image_in):
    '''
        this will convert the image to grey, then return findchessboardcorners
    :param cv_image_in:
    :return: ret, corners from the findChessboardCorners and grey image
    '''
    gray = cv.cvtColor(cv_image_in, cv.COLOR_BGR2GRAY)
    #  scale_percent = 50  # percent of original size
    #  width = int(img.shape[1] * scale_percent / 100)
    #  height = int(img.shape[0] * scale_percent / 100)
    #  dim = (width, height)
    # resize image
    #  gray = cv.resize(gray, dim, interpolation=cv.INTER_AREA)

    # gray = cv.bitwise_not(gray)
    # grey_shape = gray.shape[::-1]
    # cv.imshow('gray', gray)
    # Find the chess board corners

    ret, corners = cv.findChessboardCorners(gray, (check_rows, check_columns), flags)

    return ret, corners, gray


check_columns = 7
check_rows = 9

# termination criteria
criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objpL = np.zeros((check_rows*check_columns,3), np.float32)
objpL[:,:2] = np.mgrid[0:check_rows,0:check_columns].T.reshape(-1,2)
objpR = np.zeros((check_rows*check_columns,3), np.float32)
objpR[:,:2] = np.mgrid[0:check_rows,0:check_columns].T.reshape(-1,2)


# Arrays to store object points and image points from all the images.
objpointsL = [] # 3d point in real world space
imgpointsL = [] # 2d points in image plane.
objpointsR = [] # 3d point in real world space
imgpointsR = [] # 2d points in image plane.

images = glob.glob(r'F:\3D_calib\*.mpo')
# images = [r'F:\3D_calib\DSCF1901.JPG']
grey_shape = []

flags = cv.CALIB_CB_ADAPTIVE_THRESH
flags =  flags | cv.CALIB_CB_NORMALIZE_IMAGE

for fname in images:
    print("inspecting " + fname)
    imgMPO = Image.open(fname)
    pil_image = imgMPO.convert('RGB')
    cv_imgL = convertPILToCV(pil_image)
    imgMPO.seek(1)  # key other eye
    cv_imgR = convertPILToCV(pil_image)

    grey_shape = cv_imgL.shape[::-1]

    retL, cornersL, greyL = findCornersInCVImage(cv_imgL)
    retR, cornersR, greyR = findCornersInCVImage(cv_imgR)
    # If found, add object points, image points (after refining them)
    if retL == True:
        print("corners found L")
    if retR == True:
        print("corners found R")
    if retL == True and retR == True:
        objpointsL.append(objpL)
        objpointsR.append(objpR)

        corners2L = cv.cornerSubPix(greyL,cornersL,(11,11),(-1,-1),criteria)
        imgpointsL.append(corners2L)
        corners2R = cv.cornerSubPix(greyR, cornersR, (11, 11), (-1, -1), criteria)
        imgpointsR.append(corners2R)          

# now I get the correction matrix
image_size = grey_shape[1:]
ret, mtxL, distL, mtxR, distR, rvecs, tvecs, evecs, fvecs = cv.stereoCalibrate(objpointsL, imgpointsL, imgpointsR,
                                                                               None, None, None, None,image_size ,
                                                                               flags=cv.CALIB_FIX_ASPECT_RATIO |
                                                                               cv.CALIB_ZERO_TANGENT_DIST |
                                                                               cv.CALIB_SAME_FOCAL_LENGTH |
                                                                               cv.CALIB_RATIONAL_MODEL)


# now I need to rectify it
R1, R2, P1, P2, Q, ROI1, ROI2 = cv.stereoRectify(mtxL, distL, mtxR, distR, image_size, rvecs, tvecs)

#precalc remap maps
map1L, map2L = cv.initUndistortRectifyMap(mtxL, distL, R1, P1, image_size, cv.CV_16SC2)
map1R, map2R = cv.initUndistortRectifyMap(mtxR, distR, R2, P2, image_size, cv.CV_16SC2)

numDisparities = 16
blockSize = 50
stereo = cv.StereoSGBM_create(numDisparities=numDisparities, blockSize=blockSize)

for fname in images:
    print("inspecting " + fname)
    imgMPO = Image.open(fname)
    pil_image = imgMPO.convert('RGB')
    cv_imgL = convertPILToCV(pil_image)
    imgMPO.seek(1)  # key other eye
    cv_imgR = convertPILToCV(pil_image)
    cv_imgLremap = cv.remap(cv_imgL, map1L, map2L, cv.INTER_AREA)
    cv_imgRremap = cv.remap(cv_imgR, map1R, map2R, cv.INTER_AREA)

    disparity = stereo.compute(cv_imgLremap, cv_imgRremap)
    plt.imshow(disparity, 'gray')