开源OpenCVSharp标定工具

本工具已经合并至开源项目opencvsharphelper:

[开源]OpenCVSharp工具

感谢点赞,Star;

这几天学习OpenCV的标定,顺手写个小工具,目前实现了鱼眼和张正友部分,

开源OpenCVSharp标定工具_第1张图片

参考了python版本:https://www.jb51.net/article/200668.htm,也做了一些改动

import cv2
import numpy as np
import os
import glob
from matplotlib import pyplot as plt
 
CHECKERBOARD = (9,6)
subpix_criteria = (cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 30, 0.1)
calibration_flags = cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC
objp = np.zeros((1, CHECKERBOARD[0]*CHECKERBOARD[1], 3), np.float32)
objp[0,:,:2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2)
_img_shape = None
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.
images = glob.glob('./images/*.jpg')
if len(images)<1:
    print("no image!")
for fname in images:
    img = cv2.imread(fname)
    plt.figure(figsize = (22, 22)),plt.subplot(121),plt.imshow(img),plt.title('img',color='white'),plt.xticks([]),plt.yticks([])
    if _img_shape == None:
        _img_shape = img.shape[:2]
    else:
        assert _img_shape == img.shape[:2], "All images must share the same size."
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    # Find the chess board corners
    ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, cv2.CALIB_CB_ADAPTIVE_THRESH+cv2.CALIB_CB_FAST_CHECK+cv2.CALIB_CB_NORMALIZE_IMAGE)
    # If found, add object points, image points (after refining them)
    if ret == True:
        objpoints.append(objp)
        cv2.cornerSubPix(gray,corners,(3,3),(-1,-1),subpix_criteria)
        imgdraw = img.copy()
        cv2.drawChessboardCorners(imgdraw,CHECKERBOARD,corners,True)
        plt.subplot(122),plt.imshow(imgdraw),plt.title('imgdraw',color='white'),plt.xticks([]),plt.yticks([]),plt.show()
        imgpoints.append(corners)
N_OK = len(objpoints)
K = np.zeros((3, 3))
D = np.zeros((4, 1))
rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]
tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]
rms, _, _, _, _ = \
cv2.fisheye.calibrate(
    objpoints,
    imgpoints,
    gray.shape[::-1],
    K,
    D,
    rvecs,
    tvecs,
    calibration_flags,
    (cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 20, 1e-6)
  )
print("Found " + str(N_OK) + " valid images for calibration")
DIM=_img_shape[::-1]
print("K=np.array(" + str(K.tolist()) + ")")
print("D=np.array(" + str(D.tolist()) + ")")

