10
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

自分用:OpenCV3.4.3 カメラキャリブレーション

Posted at

概要

OpenCV 3.4.3 で C++用に書いたカメラキャリブレーションコード

説明

calib_imgフォルダ内の10枚の画像を読み込み,カメラ内部パラメータ行列と,歪み係数をXMLファイルで出力する

コード

#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <opencv2/opencv.hpp>
#include <opencv/highgui.h>
#include <opencv2/imgcodecs.hpp>
#include <vector>

using namespace std;

#define IMAGE_NUM  (10)         /* 画像数 */
#define PAT_ROW    (7)          /* パターンの行数 */
#define PAT_COL    (10)         /* パターンの列数 */
#define PAT_SIZE   (PAT_ROW*PAT_COL)
#define ALL_POINTS (IMAGE_NUM*PAT_SIZE)
#define CHESS_SIZE (23.0)       /* パターン1マスの1辺サイズ[mm] */

int main(int argc, char *argv[])
{
	int i, j, k;
	int corner_count, found;
	int p_count[IMAGE_NUM];
	// cv::Mat src_img[IMAGE_NUM];
	vector<cv::Mat> srcImages;
	cv::Size pattern_size = cv::Size2i(PAT_COL, PAT_ROW);
	vector<cv::Point2f> corners;
	vector<vector<cv::Point2f>> img_points;

	// (1)キャリブレーション画像の読み込み
	for (i = 0; i < IMAGE_NUM; i++)
	{
		ostringstream ostr;
		ostr << "calib_img\\" << setfill('0') << setw(2) << i << ".png";
		cv::Mat src = cv::imread(ostr.str());
		if (src.empty())
		{
			cerr << "cannot load image file : " << ostr.str() << endl;
		}
		else
		{
			srcImages.push_back(src);
		}
	}

	// (2)3次元空間座標の設定

	vector<cv::Point3f> object;
	for (j = 0; j < PAT_ROW; j++)
	{
		for (k = 0; k < PAT_COL; k++)
		{
			cv::Point3f p(
				j * CHESS_SIZE,
				k * CHESS_SIZE,
				0.0);
			object.push_back(p);
		}
	}

	vector<vector<cv::Point3f>> obj_points;
	for (i = 0; i < IMAGE_NUM; i++)
	{
		obj_points.push_back(object);
	}

	// 3次元の点を ALL_POINTS * 3 の行列(32Bit浮動小数点数:1チャンネル)に変換する 


	// (3)チェスボード(キャリブレーションパターン)のコーナー検出
	int found_num = 0;
	cv::namedWindow("Calibration", cv::WINDOW_AUTOSIZE);
	for (i = 0; i < IMAGE_NUM; i++)
	{
		auto found = cv::findChessboardCorners(srcImages[i], pattern_size, corners);
		if (found)
		{
			cout << setfill('0') << setw(2) << i << "... ok" << endl;
			found_num++;
		}
		else
		{
			cerr << setfill('0') << setw(2) << i << "... fail" << endl;
		}

		// (4)コーナー位置をサブピクセル精度に修正,描画
		cv::Mat src_gray = cv::Mat(srcImages[i].size(), CV_8UC1);
		cv::cvtColor(srcImages[i], src_gray, cv::COLOR_BGR2GRAY);
		cv::find4QuadCornerSubpix(src_gray, corners, cv::Size(3,3));
		cv::drawChessboardCorners(srcImages[i], pattern_size, corners, found);
		img_points.push_back(corners);

		cv::imshow("Calibration", srcImages[i]);
		cv::waitKey(0);
	}
	cv::destroyWindow("Calibration");

	if (found_num != IMAGE_NUM)
	{
		cerr << "Calibration Images are insufficient." << endl;
		return -1;
	}

	// (5)内部パラメータ,歪み係数の推定
	cv::Mat cam_mat; // カメラ内部パラメータ行列
	cv::Mat dist_coefs; // 歪み係数
	vector<cv::Mat> rvecs, tvecs; // 各ビューの回転ベクトルと並進ベクトル
	cv::calibrateCamera(
		obj_points,
		img_points,
		srcImages[0].size(),
		cam_mat,
		dist_coefs,
		rvecs,
		tvecs
	);

	// (6)XMLファイルへの書き出し
	cv::FileStorage fs("camera.xml", cv::FileStorage::WRITE);
	if(!fs.isOpened())
	{
		cerr << "File can not be opened." << endl;
		return -1;
	}

	fs << "intrinsic" << cam_mat;
	fs << "distortion" << dist_coefs;
	fs.release();

	return 0;
}
10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?