opencv 角點檢測+相機標定+去畸變+重投影誤差計算


https://blog.csdn.net/u010128736/article/details/52875137

https://blog.csdn.net/h532600610/article/details/51800488

 

python 角點檢測+相機標定+去畸變+重投影誤差計算:

#coding:utf-8
import cv2
import numpy as np
import glob

# 找棋盤格角點
# 閾值
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
#棋盤格模板規格
w = 9
h = 6
# 世界坐標系中的棋盤格點,例如(0,0,0), (1,0,0), (2,0,0) ....,(8,5,0),去掉Z坐標,記為二維矩陣
objp = np.zeros((w*h,3), np.float32)
objp[:,:2] = np.mgrid[0:w,0:h].T.reshape(-1,2)
# 儲存棋盤格角點的世界坐標和圖像坐標對
objpoints = [] # 在世界坐標系中的三維點
imgpoints = [] # 在圖像平面的二維點

images = glob.glob('calib/*.png')
for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    # 找到棋盤格角點
    ret, corners = cv2.findChessboardCorners(gray, (w,h),None)
    # 如果找到足夠點對,將其存儲起來
    if ret == True:
        cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
        objpoints.append(objp)
        imgpoints.append(corners)
        # 將角點在圖像上顯示
 cv2.drawChessboardCorners(img, (w,h), corners, ret)
        cv2.imshow('findCorners',img)
        cv2.waitKey(1)
cv2.destroyAllWindows()

# 標定
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

# 去畸變
img2 = cv2.imread('calib/00169.png')
h,  w = img2.shape[:2]
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),0,(w,h)) # 自由比例參數
dst = cv2.undistort(img2, mtx, dist, None, newcameramtx)
# 根據前面ROI區域裁剪圖片
#x,y,w,h = roi
#dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.png',dst)

# 反投影誤差
total_error = 0
for i in xrange(len(objpoints)):
    imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
    error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
    total_error += error
print "total error: ", total_error/len(objpoints)

 標定 cv2.calibrateCamera函數文檔:https://docs.opencv.org/2.4.1/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html

 

c++ 角點檢測+角點繪制:

#include <iostream>
#include <cv.h>
#include <cxcore.h>
#include <highgui.h>
using namespace std;
 
int main( )
{
    cout<<"Draw Chess OpenCV!"<<endl;  
    char* filename="..//image5.jpg";
    char* filename2="..//5.jpg";
    IplImage* imgRGB = cvLoadImage(filename); 
    IplImage* imgGrey = cvLoadImage(filename,CV_LOAD_IMAGE_GRAYSCALE); 
 
    if (imgGrey==NULL){//image validation
        cout<< "No valid image input."<<endl; 
        char c=getchar();
        return 1;
    } 
 
    //-------find chessboard corners--------------
    int corner_row=7;//interior number of row corners.(this can be countered by fingers.)
    int corner_col=7;//interior number of column corners.
    int corner_n=corner_row*corner_col;
    CvSize pattern_size=cvSize(corner_row,corner_col);
   // CvPoint2D32f* corners=new CvPoint2D32f[corner_n];
    CvPoint2D32f corners[49];
    int corner_count;
 
    int found=cvFindChessboardCorners(//returning non-zero means sucess.
        imgGrey,// 8-bit single channel greyscale image.
        pattern_size,//how many INTERIOR corners in each row and column of the chessboard.
        corners,//an array where the corner locations can be recorded.
        &corner_count,// optional, if non-NULL, its a point to an integer where the nuber of corners found can be recorded.
       // CV_CALIB_CB_ADAPTIVE_THRESH|CV_CALIB_CB_FILTER_QUADS// check page 382-383.
        0
        );
     cout<<"corner_count = "<<corner_count;
    //-------Draw the corner pattern-------
 cvDrawChessboardCorners(
        imgRGB,
        pattern_size,
        corners,
        corner_count,
        found
        );
    cvSaveImage(filename2,imgRGB);
    //to summary a bit of findings.
    cout<<"found="<<found<<endl;
    cout<<"x="<<corners[1].x;
    cout<<",y="<<corners[1].y<<endl;
    
    cvNamedWindow("Find and Draw ChessBoard", 0 );
    cvShowImage( "Find and Draw ChessBoard", imgRGB );
 
    cvWaitKey(0); 
 
    cvReleaseImage(&imgGrey);
    cvReleaseImage(&imgRGB);
    cvDestroyWindow("Find and Draw ChessBoard"); 
 
    return 0;
}

 

注意事項:

  • pattern_size參數傳遞內點數,8*8的棋盤只有7*7內點。
  • 圖像選取應注意減少干擾,例如光照與背景等。
  • Corners中的角點坐標順序排列規律不一定是以行從左上到右下。使用坐標計算映射關系時應提高警惕,對坐標進行重新排列。

關鍵函數參數說明:

int cvFindChessboardCorners( const void* image, CvSize pattern_size, CvPoint2D32f* corners, int* corner_count=NULL, int flags=CV_CALIB_CB_ADAPTIVE_THRESH );

Image:

輸入的棋盤圖,必須是8位的灰度或者彩色圖像。

pattern_size:

棋盤圖中每行和每列角點的個數。

Corners:

檢測到的角點

corner_count:

輸出,角點的個數。如果不是NULL,函數將檢測到的角點的個數存儲於此變量。

Flags:

各種操作標志,可以是0或者下面值的組合:

CV_CALIB_CB_ADAPTIVE_THRESH -使用自適應閾值(通過平均圖像亮度計算得到)將圖像轉換為黑白圖,而不是一個固定的閾值。

CV_CALIB_CB_NORMALIZE_IMAGE -在利用固定閾值或者自適應的閾值進行二值化之前,先使用cvNormalizeHist來均衡化圖像亮度。

CV_CALIB_CB_FILTER_QUADS -使用其他的准則(如輪廓面積,周長,方形形狀)來去除在輪廓檢測階段檢測到的錯誤方塊。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM