OpenCV – Python の OpenCV のコードを C++ に移植するガイドライン

目次

概要

OpenCV の Python 関数を使用して作成したコードを C++ に移植する際のガイドラインを記載します。

OpenCV の Python と C++ のコードの違い

OpenCV の Python と C++ の関数は基本的に同じであるため、C++ でコードを書く場合でも Python の解説を参考にできます。ただし、両者の違いとして次の点があります。

  1. 画像を表現するデータ型
    • Python: NumPy 配列が OpenCV のデータ構造として使用されます。これにより、NumPy の強力な数値計算機能を利用できます。
    • C++: OpenCV 独自の cv::Mat を使用します。
  2. 色、点、長方形、大きさを表すデータ型
    • Python: 色、点、長方形、大きさなどの情報はすべてタプルで表します。
    • C++: 色、点、長方形、大きさの情報を持つ OpenCV 独自のクラスを使用します。
  3. 結果を受け取る方法
    • Python: 結果は返り値として受け取ります。複数の結果がある場合、タプルになります。
      contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    • C++: 結果は引数に与える参照やポインタ経由で受け取ります。そのため、結果を格納する変数をあらかじめ定義しておく必要があります。
      std::vector<std::vector<cv::Point>> contours;
      std::vector<cv::Vec4i> hierarchy;
      cv::findContours(img, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_SIMPLE);
  4. メモリの管理
    • Python: Python のガベージコレクションにより、不要になったオブジェクトは自動的に破棄されます。
    • C++: メモリ管理を手動で行う必要があります。不要になったオブジェクトは明示的に破棄するか、スコープから外れるときに自動的に破棄されます。

点、長方形、大きさを表すデータ型の対応関係

C++ では、2 次元の点、3 次元の点、長方形、回転した長方形、大きさを表すクラスが存在します。一方、Python ではこれらはすべてタプルで表します。

2 次元、3 次元の点

2 次元の点の点は、C++ では cv::Point クラス、Python では x, y のタプルで表現します。

内容 C++ Python
int32 型の 2 次元の点 cv::Point p(1, 2) p = 1, 2
int64 型の 2 次元の点 cv::Point p(1, 2) p = 1, 2
float32 型の 2 次元の点 cv::Point p(1.0f, 2.0f) p = 1.0, 2.0
float64 型の 2 次元の点 cv::Point p(1.0, 2.0) p = 1.0, 2.0
2 次元の点の成分 px, p.y p[0], [1]

2 次元、3 次元の点

3 次元の点は、C++ では cv::Point3i クラス、Python では x, y, z のタプルで表現します。

内容 C++ Python
int32 型の 3 次元の点 cv::Point3i p(1, 2, 3) p = 1, 2, 3
int64 型の 3 次元の点 cv::Point3l p(1, 2, 3) p = 1, 2, 3
float32 型の 3 次元の点 cv::Point3f p(1.0f, 2.0f, 3.0f) p = 1.0, 2.0, 3.0
float64 型の 3 次元の点 cv::Point3d p(1.0, 2.0, 3.0) p = 1.0, 2.0, 3.0
3 次元の点の成分 px, p.y. p.z p[0], [1], p[2]

長方形

長方形は、C++ では cv::Rect クラス、Python では (x, y), (width, height) のタプルで表現します。 x, y は長方形の左上の座標、(width, height) は長方形の大きさを表します。

内容 C++ Python
int32 型の長方形 cv::Rect r(10, 10, 100, 200) r = 10, 10, 100, 200
int64 型の長方形 cv::Rect r(10, 10, 100, 200) r = 10, 10, 100, 200
float32 型の長方形 cv::Rect r(10.0f, 10.0f, 100.0f, 200.0f) r = 10.0, 10.0, 100.0, 200.0
float64 型の長方形 cv::Rect r(10.0, 10.0, 100.0, 200.0) r = 10.0, 10.0, 100.0, 200.0
長方形の左上の座標 r.tl(), r.x, r.y r[0], r[1]
長方形の右下の座標 r.br() r[0] + r[2], r[1] + r[3]
長方形の大きさ r.width, r.height r[2], r[3]

回転した長方形

回転した長方形は、C++ では cv::RotatedRect クラス、Python では (cx, cy), (width, height), angle のタプルで表現します。 cx, cy は長方形の中心の座標、(width, height) は長方形の大きさ、angle は時計回りの回転角度 (度数) を表します。

