Pynote

Python、機械学習、画像処理について

OpenCV - 行列の加減乗除及び Utility 関数

試した環境

加減乗除

加算

add()saturate(src1 + src2) を計算する。

関数
void cv::add(InputArray src1,
             InputArray src2,
             OutputArray dst,
             InputArray mask = noArray(),
             int dtype = -1)
dst = cv2.add(src1, src2[, dst[, mask[, dtype]]])
コード
cv::Mat src1 =
    (cv::Mat_<int>(3, 3) << 5, 7, -7, 7, 6, -2, 8, -3, 1);
cv::Mat src2 = (cv::Mat_<int>(3, 3) << 5, 7, 2, 7, -6, 1, 18, 3, 0);

// add()
cv::Mat dst;
cv::add(src1, src2, dst);
std::cout << dst << std::endl;

// operator+()
dst = src1 + src2;
std::cout << dst << std::endl;

// operator+=()
cv::Mat src = src1.clone();
src += src2;
std::cout << src << std::endl;
src1 = np.array([[5, 7, -7],
                 [7, 6, -2],
                 [8, -3, 1]])
src2 = np.array([[5, 7, 2],
                 [7, -6, 1],
                 [18, 3, 0]])

# OpenCV
dst = cv2.add(src1, src2)
print(dst)
# [[10 14 -5]
#  [14  0 -1]
#  [26  0  1]]

# numpy
dst = src1 + src2
print(dst)

src = src1.copy()
src += src2
print(src)

減算

substract()saturate(src1 - src2) を計算する。

関数
void cv::subtract(InputArray src1,
                  InputArray src2,
                  OutputArray dst,
                  InputArray mask = noArray(),
                  int dtype = -1)
dst = cv2.subtract(src1, src2[, dst[, mask[, dtype]]])
コード
cv::Mat src1 =
    (cv::Mat_<int>(3, 3) << 5, 7, -7, 7, 6, -2, 8, -3, 1);
cv::Mat src2 = (cv::Mat_<int>(3, 3) << 5, 7, 2, 7, -6, 1, 18, 3, 0);

// add()
cv::Mat dst;
cv::subtract(src1, src2, dst);
std::cout << dst << std::endl;

// operator-()
dst = src1 - src2;
std::cout << dst << std::endl;

// operator-=()
cv::Mat src = src1.clone();
src -= src2;
std::cout << src << std::endl;
src1 = np.array([[5, 7, -7],
                 [7, 6, -2],
                 [8, -3, 1]])
src2 = np.array([[5, 7, 2],
                 [7, -6, 1],
                 [18, 3, 0]])

