前回は「OpenCV」+「Python」でArUcoマーカを生成・認識する手順について解説しましたので、今回は「OpenCV」+「C++」での手順を解説します。
1. 使用した環境
・Ubuntu 18.04 LTS
・OpenCV 4.5.5
・cmake 3.10.2
2. 必要なパッケージのインストール
以下のコマンドを実行し、必要なパッケージのインストールを行います。
sudo apt install build-essential cmake libgtk2.0-dev pkg-config
3. OpenCVと拡張モジュール群のダウンロード
3.1. OpenCVのダウンロード
以下のサイトにアクセスするとバージョンごとのOpenCVライブラリが表示されるので、最新版のOpenCVの「Sources」をクリックしダウンロードします。
OpenCV:https://opencv.org/releases/
3.2. 拡張モジュール群のダウンロード
OpenCVの拡張モジュール群をダウンロードします。以下のサイトの「Switch branches/tags」からOpenCVと同様のバージョンを選択します。「Code」→「Download ZIP」からダウンロードします。
opencv_contrib:https://github.com/opencv/opencv_contrib
3.3. ダウンロードファイルの解凍
ダウンロードした「opencv-x.x.x.zip」、「opencv_contrib-x.x.x.zip」を解凍します。
※ x.x.xは、ダウンロードするバージョンにより異なります。
cd ~/ダウンロード
unzip opencv-x.x.x.zip -d ~/
unzip opencv_contrib-x.x.x.zip -d ~/opencv-x.x.x/
4. OpenCVと拡張モジュール群のインストール
以下のコマンドを実行しOpenCVと拡張モジュールのインストールを行います。
cd ~/opencv-x.x.x
mkdir build
cd build
cmake -DOPENCV_EXTRA_MODULES_PATH=~/opencv-x.x.x/opencv_contrib-x.x.x/modules ..
make
sudo make install
※ x.x.xには、ダウンロードしたOpenCVのバージョンを指定してください。
5. ArUcoマーカの生成
5.1. ArUcoマーカ生成プログラムの作成
以下のArUcoマーカ自動生成プログラムをコピーし、「arMarkerGenerator.cpp」を保存します。
本プログラムで生成できるArUcoマーカの種類は、20行目の「cv::aruco::DICT_4X4_50」で指定しています。
これは、「DICT_ビット数_ID数」となっており、ビット数は縦横のビット数を指し、ID数は生成できるマーカの数を指しています。
今回は、「aruco.DICT_4X4_50」なので、縦横が4ビットで、生成できるマーカの数が0~49の計50個となります。
cd ~/
mkdir -p ArMarker/src
cd ~/ArMarker/src
gedit arMarkerGenerator.cpp
// OpenCV
#include <opencv4/opencv2/opencv.hpp>
// ArUco
#include <opencv4/opencv2/aruco.hpp>
class arMarkerGenerator{
public:
int pixel = 150;
int offset = 10;
static const int CNT = 9;
void generateArMarker()
{
cv::Mat img = cv::Mat::zeros(pixel + offset, pixel + offset, CV_8UC1);
cv::Mat hconcat_img, vconcat_img;
img = cv::Scalar(255, 255, 255);
int x_offset, y_offset;
x_offset = y_offset = (int)(offset / 2);
cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_4X4_50);
for(int i = 0; i < CNT; i++){
cv::Mat ar_img;
cv::aruco::drawMarker(dictionary, i, pixel, ar_img, 1);
// ファイル名の設定
std::string file_nm = "ar" + std::to_string(i) + ".png";
// アフィン行列
cv::Mat mat = (cv::Mat_<double>(2,3)<<1.0, 0.0, x_offset, 0.0, 1.0, y_offset);
// アフィン変換
cv::warpAffine(ar_img, img, mat, img.size(), cv::INTER_LINEAR, cv::BORDER_TRANSPARENT);
// グレースケールからRGBへ変換
cv::Mat rgb_img;
cv::cvtColor(img, rgb_img, cv::COLOR_GRAY2RGB);
if(i % 3 == 0){
hconcat_img = rgb_img;
} else if(i % 3 <=2){
cv::hconcat(hconcat_img, rgb_img, hconcat_img);
if(i % 3 == 2 && i / 3 == 0){
vconcat_img = hconcat_img;
} else if(i % 3 == 2 && i / 3 > 0){
cv::vconcat(vconcat_img, hconcat_img, vconcat_img);
}
}
// Output RGB image.
cv::imwrite(file_nm, rgb_img);
}
cv::imwrite("ar" + std::to_string(CNT) + ".png", vconcat_img);
}
};
int main(int argc, char* argv[]){
arMarkerGenerator ar;
ar.generateArMarker();
return 0;
}
5.2. CMakeLists.txtの作成
以下のCMakeListsの内容をコピーし、「CMakeLists.txt」を保存します。
gedit CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
# OpenCVのバージョンを指定
set(OCV_VERSION "4.5")
project(src)
# OpenCVパッケージの設定を検索し読み込む
find_package(OpenCV ${OCV_VERSION} REQUIRED)
# ArUco marker
add_executable(arMarkerGenerator arMarkerGenerator.cpp)
if(OpenCV_FOUND)
target_include_directories(arMarkerGenerator PRIVATE ${OpenCV_INCLUDE_DIRS})
target_link_libraries(arMarkerGenerator ${OpenCV_LIBS})
endif()
5.3. ArUcoマーカ生成プログラムのビルド・実行
以下のコマンドを実行し、ビルド・実行を行います。プログラムを実行すると「build」ディレクトリにArUcoマーカが生成されます。
mkdir build
cd build
cmake ..
make
./arMarkerGenerator
図 1. 自動生成したArUcoマーカ
6. ArUcoマーカの検出
6.1. ArUcoマーカ検出プログラムの作成
以下のArUcoマーカ検出プログラムをコピーし、「arMarkerRecognizer.cpp」を保存します。
cd ~/ArMarker/src
gedit arMarkerRecognizer.cpp
// OpenCV
#include <opencv4/opencv2/opencv.hpp>
// ARマーカ関連
#include <opencv4/opencv2/aruco.hpp>
class arMarkerRecognizer{
public:
static const int cnt = 9;
void recognizeArMarker()
{
cv::Ptr<cv::aruco::DetectorParameters> parameters = cv::aruco::DetectorParameters::create();
cv::Ptr<cv::aruco::Dictionary> dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_4X4_100);
for(int i = 0; i < cnt + 1; i++){
// 入力ファイル名
std::string input_file_nm = "ar" + std::to_string(i) + ".png";
// 出力ファイル名
std::string output_file_nm = "ar_detection" + std::to_string(i) + ".png";
// 入力ファイルの読み込み
cv::Mat input_img = cv::imread(input_file_nm, cv::IMREAD_COLOR);
std::vector<std::vector<cv::Point2f>> corners, rejectedCandidates;
std::vector<int> ids;
// ArUcoマーカの検出
cv::aruco::detectMarkers(input_img, dictionary, corners, ids, parameters, rejectedCandidates);
if(ids.size() > 0){
cv::Mat output_img = input_img.clone();
// ArUcoマーカの検出結果の描画
cv:: aruco::drawDetectedMarkers(output_img, corners, ids);
// ArUcoマーカの検出結果をファイル出力
cv::imwrite(output_file_nm, output_img);
}
}
}
};
int main(int argc, char* argv[]){
arMarkerRecognizer ar;
ar.recognizeArMarker();
return 0;
}
6.2. CMakeLists.txtの追加
項番5.2で作成した「CMakeLists.txt」に以下の10、15~16行目を追加します。
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
# OpenCVのバージョンを指定
set(OCV_VERSION "4.5")
project(src)
# OpenCVパッケージの設定を検索し読み込む
find_package(OpenCV ${OCV_VERSION} REQUIRED)
# ArUco marker
add_executable(arMarkerGenerator arMarkerGenerator.cpp)
add_executable(arMarkerRecognizer arMarkerRecognizer.cpp)
if(OpenCV_FOUND)
target_include_directories(arMarkerGenerator PRIVATE ${OpenCV_INCLUDE_DIRS})
target_link_libraries(arMarkerGenerator ${OpenCV_LIBS})
target_include_directories(arMarkerRecognizer PRIVATE ${OpenCV_INCLUDE_DIRS})
target_link_libraries(arMarkerRecognizer ${OpenCV_LIBS})
endif()
6.3. ArUcoマーカ検出プログラムのビルド・実行
以下のコマンドを実行し、ビルド・実行を行います。プログラムを実行すると「build」ディレクトリにArUcoマーカ検出結果の画像が生成されます。
cd build
cmake ..
make
./arMarkerRecognizer
図 2. 検出したArUcoマーカ
いかがだったでしょうか。C++でARマーカの生成・検出を行いたい方などのお役に立てれば幸いです。