内容 C++ Python
回転した長方形 cv::RotatedRect r(cv::Point2f(50,0f, 50,0f), cv::Size2f(100,0f, 200,0f), 30.0f) r = (50.0, 50.0), (100.0, 200.0), 30.0
中心 r.center r[0][0], r[0][1]
大きさ r.size r[1][0], r[1][1]
回転角度 r.angle r[2]
4 点の座標 std::vector<Point2f> pts; r.points(pts); cv2.boundingRect(cv2.boxPoints(r))

大きさ

大きさは、C++ では cv::Size クラス、Python では width, height のタプルで表現します。

内容 C++ Python
int32 型の大きさ cv::Size s(100, 200) s = 100, 200
int64 型の大きさ cv::Size2l s(100, 200) s = 100, 200
float32 型の大きさ cv::Size2f s(10.0f, 10.0f, 100.0f, 200.0f) s = 100.0, 200.0
float64 型の大きさ cv::Size2d s(10.0, 10.0, 100.0, 200.0) s = 100.0, 200.0
幅、高さ s.width, s.height s[0], s[1]

画像を表すデータ型

C++ では、画像は cv::Mat クラスを使用して 2 次元配列で表します。配列の要素は画素値を表し、チャンネル数に応じて 1 ~ 4 つの数値になります。配列に対する各種操作は OpenCV の関数を通して行います。 一方、Python では画像は NumPy 配列で表します。配列に対する操作は OpenCV の関数でもできますが、大抵の場合は NumPy の関数でできます。

内容 C++ Python
グレースケール画像 型が CV_8UC1、形状が (h, w)cv::Mat 型が uint8、形状が (h, w) の NumPy 配列
3 チャンネル画像 型が CV_8UC3、形状が (h, w)cv::Mat 型が uint8、形状が (h, w, 3) の NumPy 配列
4 チャンネル画像 型が CV_8UC4、形状が (h, w)cv::Mat 型が uint8、形状が (h, w, 4) の NumPy 配列

配列の型の種類

OpenCV では、CV_8UC1 のように cv::Mat クラスの型を表す識別子が用意されています。 OpenCV の関数を使用する際には、引数に与える行列で要求される引数の型がなにかを理解しておくことが重要です。

CV_<ビット数><U|S|F>C<チャンネル数>
  • データ型: データのビット数 (例: CV_8UC1 の場合、8 ビット)
  • U|S|F: U: 符号なし整数、S: 符号付き整数、F: 浮動小数点数
  • チャンネル数: 1~4 の値

以下に識別子の一覧表を記載します。 Python では、画像などの多次元配列は NumPy 配列として扱うため、対応する NumPy の型も併記しました。

NumPy の型 OpenCV の型 1 チャンネル 2 チャンネル 3 チャンネル 4 チャンネル
np.uint8 CV_8U CV_8UC1 (0) CV_8UC2 (1) CV_8UC3 (2) CV_8UC4 (3)
np.int8 CV_8S CV_8SC1 (4) CV_8SC2 (5) CV_8SC3 (6) CV_8SC4 (7)
np.uint16 CV_16U CV_16UC1 (8) CV_16UC2 (9) CV_16UC3 (10) CV_16UC4 (11)
np.int16 CV_16S CV_16SC1 (12) CV_16SC2 (13) CV_16SC3 (14) CV_16SC4 (15)
np.int32 CV_32S CV_32SC1 (16) CV_32SC2 (17) CV_32SC3 (18) CV_32SC4 (19)
np.float32 CV_32F CV_32FC1 (20) CV_32FC2 (21) CV_32FC3 (22) CV_32FC4 (23)
np.float64 CV_64F CV_64FC1 (24) CV_64FC2 (25) CV_64FC3 (26) CV_64FC4 (27)
np.float16 CV_16F CV_16FC1 (28) CV_16FC2 (29) CV_16FC3 (30) CV_16FC4 (31)

配列の作成

配列の作成方法を C++、Python それぞれで記載します。

値を初期化せずに配列を作成する

値を初期化せずに領域だけ確保して、配列を作成します。

内容 C++ Python
値を初期化しない配列 (グレースケール) cv::Mat m(480, 640, CV_8UC1); m = np.empty((480, 640), dtype=np.uint8)
値を初期化しない配列 3チャンネル画像 cv::Mat m(480, 640, CV_8UC3); m = np.empty((480, 640, 3), dtype=np.uint8)
値を初期化しない配列 4チャンネル画像 cv::Mat m(480, 640, CV_8UC4); m = np.empty((480, 640, 4), dtype=np.uint8)
値を初期化しない配列 (多次元配列) int shape[] = {3, 3, 3};
cv::Mat m(3, shape, CV_8UC3);
m = np.empty((3, 3, 3, 3), dtype=np.uint8)

