【Python】OpenCVでエンボス加工してみる

こんにちは!最近業務で使うキーボードを変えたポンです。

前回はOpenCVのインストール、画像の表示を行いました。今回は画像を加工してみようと思います!

エンボス加工とは??

文字や絵を浮き彫りにする加工のことです。点字を想像するとわかりやすいと思います。

処理の流れ

まずは大まかな処理の流れを説明していきたいと思います。今回は以下のような形で処理を進めていきます。

  1. 入力画像をグレースケールで読み込む
  2. 入力画像をコピーしネガポジ反転する
  3. ネガポジ反転した画像を斜めに数ピクセル平行移動させる
  4. グレースケール画像と平行移動したネガポジ画像を合成する
  5. いい感じに出来上がり!

実際にやってみる

コードを書いていきます。まずはグレースケールで読み込むところまで実装していきます。

import cv2
import numpy as np

# 画像のパス
IMG_PATH = 'path/to/image.jpg'

# グレイスケールで読み込み
gray_img = cv2.imread(IMG_PATH, cv.IMREAD_GRAYSCALE)

ここまでで画像をグレースケールで読み込むことができました。imshow()で表示するとこのような感じになります。

続いてネガポジ反転です。ネガポジ反転は、各画素の値を255から引くことで表現できます。今回はLUT(Look Up Table)を使用した関数を実装してみます。

def nega_convert(input_img):
    """
    ネガポジ反転を行う

    Parameters
    ----------
    input_img : uint8
        入力画像
    
    Returns
    -------
    nega_img : uint8
        ネガポジ反転後の画像
    """

    # LUTの作成
    lut = np.zeros((256, 1), dtype = 'uint8')
    for i in range(256):
        lut[i][0] = 255 - i
    
    # LUTの適用
    nega_img = cv2.LUT(input_img, lut)
    
    return nega_img

こちらもimshow()で出力してみると……

なんだか気味が悪いですが、いい感じに反転できていますね。

この調子で平行移動も実装していきましょう! 平行移動はアフィン変換を適用する形で実装します。アフィン変換とは 3x3 の行列を使用しての変換のことを指します。こちらも関数を作って実装していきます。

def move_img(input_img, mv_x, mv_y):
    """
    平行移動を行う

    Parameters
    ----------
    input_img : uint8
        入力画像
    mv_x : int
        x軸移動量
    mv_y : int
        y軸移動量

    Returns
    -------
    mv_img : uint8
        平行移動後の画像
    """

    # 画像の大きさを取得
    width = input_img.shape[0]
    height = input_img.shape[1]

    # 移動用の行列の作成
    mat = np.float32([[1, 0, mv_x], [0, 1, mv_y]])
    # 移動の実行
    mv_img = cv2.warpAffine(input_img, mat, (height, width))

    return mv_img

実装できたら同じようにimshow()で出力してみましょう!

少し分りづらいですが、斜め右下に移動していることがわかると思います。上記の画像では平行移動していることを確認するために、移動量の引数に大きめの数値を与えています。

ここまできたら最後は合成です! どんどん進めていきます。

def add_img(gray_img, mv_img):
    """
    画像の合成を行う

    Parameters
    ----------
    gray_img : uint8
        入力画像1 (グレースケール画像)
    mv_img : uint8
        入力画像2 (平行移動後のネガポジ反転画像)

    Returns
    -------
    emboss_img : uint8
        エンボス画像
    """

    # 画像の合成 127を引くのは凹凸をめだたせるため
    emboss_img = (gray_img + mv_img) - 127
    # 0から255の範囲に値をおさめる
    emboss_img = emboss_img.clip(0, 255)

    return emboss_img

最後もimshow()で出力してみましょう。

一風違った面白い画像が出来上がりました!

ちなみに今回与えた移動量はx、yともに 2 です。画像の大きさなどによって最適の移動量は変わってくるので、試行錯誤していい感じの移動量を見つけてください。また、ノイズが目立つ場合は、medianBlur()などでノイズ除去するのも良いかもしれません。

まとめ

今回はOpenCVを使って画像加工(エンボス加工)を行いました。OpenCVはやろうと思えば、大抵のことはできるので、色々試してみるのも楽しいと思います。

機会があればまたOpenCVの記事を書くかもしれません! それでは!