# OpenCV
dst = cv2.subtract(src1, src2)
print(dst)
[[  0   0  -9]
#  [  0  12  -3]
#  [-10  -6   1]]

# numpy
dst = src1 - src2
print(dst)

src = src1.copy()
src -= src2
print(src)

要素ごとの乗算

multiply()saturate(scale * src1 * src2) を計算する。

関数
void cv::multiply(InputArray src1,
                  InputArray src2,
                  OutputArray dst,
                  double scale = 1,
                  int dtype = -1)
dst = cv2.multiply(src1, src2[, dst[, scale[, dtype]]])
コード
cv::Mat src1 =
    (cv::Mat_<int>(3, 3) << 5, 7, -7, 7, 6, -2, 8, -3, 1);
cv::Mat src2 = (cv::Mat_<int>(3, 3) << 5, 7, 2, 7, -6, 1, 18, 3, 0);

cv::Mat dst;
cv::multiply(src1, src2, dst, 2.);
std::cout << dst << std::endl;

要素ごとの除算

divide() は次を計算するオーバーロード関数が定義されている。
0除算が発生する計算の結果は0となる。

関数

saturate(scale * src1 / src2) を計算する。

void cv::divide(InputArray src1,
                InputArray src2,
                OutputArray dst,
                double scale = 1,
                int dtype = -1)
dst = cv2.divide(src1, src2[, dst[, scale[, dtype]]])
  • saturate(scale / src2) を計算する。
void cv::divide(double scale,
                InputArray src2,
                OutputArray dst,
                int dtype = -1)
dst = cv2.divide(scale, src2[, dst[, dtype]])
コード
cv::Mat src1 = (cv::Mat_<int>(3, 3) << 5, 7, -7, 7, 6, -2, 8, -3, 1);
cv::Mat src2 = (cv::Mat_<int>(3, 3) << 5, 7, 2, 7, -6, 1, 18, 3, 0);

// scale * src1 / src2
cv::Mat dst;
cv::divide(src1, src2, dst, 2.);
std::cout << dst << std::endl;

// scale / src2
cv::divide(5., src2, dst);
std::cout << dst << std::endl;
src1 = np.array([[5, 7, -7],
                 [7, 6, -2],
                 [8, -3, 1]])
src2 = np.array([[5, 7, 2],
                 [7, -6, 1],
                 [18, 3, 0]])

# scale * src1 / src2
dst = cv2.divide(src1, src2, scale=2.)
print(dst)
# [[ 2  2 -7]
#  [ 2 -2 -4]
#  [ 1 -2  0]]
# 3x3 の0除算が発生する計算結果は0になる。

# scale / src2
dst = cv2.divide(5., src2)
print(dst)
# [[ 1  1  2]
#  [ 1 -1  5]
#  [ 0  2  0]]
# 3x3 の0除算が発生する計算結果は0になる。

比較

compare() で配列同士の比較が行える。

2つの配列を要素ごとに比較し、比較演算子の結果が真である要素は255、そうでない要素は0とした配列を返す。

関数
void cv::compare(InputArray src1,
                 InputArray src2,
                 OutputArray dst,
                 int cmpop)
dst = cv2.compare(src1, src2, cmpop[, dst])
コード
cv::Mat src1 = (cv::Mat_<int>(3, 3) << 5, 7, -7, 7, 6, -2, 8, -3, 1);
cv::Mat src2 = (cv::Mat_<int>(3, 3) << 5, 7, 2, 7, -6, 1, 18, 3, 0);

// src1 == src2
cv::Mat dst;
cv::compare(src1, src2, dst, cv::CMP_EQ);
std::cout << dst << std::endl;

// src1 > src2
cv::compare(src1, src2, dst, cv::CMP_GT);
std::cout << dst << std::endl;

// src1 >= src2
cv::compare(src1, src2, dst, cv::CMP_GE);
std::cout << dst << std::endl;

// src1 < src2
cv::compare(src1, src2, dst, cv::CMP_LT);
std::cout << dst << std::endl;

// src1 <= src2
cv::compare(src1, src2, dst, cv::CMP_LE);
std::cout << dst << std::endl;

// src1 != src2
cv::compare(src1, src2, dst, cv::CMP_NE);
std::cout << dst << std::endl;
src1 = np.array([[5, 7, -7],
                 [7, 6, -2],
                 [8, -3, 1]])
src2 = np.array([[5, 7, 2],
                 [7, -6, 1],
                 [18, 3, 0]])

# src1 == src2
dst = cv2.compare(src1, src2, cv2.CMP_EQ)
print(dst)
# [[255 255   0]
#  [255   0   0]
#  [  0   0   0]]

# src1 > src2
dst = cv2.compare(src1, src2, cv2.CMP_GT)
print(dst)
# [[  0   0   0]
#  [  0 255   0]
#  [  0   0 255]]

# src1 >= src2
dst = cv2.compare(src1, src2, cv2.CMP_GE)
print(dst)
# [[255 255   0]
#  [255 255   0]
#  [  0   0 255]]

# src1 < src2
dst = cv2.compare(src1, src2, cv2.CMP_LT)
print(dst)
# [[  0   0 255]
#  [  0   0 255]
#  [255 255   0]]

# src1 <= src2
dst = cv2.compare(src1, src2, cv2.CMP_LE)
print(dst)
# [[255 255 255]
#  [255   0 255]
#  [255 255   0]]

# src1 != src2
dst = cv2.compare(src1, src2, cv2.CMP_NE)
print(dst)
# [[  0   0 255]
#  [  0 255 255]
#  [255 255 255]]

Utility 関数

absdiff

absdiff() は2つの入力の差の絶対値を返す。

dst = saturate(|src1 - src2|)

関数
void cv::absdiff(InputArray src1, InputArray src2, OutputArray dst)
dst = cv2.absdiff(src1, src2[, dst])
コード
cv::Mat src1 = (cv::Mat_<int>(3, 3) << 5, 7, -7, 7, 6, -2, 8, -3, 1);
cv::Mat src2 = (cv::Mat_<int>(3, 3) << 5, 7, 2, 7, -6, 1, 18, 3, 0);

// src1 及び src2 が行列の場合
cv::Mat dst;
cv::absdiff(src1, src2, dst);
std::cout << dst << std::endl;

// src1 が行列、src2 がスカラーの場合
cv::absdiff(src1, 3, dst);
std::cout << dst << std::endl;

// src1 がスカラー、src2 が行列の場合
cv::absdiff(3, src2, dst);
std::cout << dst << std::endl;
src1 = np.array([[5, 7, -7],
                 [7, 6, -2],
                 [8, -3, 1]])
src2 = np.array([[5, 7, 2],
                 [7, -6, 1],
                 [18, 3, 0]])

# src1 及び src2 が行列の場合
dst = cv2.absdiff(src1, src2)
print(dst)
# [[ 0  0  9]
#  [ 0 12  3]
#  [10  6  1]]

# src1 が行列、src2 がスカラーの場合
dst = cv2.absdiff(3, src2)
print(dst)
# [[ 2  4  1]
#  [ 4  9  2]
#  [15  0  3]]

# src1 がスカラー、src2 が行列の場合
dst = cv2.absdiff(src1, 3)
print(dst)
# [[ 2  4 10]
#  [ 4  3  5]
#  [ 5  6  2]]

addWeighted

addWeighted() dst = \verb|saturate_cast|(src1 * alpha + src2 * beta + gamma) を計算する。

関数
void cv::addWeighted(InputArray src1,
                     double alpha,
                     InputArray src2,
                     double beta,
                     double gamma,
                     OutputArray dst,
                     int dtype = -1)
dst = cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])
コード
cv::Mat src1 = (cv::Mat_<int>(3, 3) << 5, 7, -7, 7, 6, -2, 8, -3, 1);
cv::Mat src2 = (cv::Mat_<int>(3, 3) << 5, 7, 2, 7, -6, 1, 18, 3, 0);

