python

画像処理・解析その1

アフィン変換

アフィン変換とは、回転・平行移動などの線形変換です。
下記の画像のようなせん断変形や曲げ変形もアフィン変換になります。
変換の式についても載せておきます。
同次座標を用いることで、一つの行列にまとめる事もできます。

import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

img = cv2.imread('Lenna_(test_image).png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
h, w = img.shape[:2]
dx, dy = 30, 30 # 画像の平行移動量

afn_mat = np.float32([[1,0, dx], [0, 1, dy]]) # 変換行列を定義
img_afn = cv2.warpAffine(img, afn_mat, (w, h))

plt.imshow(img_afn)

# 回転
rot_mat = cv2.getRotationMatrix2D((w/2, h/2), 40, 1) # getRotationMatrix2D(center, angle, scale)
img_afn2 = cv2.warpAffine(img, rot_mat, (w, h))

plt.imshow(img_afn2)

透視変換

透視変換とは、 任意の視点から3次元空間を眺めて遠近感を出す変換です。
画像が2次元で表示されているものを奥行きがあるように変換したりすることができます。

import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

img = cv2.imread('Lenna_(test_image).png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
h, w = img.shape[:2]

# 画像の4隅の対応関係を作成します
per1 = np.float32([[100, 400], [300, 500], [300, 100], [100, 100]])
per2 = np.float32([[100, 400], [300, 500], [200, 200], [150, 200]]) # 対応後の座標関係

psp_matrix = cv2.getPerspectiveTransform(per1, per2) # 変換の行列
img_psp = cv2.warpPerspective(img, psp_matrix, (w, h))

plt.imshow(img_psp)

畳み込みとは

畳み込みとは、周囲の情報を使用した自身の画素値の更新をすることです。
畳み込みの流れとしては、
1、フィルターを用意する(種類は様々)

2、着目画素の周囲情報で(画素値)x(フィルター)を行い足していく=>畳み込み

3、すべての画素について畳み込みを行う

畳み込みを終えると、元画像と比べて、画像がぼける・ノイズが消えることがわかります。
なぜぼけるのかというと、周りの情報を取り込むことで、元々鮮明でシャープであったものが、境界が曖昧にぼけてしまいます。その代わりに、ノイズは局所的に現れるのでノイズを消す効果が得られます。

フィルターには、平滑化フィルターやSobelフィルターなどがありますが、自身で設定する事もできます。

畳み込みの基礎

import cv2
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

kernel = np.ones((3, 3)) / 9.0 # 3*3の1/9のフィルターを用意
# array([[0.11111111, 0.11111111, 0.11111111],
#        [0.11111111, 0.11111111, 0.11111111],
#        [0.11111111, 0.11111111, 0.11111111]])

img = cv2.imread('Lenna_(test_image).png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_kel = cv2.filter2D(img, -1, kernel) # -1は出力画像の深度を元画像と合わせるための設定

fig = plt.figure()
plt.gray()
fig.add_subplot(1,2,1)
plt.imshow(img)

plt.gray()
fig.add_subplot(1,2,2)
plt.imshow(img_kel)

# フィルターを自作(横方向の微分)
kernel2 = np.zeros((3, 3))
kernel2[0, 0] = 1
kernel2[1, 0] = 2
kernel2[2, 0] = 1
kernel2[0, 2] = -1
kernel2[1, 2] = -2
kernel2[2, 2] = -1

kernel2
# array([[ 1.,  0., -1.],
#        [ 2.,  0., -2.],
#        [ 1.,  0., -1.]])

img_ke2 = cv2.filter2D(img, -1, kernel2)

fig = plt.figure()
plt.gray()
fig.add_subplot(1,2,1)
plt.imshow(img)

plt.gray()
fig.add_subplot(1,2,2)
plt.imshow(img_ke2)