すべての値が 0 の配列を作成する

内容 C++ Python
グレースケール cv::Mat m = cv::Mat::zeros(480, 640, CV_8UC1); m = np.zeros((480, 640), dtype=np.uint8)
3チャンネル画像 cv::Mat m = cv::Mat::zeros(480, 640, CV_8UC3); m = np.zeros((480, 640, 3), dtype=np.uint8)
4チャンネル画像 cv::Mat m = cv::Mat::zeros(480, 640, CV_8UC4); m = np.zeros((480, 640, 4), dtype=np.uint8)
多次元配列 int shape[] = {3, 3, 3};
cv::Mat m(3, shape, CV_8UC3, 0);
m = np.zeros((3, 3, 3, 3), dtype=np.uint8)

すべての値が 1 の配列を作成する

内容 C++ Python
グレースケール cv::Mat m = cv::Mat::ones(480, 640, CV_8UC1); m = np.ones((480, 640), dtype=np.uint8)
3チャンネル画像 cv::Mat m = cv::Mat::ones(480, 640, CV_8UC3); m = np.ones((480, 640, 3), dtype=np.uint8)
4チャンネル画像 cv::Mat m = cv::Mat::ones(480, 640, CV_8UC4); m = np.ones((480, 640, 4), dtype=np.uint8)
多次元配列 int shape[] = {3, 3, 3};
cv::Mat m(3, shape, CV_8UC3, 1);
m = np.ones((3, 3, 3, 3), dtype=np.uint8)

すべての値が同じ配列を作成する

内容 C++ Python
グレースケール画像 cv::Mat m(480, 640, CV_8UC1, 255); m = np.full((480, 640), 255, dtype=np.uint8)
3チャンネル画像 cv::Mat m(480, 640, CV_8UC3, 255); m = np.full((480, 640, 3), 255, dtype=np.uint8)
4チャンネル画像 cv::Mat m(480, 640, CV_8UC4, 255); m = np.full((480, 640, 3), 255, dtype=np.uint8)
多次元配列 int shape[] = {3, 3, 3};
cv::Mat m(3, shape, CV_8UC3, 255);
m = np.full((3, 3, 3, 3), 255, dtype=np.uint8)

単位行列、対角行列を作成する

単位行列、対角行列を作成する方法について、記載します。

内容 C++ Python
単位行列 cv::Mat m = cv::Mat::eye(3, 3, CV_8UC1) m = np.eye(3, dtype=np.uint8)
対角行列 cv::Mat m(3, 3, CV_8UC1);
cv::setIdentity(m, 5);
m = np.diag(np.full(3, 5))

要素の値を指定して配列を作成する

配列の値を個別にすべて指定して初期化する方法について、記載します。

  • グレースケール画像

    • C++

      uint8_t data[2][2] = {{0, 255}, {0, 255}};
      cv::Mat m(2, 2, CV_8UC1, data);
    • Python

      m = np.array([[0, 255], [0, 255]])
  • 3 チャンネル画像

    • C++

      uint8_t data[2][2][3] = {{{255, 0, 0}, {0, 255, 0}}, {{0, 0, 255}, {255, 255, 0}}};
      cv::Mat m(2, 2, CV_8UC3, data);
    • Python

      m = np.array(
          [
              [[255, 0, 0], [0, 255, 0]],
              [[0, 0, 255], [255, 255, 0]],
          ]
      )
  • 4 チャンネル画像

    • C++

      uint8_t data[2][2][4] = {{{255, 0, 0, 255}, {0, 255, 0, 255}},
                               {{0, 0, 255, 255}, {255, 255, 0, 255}}};
      cv::Mat m(2, 2, CV_8UC4, data);
    • Python

      m = np.array(
          [
              [[255, 0, 0, 255], [0, 255, 0, 255]],
              [[0, 0, 255, 255], [255, 255, 0, 255]],
          ]
      )
  • 多次元配列

    • C++

      int shape[] = {2, 2, 2};
      uint8_t data[2][2][2][3] = {
          {{{1, 2, 3}, {4, 5, 6}}, {{7, 8, 9}, {10, 11, 12}}},
          {{{13, 14, 15}, {16, 17, 18}}, {{19, 20, 21}, {22, 23, 24}}}};
      cv::Mat m(3, shape, CV_8UC3, data);
    • Python

      m = np.array(
          [
              [[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]],
              [[[13, 14, 15], [16, 17, 18]], [[19, 20, 21], [22, 23, 24]]],
          ]
      )

