RustでOpenCV使ってみた

RustからOpenCVのロジックを呼び出す理由は特に無いのですが、Rustが好きなのでやってみました。

参考

事前準備

MacOSでは brew install opencvOpenCVをインストールしたのち、以下のように Cargo.toml を作成することで使用可能でした。

[package]
name = "ocvtest"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
opencv = "0.84.5"

メイン

今回はArUcoマーカーを検出し、検出結果を画像に描画し表示するというプログラムを書いてみました。感想としては、例えば画像のリサイズ結果を入力画像用の変数に上書きするようなところでRust特有の参照の制限で少し冗長になってしまう気がしています(C++では入力と出力が同じでも大丈夫だったはず)。また、デフォルト引数の機能がないのも少し使いづらいかなと思います。

use opencv::prelude::*;
use opencv::core::{Scalar, Size};
use opencv::types::{VectorOfMat};
use opencv::imgcodecs::{imread, IMREAD_COLOR};
use opencv::objdetect::{
    ArucoDetector,
    ArucoDetectorTraitConst,
    DetectorParameters,
    RefineParameters,
    get_predefined_dictionary,
    PredefinedDictionaryType,
    draw_detected_markers,
};
use opencv::imgproc::{resize, INTER_LINEAR};
use opencv::highgui::{named_window, imshow, wait_key, WINDOW_NORMAL};

fn main() {

    // read image
    let img = imread("test.jpeg", IMREAD_COLOR).unwrap();

    // resize image
    let mut dst: Mat = Default::default();
    resize(&img, &mut dst, Size::new(0, 0), 0.2, 0.2, INTER_LINEAR).unwrap();
    let mut img = dst;

    // ArUco predefined dictionary
    let dictionary = get_predefined_dictionary(PredefinedDictionaryType::DICT_6X6_50).unwrap();

    // ArUco detector parameters
    let detector_params = DetectorParameters::default().unwrap();
    
    // ArUco refine parameters
    let refine_params = RefineParameters::new(10., 3., true).unwrap();

    // construct ArUco detector
    let aruco_detector = ArucoDetector::new(&dictionary, &detector_params, refine_params).unwrap();

    // declare some variables for the ArUco detection result
    let mut corners: VectorOfMat = Default::default();
    let mut ids: Mat = Default::default();
    let mut rejected_img_points: VectorOfMat = Default::default();

    // ArUco detection 
    aruco_detector.detect_markers(&img, &mut corners, &mut ids, &mut rejected_img_points).unwrap();

    // draw detection result
    let color = Scalar::new(0., 255., 0., 0.);
    draw_detected_markers(&mut img, &corners, &ids, color).unwrap();

    // show detection result on a window
    named_window("main", WINDOW_NORMAL).unwrap();
    imshow("main", &img).unwrap();
    wait_key(0).unwrap();

}

実行結果