for fname in images:
    testimg = cv2.imread(fname)
    plt.figure(figsize = (22, 22)),plt.subplot(121),plt.imshow(testimg),plt.title('distorted_img',color='white'),plt.xticks([]),plt.yticks([]) 
    
    h,w = img.shape[:2]
    
    map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), K, DIM, cv2.CV_16SC2)
    undistorted_img = cv2.remap(testimg, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
    plt.subplot(122),plt.imshow(undistorted_img),plt.title('undistorted_img',color='white'),plt.xticks([]),plt.yticks([]),plt.show()

开源OpenCVSharp标定工具_第2张图片

也参考了C++的版本:

//运行环境 VS2012+opencv3.0
#include 
#include 
using namespace std;
using namespace cv;

int main()
{
    ofstream fout("caliberation_result.txt");  /**    保存定标结果的文件     **/

    /************************************************************************  
           读取每一幅图像,从中提取出角点,然后对角点进行亚像素精确化  
    *************************************************************************/   
    cout<<"开始提取角点………………"< corners;                  /****    缓存每幅图像上检测到的角点       ****/
    vector>  corners_Seq;    /****  保存检测到的所有角点       ****/   
    vector  image_Seq;
	int successImageNum = 0;				/****	成功提取角点的棋盘图数量	****/

    int count = 0;
    for( int i = 0;  i != image_count ; i++)
    {
        cout<<"Frame #"<>imageFileName;
        imageFileName += ".jpg";
        cv::Mat image = imread("img"+imageFileName); 
        /* 提取角点 */   
        Mat imageGray;
        cvtColor(image, imageGray , CV_RGB2GRAY);
        bool patternfound = findChessboardCorners(image, board_size, corners,CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE+ 
            CALIB_CB_FAST_CHECK );
        if (!patternfound)   
        {   
            cout<<"can not find chessboard corners!\n";  
            continue;
            exit(1);   
        } 
        else
        {   
            /* 亚像素精确化 */
            cornerSubPix(imageGray, corners, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
            /* 绘制检测到的角点并保存 */
            Mat imageTemp = image.clone();
            for (int j = 0; j < corners.size(); j++)
            {
                circle( imageTemp, corners[j], 10, Scalar(0,0,255), 2, 8, 0);
            }
            string imageFileName;
            std::stringstream StrStm;
            StrStm<>imageFileName;
            imageFileName += "_corner.jpg";
            imwrite(imageFileName,imageTemp);
            cout<<"Frame corner#"<>  object_Points;        /****  保存定标板上角点的三维坐标   ****/

    Mat image_points = Mat(1, count, CV_32FC2, Scalar::all(0));  /*****   保存提取的所有角点   *****/
    vector  point_counts;                                                         
    /* 初始化定标板上角点的三维坐标 */
	for (int t = 0; t tempPointSet;
        for (int i = 0; i rotation_vectors;                           /* 每幅图像的旋转向量 */
    std::vector translation_vectors;                        /* 每幅图像的平移向量 */
    int flags = 0;
    flags |= cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC;
    flags |= cv::fisheye::CALIB_CHECK_COND;
    flags |= cv::fisheye::CALIB_FIX_SKEW;
    fisheye::calibrate(object_Points, corners_Seq, image_size, intrinsic_matrix, distortion_coeffs, rotation_vectors, translation_vectors, flags, cv::TermCriteria(3, 20, 1e-6));
    cout<<"定标完成!\n";   

    /************************************************************************  
           对定标结果进行评价  
    *************************************************************************/   
    cout<<"开始评价定标结果………………"<  image_points2;             /****   保存重新计算得到的投影点    ****/   

    cout<<"每幅图像的定标误差:"< tempPointSet = object_Points[i];
        /****    通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到新的投影点     ****/
		fisheye::projectPoints(tempPointSet, image_points2, rotation_vectors[i], translation_vectors[i], intrinsic_matrix, distortion_coeffs);
        /* 计算新的投影点和旧的投影点之间的误差*/  
        vector tempImagePoint = corners_Seq[i];
        Mat tempImagePointMat = Mat(1,tempImagePoint.size(),CV_32FC2);
        Mat image_points2Mat = Mat(1,image_points2.size(), CV_32FC2);
        for (size_t i = 0 ; i != tempImagePoint.size(); i++)
        {
            image_points2Mat.at(0,i) = Vec2f(image_points2[i].x, image_points2[i].y);
            tempImagePointMat.at(0,i) = Vec2f(tempImagePoint[i].x, tempImagePoint[i].y);
        }
        err = norm(image_points2Mat, tempImagePointMat, NORM_L2);
        total_err += err/=  point_counts[i];   
        cout<<"第"<>imageFileName;
        imageFileName += "_d.jpg";
        imwrite(imageFileName,t);
    }
    cout<<"保存结束"<

和C#的winform张正友标定版本:https://gitee.com/UDCS/opencvsharp_calibration

然后自己写了一个wpf的版本:https://gitee.com/tfarcraw/opencvsharp-calibration

张正友标定:

开源OpenCVSharp标定工具_第3张图片

你可能感兴趣的:(OpenCVSharp,C#图像处理,标定)