乱数で初期化した配列を作成する

配列の値を乱数で初期化する方法について、記載します。

内容 C++ Python
離散一様分布で初期化 cv::Mat m(3, 3, CV_8UC1);
cv::randu(m, 0, 256); // [0, 255] の範囲の離散一様分布
m = np.random.randint(0, 256, (3, 3))
連続一様分布で初期化 cv::Mat m(3, 3, CV_64FC1);
cv::randu(m, 0, 256); // [0, 256) の範囲の一様分布
m = np.random.uniform(0, 255, (3, 3))
正規分布で初期化 cv::Mat m(3, 3, CV_64FC1);
cv::randn(m, 3.0, 5.0); // 平均3、標準偏差5の正規分布
m = np.random.normal(3, 5, size=(3, 3))
標準正規分布で初期化 cv::Mat m(3, 3, CV_64FC1);
cv::randn(m, 0.0, 1.0); // 標準正規分布
m = np.random.randn(3, 3)
乱数シードの設定 cv::setRNGSeed(0); np.random.seed(0)

部分配列を作成する

C++ と Python で配列の一部をスライスして部分配列を作成する方法を記載します。 C++ では、cv::Mat クラスのメソッドを使用して部分配列を作成します。 一方、Python では、NumPy 配列のスライスを使用して部分配列を作成します。

内容 C++ Python
行、列の範囲を指定してスライス cv::Mat m(cv::Range(100, 200), cv::Range(100, 200)); m[100:200, 100:200]
行の範囲を指定してスライス cv::Mat n = m.rowRange(100, 200); m[100:200]
列の範囲を指定してスライス cv::Mat n = m.colRange(100, 200); m[:, 100:200]
行を指定してスライス cv::Mat n = m.row(100); m[100]
列を指定してスライス cv::Mat n = m.col(100); m[:, 100]
対角成分をスライス cv::Mat n = m.diag(0); m.diagonal()
多次元配列のスライス cv::Range ranges[] = {cv::Range(1, 3), cv::Range(1, 3), cv::Range(1, 3)};
cv::Mat n(m, ranges);
m[1:3, 1:3, 1:3]

配列のコピー

内容 C++ Python
浅いコピー cv::Mat m = other; m = other
深いコピー cv::Mat m = other.clone(); m = other.copy()

画像の情報

内容 C++ Python
画像の幅 m.cols m.shape[1]
画像の高さ m.rows m.shape[0]
画像のチャンネル数 m.channels() m.shape[2] (カラー画像の場合)
画像の型 m.type() m.dtype
画像の画素数 m.total() m.size

行列に対する演算

対数、指数、平方根、べき乗

内容 C++ Python (NumPy)
対数関数 cv::log(src, dst) dst = np.log(src)
指数関数 cv::exp(src, dst) dst = np.exp(src)
平方根 cv::sqrt(src, dst) dst = np.sqrt(src)
べき乗 cv::pow(src, power, dst) dst = src ** 2

四則演算

内容 C++ Python (NumPy)
加算 cv::add(src1, src2, dst) dst = src1 + src2
減算 cv::subtract(src1, src2, dst) dst = src1 - src2
乗算 cv::multiply(src1, src2, dst, scale) dst = scale * src1 * src2
除算 cv::divide(src1, src2, dst, scale) dst = scale * src1 / src2
|src1 - src2| cv::absdiff(src1, src2, dst) dst = np.abs(src1 - src2)
s * src1 + src2 cv::scaleAdd(src1, alpha, src2, dst) dst = scale * src1 + src2
a * src1 + b * src2 + c cv::addWeighted(src1, alpha, src2, beta, gamma, dst) dst = src1 * alpha + src2 * beta + gamma
src1 * w1 + src2 * w2 cv::blendLinear(src1, src2, weights1, weights2, dst) dst = src1 * weights1 + src2 * weights2
src * a * b cv::convertScaleAbs(src, dst, alpha, beta) dst = np.abs(src * alpha + beta)
dst += src cv::accumulate(src, dst) dst += src
dst += src1 * src2 cv::accumulateProduct(src1, src2, dst) dst += src1 * src2
dst += src ** 2 cv::accumulateSquare(src, dst) dst += src ** 2
dst += (1 - alpha) * dst + alpha * src cv::accumulateWeighted(src, dst, alpha) dst += (1 - alpha) * dst + alpha * src

