概要
OpenCV の Python 関数を使用して作成したコードを C++ に移植する際のガイドラインを記載します。
OpenCV の Python と C++ のコードの違い
OpenCV の Python と C++ の関数は基本的に同じであるため、C++ でコードを書く場合でも Python の解説を参考にできます。ただし、両者の違いとして次の点があります。
- 画像を表現するデータ型
- Python: NumPy 配列が OpenCV のデータ構造として使用されます。これにより、NumPy の強力な数値計算機能を利用できます。
- C++: OpenCV 独自の
cv::Mat
を使用します。
- 色、点、長方形、大きさを表すデータ型
- Python: 色、点、長方形、大きさなどの情報はすべてタプルで表します。
- C++: 色、点、長方形、大きさの情報を持つ OpenCV 独自のクラスを使用します。
- 結果を受け取る方法
- 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);
- Python: 結果は返り値として受け取ります。複数の結果がある場合、タプルになります。
- メモリの管理
- 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}; |
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}; |
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}; |
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}; |
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); |
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); |
m = np.random.randint(0, 256, (3, 3)) |
連続一様分布で初期化 | cv::Mat m(3, 3, CV_64FC1); |
m = np.random.uniform(0, 255, (3, 3)) |
正規分布で初期化 | cv::Mat m(3, 3, CV_64FC1); |
m = np.random.normal(3, 5, size=(3, 3)) |
標準正規分布で初期化 | cv::Mat m(3, 3, CV_64FC1); |
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)}; |
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) |
コメント