目次
概要
OpenCV で画像にエンボス処理を行う方法について解説します。
エンボス処理
入力画像の $(x, y)$ の画素値を $\text{src}(x, y)$ としたとき、符号を反転させ、$x, y$ 共に $t$ だけ平行移動した位置の画素 $-\text{src}(x + t, y + t)$ を足して、出力画像の画素を作成する処理をエンボス (emboss) といいます。
$$ \text{dst}(x, y) = \text{src} + (-\text{src}(x + t, y + t)) $$1次元で考えると、以下のようにエッジ部分を強調する処理であると理解できます。
フィルタを使用したエンボス処理
エンボス処理はフィルタリングでも行えます。
水平方向のエンボスフィルタ
$$ \begin{pmatrix} 0 & 0 & 0 \\ 1 & 0 & -1 \\ 0 & 0 & 0 \\ \end{pmatrix} $$垂直方向のエンボスフィルタ
$$ \begin{pmatrix} 0 & 1 & 0 \\ 0 & 0 & 0 \\ 0 & -1 & 0 \\ \end{pmatrix} $$斜め方向のエンボスフィルタ
$$ \begin{pmatrix} 1 & 0 & 0 \\ 0 & 0 & 0 \\ 0 & 0 & -1 \\ \end{pmatrix}, \begin{pmatrix} -1 & 0 & 0 \\ 0 & 0 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} $$$$ \begin{pmatrix} 0 & 0 & 1 \\ 0 & 0 & 0 \\ -1 & 0 & 0 \\ \end{pmatrix}, \begin{pmatrix} 0 & 0 & -1 \\ 0 & 0 & 0 \\ 1 & 0 & 0 \\ \end{pmatrix} $$OpenCV でのエンボス処理
In [1]:
import cv2
import numpy as np
from IPython.display import Image, display
def imshow(img):
"""ndarray 配列をインラインで Notebook 上に表示する。
"""
ret, encoded = cv2.imencode(".jpg", img)
display(Image(encoded))
# 画像を読み込む。
img = cv2.imread("sample.jpg", cv2.IMREAD_GRAYSCALE)
cv2.filter()
で画像にエンボスフィルタを適用できます。
演算結果は $[0, 255]$ に収まらないので、ddepth=cv2.CV_32F
を指定して、結果は float32
型の配列で受け取ります。その後、$[0, 255]$ の範囲にスケールします。
水平方向のエンボスフィルタ
In [2]:
def scale(x):
x = 255 / (x.max() - x.min()) * (x - x.max()) + 255
return x.astype(np.uint8)
# 水平方向のエンボスフィルタ
kernel = np.array([[0, 0, 0],
[1, 0, -1],
[0, 0, 0]])
dst = cv2.filter2D(img, cv2.CV_32F, kernel)
dst = scale(dst)
imshow(dst)
垂直方向のエンボスフィルタ
In [3]:
# 垂直方向のエンボスフィルタ
kernel = np.array([[0, 1, 0],
[0, 0, 0],
[0, -1, 0]])
dst = cv2.filter2D(img, cv2.CV_32F, kernel)
dst = scale(dst)
imshow(dst)
斜め方向のエンボスフィルタ
In [4]:
kernel = np.array([[1, 0, 0],
[0, 0, 0],
[0, 0, -1]])
dst = cv2.filter2D(img, cv2.CV_32F, kernel)
dst = scale(dst)
imshow(dst)
In [5]:
kernel = np.array([[0, 0, -1],
[0, 0, 0],
[1, 0, 0]])
dst = cv2.filter2D(img, cv2.CV_32F, kernel)
dst = scale(dst)
imshow(dst)
エンボスをより強くする
In [6]:
kernel = np.array(
[
[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, -1, 0],
[0, 0, 0, 0, -1],
]
)
dst = cv2.filter2D(img, cv2.CV_32F, kernel)
dst = scale(dst)
imshow(dst)
コメント