比較

内容 C++ Python
以下 cv::compare(src1, src2, dst, cv2.CMP_LE) np.where(src1 <= src2, 255, 0)
未満 cv::compare(src1, src2, dst, cv2.CMP_LT) np.where(src1 < src2, 255, 0)
以上 cv::compare(src1, src2, dst, cv2.CMP_GE) np.where(src1 >= src2, 255, 0)
より大きい cv::compare(src1, src2, dst, cv2.CMP_GT) np.where(src1 > src2, 255, 0)
等しい cv::compare(src1, src2, dst, cv2.CMP_EQ) np.where(src1 == src2, 255, 0)
等しくない cv::compare(src1, src2, dst, cv2.CMP_NE) np.where(src1 != src2, 255, 0)

NOT、AND、OR、XOR

内容 C++ Python
NOT 演算 cv::bitwise_not(src, dst) dst = ~src
AND 演算 cv::bitwise_and(src1, src2, dst) dst = src1 & src2
OR 演算 cv::bitwise_or(src1, src2, dst) dst = src1 | src2
XOR 演算 cv::bitwise_xor(src1, src2, dst) dst = src1 ^ src2

値の取得、設定

内容 C++ Python
i 成分の値の取得 ($1 \times n$ 行列) m.at(i) m[0, i]
i 成分の値の取得 ($n \times 1$ 行列) m.at(i) m[i, 0]
(i, j) 成分の値の取得 ($m \times n$ 行列) m.at(i, j) m[i, j]
i 成分の値の設定 ($1 \times n$ 行列) m.at<cv::Vec3b>(i) = cv::Vec3b(255, 255, 255) m[0, i] = [255, 255, 255]
i 成分の値の設定 ($n \times 1$ 行列) m.at<cv::Vec3b>(i) = cv::Vec3b(255, 255, 255) m[i, 0] = [255, 255, 255]
(i, j) 成分の値の設定 ($m \times n$ 行列) m.at<cv::Vec3b>(i, j) = cv::Vec3b(255, 255, 255) m[i, j] = [255, 255, 255]
形状の変更 dst = m.reshape(channels, row) dst = m.reshape(row, col, channels)
形状のリサイズ m.resize(row) dst = m.resize(row, col, channnels)
型の変更 m.convertTo(dst, CV_32F) dst = m.astype(np.float32)
すべて同じ値を設定する m.setTo(cv::Scalar(255, 255, 255)) m[:, :] = [255, 255, 255]
行列の要素を順番に取得する m.begin(), m.end() np.nditer(m)

最小値、最大値を探す

内容 C++ Python
最小値、最大値とその場所 cv::minMaxLoc(src, minVal, maxVal, minLoc, maxLoc) minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(src)
行または列ごとの最小値の場所 cv::reduceArgMax(src, dst, axis) dst = src.argmax(axis)
行または列ごとの最大値の場所 cv::reduceArgMin(src, dst, axis) dst = src.argmin(axis)
行または列ごとの最小値 cv::reduce(src, dst, axis, cv2.REDUCE_MIN) dst = src.min(axis)
行または列ごとの最大値 cv::reduce(src, dst, axis, cv2.REDUCE_MAX) dst = src.max(axis)

チャンネルを操作する

内容 C++ Python
チャンネルに値を設定する cv::insertChannel(src, dst, c) dst[..., c] = src
ャンネルから値を取得する cv::extractChannel(src, dst, c) dst = src[..., c]
チャンネルを分割する cv::split(src, channels) channels = np.dsplit(src, src.shape[2])
チャンネルを結合する cv::merge(srcs, count, dst) dst = np.dstack([src1, src2, src3])

非ゼロ要素

内容 C++ Python
非ゼロ要素をカウント cv::countNonZero(src) np.count_nonzero(src)
非ゼロ要素が存在するかどうか cv::hasNonZero(src) (src > 0).any()
非ゼロ要素を探す idx = cv::findNonZero(src, idx) non_zero_indices = np.nonzero(array)<br>non_zero_positions = np.vstack(non_zero_indices).T

和、平均、標準偏差

