OpenCV を用いた行列操作(OpenCV 4.5 対応)(C++ を使用)
【サイト内の OpenCV 関連ページ】
- OpenCV について [PDF] , [パワーポイント]
- OpenCV のインストール,画像表示を行う C++ プログラムの実行手順: 別ページ »で説明
- OpenCVとPythonを活用した画像・ビデオ処理プログラム: 別ページ »にまとめ
- OpenCV 4 の C/C++ プログラム: 別ページ »にまとめている.
【OpenCV の公式情報】
- OpenCV の公式ページ: https://opencv.org
- GitHub の OpenCV のページ: https://github.com/opencv/opencv/releases
用語
このページでは,行列、行ベクトル,列ベクトルという言葉を次の意味で扱う.- 行列: n行m列の行列 (n>=1, m>=1)
- 行ベクトル: 1行m列の行列 (m>=1)
- 列ベクトル: n行1列の行列 (n>=1)
要素の型
【関連する外部ページ】 https://docs.opencv.org/modules/core/doc/intro.html#fixed-pixel-types-limited-use-of-templates
◆ チャンネル数=1の場合の表記 ※ 末尾に「C1」を付けても同じ意味
- CV_8U: 8-bit unsigned integer (uchar)
- CV_8S: 8-bit signed integer (schar)
- CV_16U: 16-bit unsigned integer (ushort)
- CV_16S; 16-bit signed integer (short)
- CV_32S: 32-bit signed integer (int)
- CV_32F: 32-bit floating-point number (float)
- CV_64F: 64-bit floating-point number (double)
行ベクトル
https://docs.opencv.org/modules/core/doc/basic_structures.html#mat
行ベクトルのコンストラクタ
- 行ベクトルのコンストラクタ
unsigned char v[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; cv::Mat vec01 = cv::Mat(1, sizeof(v)/sizeof(unsigned char), CV_8U, v);
- 全要素が 0 の行ベクトル: cv::Mat::zeros
「cv::Mat::zeros(1, m, <要素型>)」のように書く.m は列数.
cv::Mat vec02 = cv::Mat::zeros(1, 5, CV_8U);
- 全要素が 1 の行ベクトル: cv::Mat::ones
「cv::Mat::ones(1, m, <要素型>)」のように書く.m は列数.
cv::Mat vec03 = cv::Mat::ones(1, 5, CV_8U);
- 全要素が 同じ値 の行ベクトル: cv::Mat
「cv::Mat(1, 5, <要素型>, cv::Scalar(x));」のように書く.m は列数.
cv::Mat vec04 = cv::Mat(1, 5, CV_8U, cv::Scalar(8));
- [A, B) の一様乱数を要素に持つ行ベクトル: cv::randu
「cv::randu(vec, Scalar(A), cv::Scalar(B));」
cv::Mat vec05 = cv::Mat::zeros(1, 5, CV_8U); cv::randu(vec05, cv::Scalar(0), cv::Scalar(256));
- 平均 M 分散 S の正規分布の乱数を要素に持つ行ベクトル: cv::randn
「cv::randn(vec, Scalar(M), cv::Scalar(S));」
cv::Mat vec06 = cv::Mat::zeros(1, 5, CV_8U); cv::randn(vec06, cv::Scalar(128), cv::Scalar(5));
- 浅いコピー: =
unsigned char v07[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; cv::Mat vec07 = cv::Mat(1, sizeof(v)/sizeof(unsigned char), CV_8U, v07); cv::Mat vec08 = vec07;
- 深いコピー: clone
unsigned char v09[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; cv::Mat vec09 = cv::Mat(1, sizeof(v)/sizeof(unsigned char), CV_8U, v09); cv::Mat vec10 = vec09.clone();
- サイズの変更: reshape
下の例では、行列をベクトルに変換している. 「reshape(1, m)」のように書く.m は列数.
unsigned char v11[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; cv::Mat mat11 = cv::Mat(3, 4, CV_8U, v11); cv::Mat vec11 = mat11.reshape(1, 12);
- 要素の型変換: covertTo
unsigned char v12[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; cv::Mat vec12 = cv::Mat(1, sizeof(v)/sizeof(unsigned char), CV_8U, v12); cv::Mat vec13; vec12.convertTo( vec13, CV_32F );
◆ ソースコードの例
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main( int argc, char** argv )
{
unsigned char v[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
cv::Mat vec01 = cv::Mat(1, sizeof(v)/sizeof(unsigned char), CV_8U, v);
cv::Mat vec02 = cv::Mat::zeros(1, 5, CV_8U);
cv::Mat vec03 = cv::Mat::ones(1, 5, CV_8U);
cv::Mat vec04 = cv::Mat(1, 5, CV_8U, cv::Scalar(8));
cv::Mat vec05 = cv::Mat::zeros(1, 5, CV_8U);
cv::randu(vec05, cv::Scalar(0), cv::Scalar(256));
cv::Mat vec06 = cv::Mat::zeros(1, 5, CV_8U);
cv::randn(vec06, cv::Scalar(128), cv::Scalar(5));
unsigned char v07[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
cv::Mat vec07 = cv::Mat(1, sizeof(v)/sizeof(unsigned char), CV_8U, v07);
cv::Mat vec08 = vec07;
vec08.cv::Mat::col(2) = 23;
unsigned char v09[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
cv::Mat vec09 = cv::Mat(1, sizeof(v)/sizeof(unsigned char), CV_8U, v09);
cv::Mat vec10 = vec09.clone();
vec10.cv::Mat::col(2) = 23;
unsigned char v11[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
cv::Mat mat11 = cv::Mat(3, 4, CV_8U, v11);
cv::Mat vec11 = mat11.reshape(1, 12);
unsigned char v12[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
cv::Mat vec12 = cv::Mat(1, sizeof(v)/sizeof(unsigned char), CV_8U, v12);
cv::Mat vec13;
vec12.convertTo( vec13, CV_32F );
cout << vec01 << "\n";
cout << vec02 << "\n";
cout << vec03 << "\n";
cout << vec04 << "\n";
cout << vec05 << "\n";
cout << vec06 << "\n";
cout << vec07 << "\n";
cout << vec08 << "\n";
cout << vec09 << "\n";
cout << vec10 << "\n";
cout << mat11 << "\n";
cout << vec11 << "\n";
cout << vec12 << "\n";
cout << vec13 << "\n";
waitKey(0);
return 0;
}
Windows では,Visual Studio の x64 Native Tools コマンドプロンプトを使う.(Windows のスタートメニューで起動できる).次のように実行して,プログラムファイル a.cpp を作り,実行する.
cd %LOCALAPPDATA%
notepad a.cpp
cl /I"c:\opencv\build\include" a.cpp /link /LIBPATH:"c:\opencv\build\lib" opencv_core455.lib opencv_highgui455.lib opencv_imgcodecs455.lib
.\a.exe

Ubuntu では,プログラムファイル(ファイル名は /tmp/a.cpp とする)を作成したのち,次のような手順で実行する.
g++ -I/usr/local/include/opencv4 -o /tmp/a.out /tmp/a.cpp -L/usr/local/lib -lopencv_world
/tmp/a.out
行列の要素の操作
- 参照(行ベクトル→スカラー)
: cv::Mat::col
要素番号 M を使っての参照.先頭要素は M = 0
「cv::Mat::col(M);」
vec01.cv::Mat::col(2);
- 要素の代入
: cv::Mat::col
要素番号 M を使っての代入. 先頭要素は M = 0
「cv::Mat::col(M) = x;」
vec01.cv::Mat::col(2) = 23;
◆ ソースコードの例
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main( int argc, char** argv )
{
unsigned char v[] = { 101, 102, 103, 104 };
cv::Mat vec01 = cv::Mat(1, sizeof(v)/sizeof(unsigned char), CV_8U, v);
cout << vec01.cv::Mat::col(0) << "\n";
cout << vec01.cv::Mat::col(2) << "\n";
vec01.cv::Mat::col(2) = 23;
cout << vec01 << "\n";
waitKey(0);
return 0;
}
Windows では,Visual Studio の x64 Native Tools コマンドプロンプトを使う.(Windows のスタートメニューで起動できる).次のように実行して,プログラムファイル a.cpp を作り,実行する.
cd %LOCALAPPDATA%
notepad a.cpp
cl /I"c:\opencv\build\include" a.cpp /link /LIBPATH:"c:\opencv\build\lib" opencv_core455.lib opencv_highgui455.lib opencv_imgcodecs455.lib
.\a.exe

Ubuntu では,プログラムファイル(ファイル名は /tmp/a.cpp とする)を作成したのち,次のような手順で実行する.
g++ -I/usr/local/include/opencv4 -o /tmp/a.out /tmp/a.cpp -L/usr/local/lib -lopencv_world
/tmp/a.out
行ベクトルの演算
https://docs.opencv.org/modules/core/doc/basic_structures.html#matrix-expressions
- 行ベクトルの要素のデータ型: cv::Mat::type()
cv::Mat::zeros(1, 5, CV_8U).type();
- サイズ: cv::Mat::size().width
cv::Mat::zeros(1, 5, CV_8U).size().width;
- 転置 (行ベクトル → 列ベクトル): cv::Mat::t()
「.'」を使った転置
cv::Mat::zeros(1, 5, CV_8U).t();
- 行ベクトルに同じ数を足す: + (行ベクトル → 行ベクトル)
* 要素単位の演算は,この Web ページの下の方に,別立てで書いています.
cv::Mat::zeros(1, 5, CV_8U) + 5;
- 行ベクトルの定数倍: * (行ベクトル → 行ベクトル)
* 要素単位の演算は,この Web ページの下の方に,別立てで書いています.
( cv::Mat::zeros(1, 5, CV_8U) + 5 ) * 3;
- 定数を行ベクトルの各要素で割る: / (行ベクトル → 行ベクトル)
float f[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 1.0 / cv::Mat(1, sizeof(f)/sizeof(float), CV_32F, f);
- 行ベクトルと、ある値との比較: == (行ベクトル → 行ベクトル)
unsigned char v01[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; cv::Mat(1, sizeof(v01)/sizeof(unsigned char), CV_8U, v01) == 4;
- 合計、最大、最小、平均: cv::reduce を使用
(
書きかけ)
cv::Mat s, av, ma, mi; unsigned char v01[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; cv::Mat vec01 = cv::Mat(1, sizeof(v01)/sizeof(unsigned char), CV_8U, v01); cv::reduce( vec01, s, CV_REDUCE_SUM, 0 ); cv::reduce( vec01, av, CV_REDUCE_AVG, 0 ); cv::reduce( vec01, ma, CV_REDUCE_MAX, 0 ); cv::reduce( vec01, mi, CV_REDUCE_MIN, 0 );
https://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=reduce#reduce
- ソート: cv::sort (行ベクトル → 行ベクトル)
unsigned char v02[] = { 3, 6, 2, 9, 1, 4, 7, 5, 8 }; cv::Mat vec02 = cv::Mat(1, sizeof(v02)/sizeof(unsigned char), CV_8U, v02); cv::Mat vec03, vec04; cv::sort( vec02, vec03, CV_SORT_ASCENDING ); cv::sort( vec02, vec04, CV_SORT_DESCENDING );
https://docs.opencv.org/modules/core/doc/operations_on_arrays.html?highlight=reduce#sort
- 内積: dot() (行ベクトル 列ベクトル → スカラー)
unsigned char v05[] = { 1, 2, 3 }; unsigned char v06[] = { 4, 5, 6 }; cv::Mat vec05 = cv::Mat(1, sizeof(v05)/sizeof(unsigned char), CV_8U, v05); cv::Mat vec06 = cv::Mat(1, sizeof(v06)/sizeof(unsigned char), CV_8U, v06); vec05.dot( vec06 );
◆ ソースコードの例
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main( int argc, char** argv )
{
cout << cv::Mat::zeros(1, 5, CV_8U).type() << "\n";
cout << cv::Mat::zeros(1, 5, CV_8U).size().width << "\n";
cout << cv::Mat::zeros(1, 5, CV_8U).t() << "\n";
cout << cv::Mat::zeros(1, 5, CV_8U) + 5 << "\n";
cout << ( cv::Mat::zeros(1, 5, CV_8U) + 5 ) * 3 << "\n";
float f[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
cout << 1.0 / cv::Mat(1, sizeof(f)/sizeof(float), CV_32F, f) << "\n";
unsigned char v01[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
cout << ( cv::Mat(1, sizeof(v01)/sizeof(unsigned char), CV_8U, v01) == 4 ) << "\n";
unsigned char v02[] = { 3, 6, 2, 9, 1, 4, 7, 5, 8 };
cv::Mat vec02 = cv::Mat(1, sizeof(v02)/sizeof(unsigned char), CV_8U, v02);
cv::Mat vec03, vec04;
cv::sort( vec02, vec03, SORT_ASCENDING );
cout << vec03 << "\n";
cv::sort( vec02, vec04, SORT_DESCENDING );
cout << vec04 << "\n";
unsigned char v05[] = { 1, 2, 3 };
unsigned char v06[] = { 4, 5, 6 };
cv::Mat vec05 = cv::Mat(1, sizeof(v05)/sizeof(unsigned char), CV_8U, v05);
cv::Mat vec06 = cv::Mat(1, sizeof(v06)/sizeof(unsigned char), CV_8U, v06);
cout << vec05.dot( vec06 ) << "\n";
waitKey(0);
return 0;
}
Windows では,Visual Studio の x64 Native Tools コマンドプロンプトを使う.(Windows のスタートメニューで起動できる).次のように実行して,プログラムファイル a.cpp を作り,実行する.
cd %LOCALAPPDATA%
notepad a.cpp
cl /I"c:\opencv\build\include" a.cpp /link /LIBPATH:"c:\opencv\build\lib" opencv_core455.lib opencv_highgui455.lib opencv_imgcodecs455.lib
.\a.exe

Ubuntu では,プログラムファイル(ファイル名は /tmp/a.cpp とする)を作成したのち,次のような手順で実行する.
g++ -I/usr/local/include/opencv4 -o /tmp/a.out /tmp/a.cpp -L/usr/local/lib -lopencv_world
/tmp/a.out
行列
https://docs.opencv.org/modules/core/doc/basic_structures.html#mat
行列のコンストラクタ
- 行列のコンストラクタ
unsigned char v[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; cv::Mat mat01 = cv::Mat(3, 4, CV_8U, v);
- 全要素が 0 の行列: cv::Mat::zeros
「cv::Mat::zeros(n, m, <要素型>)」のように書く.n は行数,m は列数.
cv::Mat mat02 = cv::Mat::zeros(3, 4, CV_8U);
- 全要素が 1 の行列: cv::Mat::ones
「cv::Mat::ones(1, m, <要素型>)」のように書く.n は行数,m は列数.
cv::Mat mat03 = cv::Mat::ones(3, 4, CV_8U);
- 全要素が 同じ値 の行列: cv::Mat
「cv::Mat(1, 5, <要素型>, cv::Scalar(x));」のように書く.n は行数,m は列数.
cv::Mat mat04 = cv::Mat(3, 4, CV_8U, cv::Scalar(8));
- 単位行列: cv::Mat::eye
「eye(n, m, CV_8U)」のように書く.
cv::Mat mat05 = cv::Mat::zeros(3, 4, CV_8U);
- [A, B) の一様乱数を要素に持つ行列: cv::randu
「cv::randu(mat, Scalar(A), cv::Scalar(B));」
cv::Mat mat06 = cv::Mat::zeros(3, 4, CV_8U); cv::randu(mat06, cv::Scalar(0), cv::Scalar(256));
- 平均 M 分散 S の正規分布の乱数を要素に持つ行列: cv::randn
「cv::randn(mat, Scalar(M), cv::Scalar(S));」
cv::Mat mat07 = cv::Mat::zeros(3, 4, CV_8U); cv::randn(mat07, cv::Scalar(128), cv::Scalar(5));
- 浅いコピー: =
unsigned char v08[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; cv::Mat mat08 = cv::Mat(3, 4, CV_8U, v08); cv::Mat mat09 = mat08;
- 深いコピー: clone
unsigned char v10[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; cv::Mat mat10 = cv::Mat(3, 4, CV_8U, v10); cv::Mat mat11 = mat10.clone();
- サイズの変更: reshape
下の例では、行ベクトルを行列に変換している. 「reshape(n, m)」のように書く.n は行数.m は列数.
unsigned char v12[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; cv::Mat vec12 = cv::Mat(1, 12, CV_8U, v12); cv::Mat mat12 = vec12.reshape(3, 4);
- 要素の型変換: covertTo
unsigned char v13[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; cv::Mat mat13 = cv::Mat(3, 4, CV_8U, v13); cv::Mat mat14; mat13.convertTo( mat14, CV_32F );
◆ ソースコードの例
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main( int argc, char** argv )
{
unsigned char v[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
cv::Mat mat01 = cv::Mat(3, 4, CV_8U, v);
cv::Mat mat02 = cv::Mat::zeros(3, 4, CV_8U);
cv::Mat mat03 = cv::Mat::ones(3, 4, CV_8U);
cv::Mat mat04 = cv::Mat(3, 4, CV_8U, cv::Scalar(8));
cv::Mat mat05 = cv::Mat::zeros(3, 4, CV_8U);
cv::Mat mat06 = cv::Mat::zeros(3, 4, CV_8U);
cv::randu(mat06, cv::Scalar(0), cv::Scalar(256));
cv::Mat mat07 = cv::Mat::zeros(3, 4, CV_8U);
cv::randn(mat07, cv::Scalar(128), cv::Scalar(5));
unsigned char v08[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
cv::Mat mat08 = cv::Mat(3, 4, CV_8U, v08);
cv::Mat mat09 = mat08;
mat09.cv::Mat::col(2).cv::Mat::row(2) = 23;
unsigned char v10[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
cv::Mat mat10 = cv::Mat(3, 4, CV_8U, v10);
cv::Mat mat11 = mat10.clone();
mat11.cv::Mat::col(2).cv::Mat::row(2) = 23;
unsigned char v12[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
cv::Mat vec12 = cv::Mat(1, 12, CV_8U, v12);
cv::Mat mat12 = vec12.reshape(3, 4);
unsigned char v13[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
cv::Mat mat13 = cv::Mat(3, 4, CV_8U, v13);
cv::Mat mat14;
mat13.convertTo( mat14, CV_32F );
cout << mat01 << "\n";
cout << mat02 << "\n";
cout << mat03 << "\n";
cout << mat04 << "\n";
cout << mat05 << "\n";
cout << mat06 << "\n";
cout << mat07 << "\n";
cout << mat08 << "\n";
cout << mat09 << "\n";
cout << mat10 << "\n";
cout << mat11 << "\n";
cout << vec12 << "\n";
cout << mat12 << "\n";
cout << mat13 << "\n";
cout << mat14 << "\n";
waitKey(0);
return 0;
}
Windows では,Visual Studio の x64 Native Tools コマンドプロンプトを使う.(Windows のスタートメニューで起動できる).次のように実行して,プログラムファイル a.cpp を作り,実行する.
cd %LOCALAPPDATA%
notepad a.cpp
cl /I"c:\opencv\build\include" a.cpp /link /LIBPATH:"c:\opencv\build\lib" opencv_core455.lib opencv_highgui455.lib opencv_imgcodecs455.lib
.\a.exe

Ubuntu では,プログラムファイル(ファイル名は /tmp/a.cpp とする)を作成したのち,次のような手順で実行する.
g++ -I/usr/local/include/opencv4 -o /tmp/a.out /tmp/a.cpp -L/usr/local/lib -lopencv_world
/tmp/a.out
行列の要素の操作
- 特定の列の参照
: cv::Mat::col
列番号 M を使っての参照.先頭要素は M = 0
「cv::Mat::col(M);」
mat01.cv::Mat::col(1);
- 特定の行の参照
: cv::Mat::row
行番号 N を使っての参照.先頭要素は M = 0
「cv::Mat::row(M);」
mat01.cv::Mat::row(2);
- 対角要素の参照: diag
diag を使う.引数に指定したベクトルを対角要素に持つ行列が作られる.
mat01.diag(0); mat01.diag(-1); mat01.diag(1);
- 要素の参照
: cv::Mat::col と cv::Mat::rowの組み合わせ
列番号 M と行番号 N を使っての参照.左上の要素は M = 0, N = 0
「cv::Mat::col(M).cv::Mat::row(N);」
mat01.cv::Mat::col(1).cv::Mat::row(2);
- 要素の代入
: cv::Mat::col と cv::Mat::rowの組み合わせ
列番号 M と行番号 N を使っての代入.左上の要素は M = 0, N = 0
「cv::Mat::col(M).cv::Mat::row(N) = x;」
mat01.cv::Mat::col(1).cv::Mat::row(2) = 23;
◆ ソースコードの例
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main( int argc, char** argv )
{
unsigned char v[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
cv::Mat mat01 = cv::Mat(3, 4, CV_8U, v);
cout << mat01 << "\n";
cout << mat01.cv::Mat::col(1) << "\n";
cout << mat01.cv::Mat::row(2) << "\n";
cout << mat01.diag(0) << "\n";
cout << mat01.diag(-1) << "\n";
cout << mat01.diag(1) << "\n";
cout << mat01.cv::Mat::col(1).cv::Mat::row(2) << "\n";
cout << ( mat01.cv::Mat::col(1).cv::Mat::row(2) = 23 ) << "\n";
waitKey(0);
return 0;
}
Windows では,Visual Studio の x64 Native Tools コマンドプロンプトを使う.(Windows のスタートメニューで起動できる).次のように実行して,プログラムファイル a.cpp を作り,実行する.
cd %LOCALAPPDATA%
notepad a.cpp
cl /I"c:\opencv\build\include" a.cpp /link /LIBPATH:"c:\opencv\build\lib" opencv_core455.lib opencv_highgui455.lib opencv_imgcodecs455.lib
.\a.exe

Ubuntu では,プログラムファイル(ファイル名は /tmp/a.cpp とする)を作成したのち,次のような手順で実行する.
g++ -I/usr/local/include/opencv4 -o /tmp/a.out /tmp/a.cpp -L/usr/local/lib -lopencv_world
/tmp/a.out