目標
画像の加算
OpenCVの関数 cv.add() を使うか、単に numpy 演算 res = img1 + img2 によって2つの画像を加算できる。両方の画像は同じビット深度・型でなければならず、または2番目の画像は単なるスカラー値でもよい。
- 覚え書き
- OpenCVの加算とNumpyの加算には違いがある。OpenCVの加算は飽和演算であるのに対し、Numpyの加算は剰余演算である。
例として、以下のサンプルを考える:
>>> x = np.uint8([250])
>>> y = np.uint8([10])
[[255]]
>>> print( x+y )
[4]
void add(InputArray src1, InputArray src2, OutputArray dst, InputArray mask=noArray(), int dtype=-1)
Calculates the per-element sum of two arrays or an array and a scalar.
これは2つの画像を加算するとより顕著になる。より良い結果が得られるため、OpenCVの関数を使うとよい。
画像のブレンディング
これも画像の加算であるが、ブレンディングや透明感を出すために画像に異なる重みを与える。画像は以下の式に従って加算される:
\[g(x) = (1 - \alpha)f_{0}(x) + \alpha f_{1}(x)\]
\(\alpha\) を \(0 \rightarrow 1\) と変化させることで、ある画像から別の画像への滑らかなトランジションを実現できる。
ここでは2枚の画像をブレンドして合成する。1枚目の画像には重み0.7を、2枚目の画像には重み0.3を与える。cv.addWeighted() は画像に対して次の式を適用する。
\[dst = \alpha \cdot img1 + \beta \cdot img2 + \gamma\]
ここでは \(\gamma\) を0としている。
assert img1 is not None, "file could not be read, check with os.path.exists()"
assert img2 is not None, "file could not be read, check with os.path.exists()"
void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype=-1)
Calculates the weighted sum of two arrays.
void imshow(const String &winname, InputArray mat)
Displays an image in the specified window.
int waitKey(int delay=0)
Waits for a pressed key.
void destroyAllWindows()
Destroys all of the HighGUI windows.
Mat imread(const String &filename, int flags=IMREAD_COLOR_BGR)
Loads an image from a file.
結果を以下に示す。
image
ビット演算
これにはビット単位のAND・OR・NOT・XOR演算が含まれる。これらは画像の任意の部分を抽出する際(後の章で見るように)や、矩形でないROIを定義して扱う際などに非常に有用である。以下では画像の特定領域を変更する例を見ていく。
ある画像の上にOpenCVのロゴを載せたいとする。2枚の画像を単純に加算すると色が変わってしまう。ブレンドすると透けた効果になる。しかしここでは不透明にしたい。もし矩形領域であれば、前章で行ったようにROIを使えばよい。だがOpenCVのロゴは矩形ではない。そこで以下に示すようにビット演算を使えば実現できる。
assert img1 is not None, "file could not be read, check with os.path.exists()"
assert img2 is not None, "file could not be read, check with os.path.exists()"
rows,cols,channels = img2.shape
roi = img1[0:rows, 0:cols]
ret, mask =
cv.threshold(img2gray, 10, 255, cv.THRESH_BINARY)
img1[0:rows, 0:cols ] = dst
void bitwise_not(InputArray src, OutputArray dst, InputArray mask=noArray())
Inverts every bit of an array.
void bitwise_and(InputArray src1, InputArray src2, OutputArray dst, InputArray mask=noArray())
computes bitwise conjunction of the two arrays (dst = src1 & src2) Calculates the per-element bit-wis...
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0, AlgorithmHint hint=cv::ALGO_HINT_DEFAULT)
Converts an image from one color space to another.
double threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type)
Applies a fixed-level threshold to each array element.
結果を以下に示す。左の画像は作成したマスクを示す。右の画像は最終結果を示す。理解を深めるため、上記コード中の中間画像、特に img1_bg と img2_fg をすべて表示してみるとよい。
image
演習
- cv.addWeighted 関数を使い、フォルダ内の画像を画像間で滑らかにトランジションさせるスライドショーを作成せよ