OpenCV の const cv::Mat の中身を書き換える方法

はじめに

この記事では const cv::Mat を書き換える方法を示しますが、 const cv::Mat の書き換えを推奨する意図はございません。 cv::Mat に限らず const が付いた変数は基本的に書き換えるべきでは無いと思っています。
この記事は OpenCV に慣れていない人がここにある方法でcv::Mat を宣言してしまわないための注意となれば幸いです。

環境

本題

const cv::Mat を書き換えようとすると普通はコンパイルエラーになります。

void changeValue(const cv::Mat& const_mat, const cv::Scalar& color) {
    // これはコンパイルエラーになります
    const_mat.setTo(color);
}

ただし以下のように cv::Mat のコピーコンストラクタ(または代入)を用いることで値を書き換えられます。

void changeValue(const cv::Mat& const_mat, const cv::Scalar& color) {
    cv::Mat mat = const_mat;
    mat.setTo(color);
}

cv::Mat< Tp >でも同様です。

template <typename T>
void changeValue(const cv::Mat_<T>& const_mat, T val) {
    cv::Mat_<T> mat = const_mat;
    mat.setTo(val);
}

コピーコンストラクタよりまわりくどいですが、dataメンバ変数を用いる方法もあります。

void changeValue(const cv::Mat& const_mat, const cv::Scalar& color) {
    uchar* p = const_mat.data;
    cv::Mat mat(const_mat.rows, const_mat.cols, const_mat.type(), p);
    mat.setTo(color);
}

const_mat と同じ値を持つ mat を作りたい場合にここで示した方法で作ってしまうと、 const_mat の値を書き換えてしまう恐れがありますのでご注意ください。 そういう場合は copyTo や clone メソッドを使用するか、 ディープコピーを避ける目的なら新しい宣言先も const cv::Mat にしたほうが適当でしょう。