内容 C++ Python
チャンネルごとの和 retval = cv::sum(src) retval = src.sum(axis=(0, 1))
チャンネルごとの平均 retval = cv::mean(src) retval = src.mean(axis=(0, 1))
チャンネルごとの平均と標準偏差 cv::meanStdDev(src, mean, stddev) mean, std = src.mean(axis=(0, 1)), src.std(axis=(0, 1))
行または列ごとの平均 cv::reduce(src, dst, axis, cv2.REDUCE_AVG) src.mean(axis)
行または列ごとの和 cv::reduce(src, dst, axis, cv2.REDUCE_SUM) src.sum(axis)
行または列ごとの二乗和 cv::reduce(src, dst, axis, cv2.REDUCE_SUM2) (src ** 2).sum(axis)

2 次元ベクトルの演算

内容 C++ Python
2 次元ベクトルの大きさ cv::magnitude(x, y, magnitude) magnitude = np.linalg.norm([x, y], axis=0)
2 次元ベクトルのなす角 cv::phase(x, y, angle) angle = np.arctan2(y, x)
2 次元ベクトルのなす角 retcval = cv::fastAtan2(y, x) angle_deg = np.degrees(np.arctan2(y, x)) % 360
極座標をデカルト座標に変換 cv::polarToCart(magnitude, angle, x, y) x = magnitude * np.cos(angle)<br>y = magnitude * np.sin(angle)

その他

内容 C++ Python
値の設定 cv::copyTo(src, dst) np.copyto(dst, src)
すべての値が指定の範囲かどうか checkRange(a, true, pos, minVal, maxVal) ((minVal <= a) & (a <= maxVal)).all()
指定した配列を縦横に繰り返した配列を作成 cv::Mat dst = cv::repeat(src, ny, nx) np.tile(src, (ny, nx))
NaN を指定した値に置き換える cv::patchNaNs(a, val) a[np.isnan(a)] = val
ブロードキャスト cv::broadcast(src, shape, dst) dst = np.broadcast_to(src, shape)
シャッフルする cv::randShuffle(dst) dst.shuffle()
乱数シードを設定する cv::setRNGSeed(seed) np.random.seed()

同次座標

内容 C++ Python
同次座標からデカルト座標に変換 cv::convertPointsFromHomogeneous(src, dst) dst = src[:, :2] / src[:, 2, np.newaxis]
デカルト座標から同次座標に変換 cv::convertPointsToHomogeneous(src, dst) dst = np.hstack([src, np.ones((src.shape[0], 1), dtype=src.dtype)])

行列操作

内容 C++ Python
行列積 dst = m.mul(n) dst = m @ n
逆行列、擬似逆行列 cv::invert(src, dst) または m.inv() dst = np.linalg.inv(src)
対称行列の固有値、固有ベクトル cv::eigen(src, eigenvalues, eigenvectors) eigenvalues, eigenvectors = np.linalg.eig(src)
非対称行列の固有値、固有ベクトル cv::eigenNonSymmetric(src, eigenvalues, eigenvectors) eigenvalues, eigenvectors = np.linalg.eig(src)
行列式 cv::determinant(mtx) np.linalg.det(mtx)
行列の下三角成分を反転させて、対称行列を作成する cv::completeSymm(m, true) np.tril(m) + np.tril(m, -1).T
行列の上三角成分を反転させて、対称行列を作成する cv::completeSymm(m, false) np.triu(m) + np.triu(m, 1).T
行列を転置する cv::transpose(src, dst) または m.t() dst = src.T
行列のトレース cv::trace(mtx) mtx.trace()
点 src を行列 M で変換する cv::transform(src, dst, M) dst = src @ M.T
scale * (src – delta)^T @ (src – delta) cv::mulTransposed(src, dst, true, dtype=cv2.CV_64F) dst = scale * (src - delta).T @ (src - delta)
scale * (src – delta) @ (src – delta)^T cv::mulTransposed(src, dst, false, dtype=cv2.CV_64F) dst = scale * (src - delta) @ (src - delta).T
alpha src1^T src2 + beta src3^T cv::gemm(src1, src2, alpha, src3, beta, dst) dst = alpha src1.T src2 + beta src3.T
同じ大きさの行列を横方向に結合する cv::hconcat(src, nsrc, dst) dst = np.concatenate(src, axis=1)
同じ大きさの行列を縦方向に結合する cv::vconcat(src, nsrc, dst) dst = np.concatenate(src, axis=0)

コメント

コメントする

目次