cv::Mat dst;
double alpha = 0.1, beta = 0.5, gamma = 0.3;
cv::addWeighted(src1, alpha, src2, beta, gamma, dst);
std::cout << dst << std::endl;
src1 = np.array([[5, 7, -7],
                 [7, 6, -2],
                 [8, -3, 1]])
src2 = np.array([[5, 7, 2],
                 [7, -6, 1],
                 [18, 3, 0]])

alpha = 0.1
beta = 0.5
gamma = 0.3

dst = cv2.addWeighted(src1, alpha, src2, beta, gamma)
print(dst)
# [[ 3  4  1]
#  [ 4 -2  1]
#  [10  2  0]]

convertScaleAbs

convertScaleAbs() dst = \verb|saturate_cast|(|alpha * src + beta|) を計算する。

関数
void cv::convertScaleAbs(InputArray src,
                         OutputArray dst,
                         double alpha = 1,
                         double beta = 0)
dst = cv2.convertScaleAbs(src[, dst[, alpha[, beta]]])
コード
src = np.array([[5, 7, -7],
                [7, 6, -2],
                [8, -3, 1]])
alpha = 0.1
beta = 0.5

dst = cv2.convertScaleAbs(src, alpha=2., beta=3.)
print(dst)
# [[13 17 11]
#  [17 15  1]
#  [19  3  5]]
cv::Mat src = (cv::Mat_<int>(3, 3) << 5, 7, -7, 7, 6, -2, 8, -3, 1);
double alpha = 2., beta = 3.;

cv::Mat dst;
cv::convertScaleAbs(src, dst, alpha, beta);
std::cout << dst << std::endl;

scaleAdd

scaleAdd() dst = scale * src1 + src2 を計算する。

関数
void cv::scaleAdd(InputArray src1,
                  double alpha,
                  InputArray src2,
                  OutputArray dst)
dst = cv2.scaleAdd(src1, alpha, src2[, dst])
コード
cv::Mat src1 = (cv::Mat_<int>(3, 3) << 5, 7, -7, 7, 6, -2, 8, -3, 1);
cv::Mat src2 = (cv::Mat_<int>(3, 3) << 5, 7, 2, 7, -6, 1, 18, 3, 0);

cv::Mat dst;
cv::scaleAdd(src1, 2., src2, dst);
std::cout << dst << std::endl;
src1 = np.array([[5, 7, -7],
                 [7, 6, -2],
                 [8, -3, 1]])
src2 = np.array([[5, 7, 2],
                 [7, -6, 1],
                 [18, 3, 0]])
scale = 2.

dst = cv2.scaleAdd(src1, scale, src2)
print(dst)
# [[ 15  21 -12]
#  [ 21   6  -3]
#  [ 34  -3   2]]