web-dev-qa-db-fra.com

OpenCV - Comment obtenir la distance réelle d'une image 2D en utilisant un échiquier comme référence

enter image description here

Après avoir vérifié plusieurs morceaux de codes, j'ai pris plusieurs photos, trouvé les coins de l'échiquier et les ai utilisés pour obtenir la matrice de la caméra, les coefficients de distorsion, la rotation et les vecteurs de translation. Maintenant, quelqu'un peut-il me dire quelle fonction python opencv ai-je besoin pour calculer la distance dans le monde réel à partir de l'image 2D? Points de projet? Par exemple, en utilisant un échiquier comme référence (voir l'image ), si la taille des carreaux est de 5 cm, la distance pour 4 carreaux doit être de 20 cm. J'ai vu certaines fonctions comme projectPoints, findHomography, resolvePnP mais je ne sais pas lequel dois-je résoudre mon problème et obtenir la matrice de transformation entre les le monde de la caméra et le monde de l'échiquier.1 caméra unique, même position de la caméra dans tous les cas mais pas exactement sur l'échiquier, et l'échiquier est placé sur un objet plan (tableau)

# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
    objp = np.zeros((nx * ny, 3), np.float32)
    objp[:, :2] = np.mgrid[0:nx, 0:ny].T.reshape(-1, 2)

    # Arrays to store object points and image points from all the images.
    objpoints = []  # 3d points in real world space
    imgpoints = []  # 2d points in image plane.

    # Make a list of calibration images
    images = glob.glob(path.join(calib_images_dir, 'calibration*.jpg'))
    print(images)
    # Step through the list and search for chessboard corners
    for filename in images:

        img = cv2.imread(filename)

        imgScale = 0.5
        newX,newY = img.shape[1]*imgScale, img.shape[0]*imgScale
        res = cv2.resize(img,(int(newX),int(newY)))

        gray = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY)

        # Find the chessboard corners
        pattern_found, corners = cv2.findChessboardCorners(gray, (nx,ny), None)

        # If found, add object points, image points (after refining them)
        if pattern_found is True:
            objpoints.append(objp)

            # Increase accuracy using subpixel corner refinement
            cv2.cornerSubPix(gray,corners,(5,5),(-1,-1),(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.1 ))
            imgpoints.append(corners)

            if verbose:
                # Draw and display the corners
                draw = cv2.drawChessboardCorners(res, (nx, ny), corners, pattern_found)
                cv2.imshow('img',draw)
                cv2.waitKey(500)

    if verbose:
        cv2.destroyAllWindows()

    #Now we have our object points and image points, we are ready to go for calibration
    # Get the camera matrix, distortion coefficients, rotation and translation vectors
    ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)
    print(mtx)
    print(dist)
    print('rvecs:', type(rvecs),' ',len(rvecs),' ',rvecs)
    print('tvecs:', type(tvecs),' ',len(tvecs),' ',tvecs)

    mean_error = 0
    for i in range(len(objpoints)):
        imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
        error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
        mean_error += error

    print("total error: ", mean_error/len(objpoints))


    imagePoints,jacobian = cv2.projectPoints(objpoints[0], rvecs[0], tvecs[0], mtx, dist)
    print('Image points: ',imagePoints)
11
Pablo Gonzalez

Votre problème concerne principalement l'étalonnage de la caméra, en particulier dans la mauvaise mise en œuvre de la résolution de la caméra distorsion en opencv. Vous devez approximer la fonction de distorsion de votre appareil photo en prenant quelques sondes de distance dans différentes coordonnées de votre échiquier. La bonne idée sera de prendre d'abord une petite distance au centre de la lentille, puis un carré loin en prenant une seconde distance un peu plus longue et de répéter l'opération jusqu'à la frontière. Il vous donnera des coefficients de votre fonction de distorsion. Matlab a sa propre bibliothèque pour résoudre votre problème avec une grande précision, malheureusement c'est assez cher.
Selon:

Maintenant, quelqu'un peut-il me dire quelle fonction python opencv ai-je besoin pour calculer la distance dans le monde réel à partir de l'image 2D?

Je pense que cet article prend une bonne explication de python ensemble de fonctions opencv pour générer une mesure réelle. Avec la résolution des coefficients comme je l'ai dit ci-dessus, vous pouvez faire une bonne précision. pense pas si c'est une implémentation open source de fonction comme

cv2.GetRealDistance(...)
0
ElConrado