最近OpenCVを使うことが増えたので,メモ代わりに情報を残しておきます.
今回は,OpenCVを使ってチェスボードの交点を探します.
以下の,チェスボードの交点を探します.
チェスボードのデータをPDFで置いておきますので,よろしければA4用紙に印刷して使用ください.
chess_board_A4_7x10.pdf
チェスボードの交点位置を求めるプログラムは以下のようになります.
#include "opencv2/core/core.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
bool find_chess_corners( cv::Mat image,
cv::vector *corners,
cv::Size pattern_size, cv::Size chess_size )
{
bool is_find = cv::findChessboardCorners(image, pattern_size, *corners);
if( is_find != true )
{
return false;
}
cv::Mat gray( image.rows, image.cols, CV_8UC1 );
cv::cvtColor(image, gray, CV_BGR2GRAY);
cv::cornerSubPix(gray, *corners, chess_size,
cv::Size(-1, -1),
cv::TermCriteria(CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.01));
return true;
}
int main(int argc, const char ** argv)
{
cv::Mat src_img = cv::imread("chess.jpg");
cv::namedWindow("src", CV_WINDOW_AUTOSIZE);
cv::vector src_corners;
find_chess_corners( src_img, &src_corners, cv::Size(10, 7), cv::Size(20, 20) );
cv::drawChessboardCorners( src_img, cv::Size(10, 7), ( cv::Mat )src_corners, true);
cv::imshow("src", src_img);
if( cv::waitKey(0) == 'q' )
{
cv::imwrite( "dst.jpg", src_img);
return 0;
}
}
Visual Studioで実行する場合は,以下の記述をプログラムの最初に追記することで,必要なライブラリがリンクされます.
*2410は2.4.10版のことですので,ご自分の環境に合わせて書き換えてください.
#ifdef DEBUG
#pragma comment(lib, "opencv_calib3d2410.lib")
#pragma comment(lib, "opencv_core2410.lib")
#pragma comment(lib, "opencv_highgui2410.lib")
#pragma comment(lib, "opencv_imgproc2410.lib")
#else
#pragma comment(lib, "opencv_calib3d2410d.lib")
#pragma comment(lib, "opencv_core2410d.lib")
#pragma comment(lib, "opencv_highgui2410d.lib")
#pragma comment(lib, "opencv_imgproc2410d.lib")
#endif
このプログラムを実行すると,以下のようにチェスボードの交点を見つけることができます.
それではプログラムの説明を行います.
このプログラムは,読み込んだjpeg画像からチェスボードの交点を探します.
交点を探す処理はfind_chess_corners関数で行っています.
この関数の引数は以下のようになります.
bool fined_chess_corners( cv::mat カラー画像,
cv::vector<cv::Point2f> 交点を格納する配列,
cv::Size チェスボードの交点数(行, 列),
cv::Size 探索ウィンドウの半分の大きさ)
この関数内では,以下のような2つの関数を使って交点位置を求めています.
・cv::findChessboardCorners関数
チェスボードの交点は,cv::findChessboardCorners関数で見つけることができます.
チェスボードがあれば真を返し,なければ偽を返します.
そして,検出したチェスボードのコーナーが配列に格納されます.
cv::findChessboardCorners関数の引数は以下のようになります.
bool findChessboardCorners( cv::mat カラーまたは8bitグレースケール画像,
cv::Size チェスボードの交点数(行, 列),
cv::vector<cv::Point2f> 交点を格納する配列,
int 処理のフラグ)
・cv::cornerSubPix関数
cv::cornerSubPix関数を使うことで検出した交点位置の精度をあげることができます.
cv::cornerSubPix関数の引数は以下のようになります.
対象外の探索領域の半分の大きさにcv::Size(-1, -1)を指定すると,対象外領域はないということを指定できます.
この関数はコーナー位置の高精度化処理を繰り返し行うので,その最大反復回数と要求精度のどちらか,または両方を設定します.
void cornerSubPix( cv::mat 8bitグレースケール画像,
cv::vector<cv::Point2f> 交点を格納する配列,
cv::Size 探索ウィンドウの半分の大きさ,
cv::Size 対象外の探索領域の半分の大きさ,
cv::TermCritera 繰り返し処理の終了条件)
私もはまったのですが,cv::cornerSubPix関数に与える画像は1chのグレースケール画像である必要があるので注意してください.
これで,チェスボードのコーナー点を求めることができました.
今回は以上となります.
参考文献:
OpenCV 2 プログラミングブック制作チーム『OpenCV 2 プログラミングブック OpenCV 2.2/2.3対応』マイナビ (2011/12/27)
「特徴検出」『opencv 2.2 documetation』<http://opencv.jp/opencv-2svn/cpp/feature_detection.html> (2015/02/03アクセス)
「カメラキャリブレーションと3次元再構成」『opencv 2.2 documetation』<http://opencv.jp/opencv-2svn/cpp/camera_calibration_and_3d_reconstruction.html> (2015/02/03アクセス)
コメント
コメントを投稿