【初心者向け】Pythonによる画像処理入門!ライブラリから基本を理解する

Pythonによる画像処理の基本を学びたい!そんな方にぴったりの記事です。

Pythonによる画像処理のライブラリから、画像処理の基礎まで学ぶことが出来ます。

この記事を読み終わる頃には、画像処理に必要な知識をすべて身につけているはずです。

それでは、画像処理の基本を学んでいきましょう!

目次

画像処理とは?

画像処理とは、主にコンピュータを使用して、画像を変形したり、色合いを変えたり、別の画像と合成したり、画像に対して何らかの処理を行う事を指します。

画像に対して、変換、変形、解析、情報抽出などを行います。

コンピュータビジョン、医療、人工知能、ロボット工学など、様々な分野で利用されています。

画像処理では、デジタル画像を加工して所望の画像や情報を得ることが出来ます。

Pythonの画像処理でできること

Pythonでは、様々な画像処理を行うことが出来ます。

画像のリサイズ、リスケール、コントラストの調整、画像の色の変更、そして、チャンネルやピクセルなどの画像情報の抽出などにも使用することが出来ます。

また、画像中の物体を正確に識別・分類するためにも使用されます。

コンピュータビジョンや医療用画像の分野などでよく使用されます。

Pythonによる画像処理ライブラリの理解

Pythonは、最も人気のあるプログラミング言語であり、画像処理も得意としています。

Pythonには、OpenCVやPillowなど、画像処理を可能にするさまざまなライブラリが用意されています。

これらのライブラリはそれぞれ強みがあり、さまざまなタイプの画像処理操作を行うことができます。

OpenCVは、Pythonの画像処理ライブラリの中で最も人気があり、広く使われているライブラリの1つです。

豊富な機能があり、画像から何かを認識したり検出したりする場合はOpenCVを使います。

PillowもPythonの画像処理ライブラリとして人気があります。

Pillowは、リサイズやトリミング、回転、反転など基本的な処理を行うのに使用します。

その他にも、画像処理が出来るライブラリはいくつもあります。

画像処理ライブラリまとめ
  • OpenCV
  • Pillow
  • NumPy
  • scikit-image

Pythonによる画像処理入門

今回は、OpenCVを使って、様々な画像処理を実践してみたいと思います。

OpenCVを利用する理由
  • 最もよく使われているライブラリである
  • 商用利用も可能で、生産性を高めることが出来る
  • 共通して利用しやすい(Linux,Mac,Windows上で動作する・Python,Matlab,Java,JavaScriptなど様々な言語で使用可能)

画像の表示

import cv2
import matplotlib.pyplot as plt

# 使いたい画像のパスを指定する
image=cv2.imread('drive/My Drive/PythonCode/img/MRI.jpg', cv2.IMREAD_GRAYSCALE)

plt.imshow(image)

マトリクスサイズの確認

# 上記コードの続き
# マトリクスサイズの確認

height,width = image.shape
print('マトリクスサイズ 幅:',width,' 高さ:',height)

マトリクスサイズ 幅: 236  高さ: 218

画像のチャンネルの確認

import cv2

bgr = cv2.imread('drive/My Drive/PythonCode/img/lena-rgb.png',flags=cv2.IMREAD_UNCHANGED)

rgb = cv2.cvtColor(bgr, cv2.COLOR_BGR2RGB)

gray = cv2.imread('drive/My Drive/PythonCode/img/lena-gray.png',flags=cv2.IMREAD_UNCHANGED)

height, width ,channel = rgb.shape
print('高さ:',height, ' 幅:',width , ' チャンネル:',channel)

height, width = gray.shape
print('高さ:',height, ' 幅:',width)

高さ: 512 幅: 512 チャンネル: 3
高さ: 512 幅: 512

画像のリサイズ

import cv2

chest = cv2.imread('drive/My Drive/PythonCode/img/chestxray.png',cv2.IMREAD_GRAYSCALE)
print("オリジナルサイズ:",chest.shape)

# サイズを指定してリサイズ
chest256 = cv2.resize(src=chest,dsize=(512,512),interpolation=cv2.INTER_LINEAR)
print("ダウンサンプリング1:",chest256.shape)

# 係数でリサイズ(1/10にする例)
img300 = cv2.resize(chest ,dsize=None,fx=0.1,fy=0.1,interpolation=cv2.INTER_LINEAR)
print("ダウンサンプリング2:",img300.shape)

オリジナルサイズ: (3000, 3000)
ダウンサンプリング1: (512, 512)
ダウンサンプリング2: (300, 300)

ピクセル補間

import numpy as np
import matplotlib.pyplot as plt


chest32 = cv2.imread('drive/My Drive/PythonCode/img/chestx-ray32.png')
#chest32 = np.unit8(chest32)
print(chest32.dtype)


# インターニアレスト(補間なし)
internearest = cv2.resize(src=chest32,dsize=(128,128),interpolation=cv2.INTER_NEAREST)
plt.subplot(1,4,1)
plt.title("None")
plt.imshow(internearest)
# バイリニア
linear = cv2.resize(src=chest32,dsize=(128,128),interpolation=cv2.INTER_LINEAR)
plt.subplot(1,4,2)
plt.title("bilinear")
plt.imshow(linear)
# バイキュービック
cubic = cv2.resize(src=chest32,dsize=(128,128),interpolation=cv2.INTER_CUBIC)
plt.subplot(1,4,3)
plt.title("bicubic")
plt.imshow(cubic)
# ランチョス
lanczos = cv2.resize(src=chest32,dsize=(128,128),interpolation=cv2.INTER_LANCZOS4)
plt.subplot(1,4,4)
plt.title("lanczos")
plt.imshow(lanczos)
plt.tight_layout()
plt.show()

画像のコントラスト

gamma = 1.0

pixels = cv2.imread("drive/My Drive/PythonCode/img/MG.png", cv2.IMREAD_UNCHANGED)

amin=np.amin(pixels)
amax=np.amax(pixels)
scale = 256.0/(amax-amin+1) 
values = ((pixels-amin)*scale) + 0.5
values = np.clip(values,0,255)
img = np.uint8(values) 

def gamma_correction(gamma):
  lookUpTable = np.empty((1,256), np.uint8)
  for i in range(256):
      lookUpTable[0,i] = np.clip(pow(i / 255.0, 1./gamma) * 255.0, 0, 255)
  return lookUpTable

for i in [1,2,3,4,5,6,7]:
  gamma = round(i*0.1, 2)

  imgA = cv2.LUT(img, gamma_correction(gamma))
  plt.subplot(1,7,i)
  plt.imshow(imgA,cmap="gray")
  plt.title(str(gamma))
plt.show()

画像の2次元フーリエ変換

import cv2
import numpy as np
from numpy.fft import *
import matplotlib.pyplot as plt

H = 16
W = 16

chest = cv2.imread('drive/My Drive/PythonCode/img/chestx-ray.png',cv2.IMREAD_GRAYSCALE).astype(float)
# サイズが大きいので16×16へダウンサンプル
chest = cv2.resize(chest,(W,H),cv2.INTER_LANCZOS4)

plt.subplot(1,3,1)
plt.title("original")
plt.tight_layout()
plt.imshow(chest,cmap='gray')

# 2次元フーリエ変換
spectrum = np.fft.fft2(chest)
spectrum = np.fft.fftshift(spectrum)

real = np.real(spectrum)#実部を取得
imag = np.imag(spectrum)#虚部を取得

# 2次元フーリエ変換の結果(周波数空間画像)を表示
plt.subplot(1,3,2)
plt.tight_layout()
plt.imshow(real)
plt.title("real")
plt.subplot(1,3,3)
plt.tight_layout()
plt.imshow(imag)
plt.title("imaginary")

画像のフィルタ処理

import cv2
import numpy as np
from matplotlib import pyplot as plt

noise = cv2.imread('drive/My Drive/PythonCode/img/chestx-ray-noise.png',cv2.IMREAD_GRAYSCALE)
#ノイズ画像を確認
plt.subplot(1,2,1)
plt.imshow(noise,cmap='gray')
plt.tight_layout()
#メディアンフィルタによるフィルタリングを行う
#フィルタサイズを5×5で設定
median = cv2.medianBlur(noise, 5)
plt.subplot(1,2,2)
plt.imshow(median,cmap='gray')
plt.tight_layout()
from numpy.fft import * 

img = cv2.imread('/content/drive/My Drive/dataset/ChestXray256_uint8.png', cv2.IMREAD_GRAYSCALE).astype(float)

# いくつかのフィルタの重みを空間周波数化し、
# 対象画像の周波数空間へ乗じる

# 平均フィルタの重み
mean_filter = np.ones((3,3))
# ガウシアンフィルタ
x = cv2.getGaussianKernel(5,10)
gaussian = x*x.T
# エッジ検出フィルタ系
# sobel(x軸方向)
sobel_x= np.array([[-1, 0, 1],
                   [-2, 0, 2],
                   [-1, 0, 1]])
# sobel(y軸方向)
sobel_y= np.array([[-1,-2,-1],
                   [0, 0, 0],
                   [1, 2, 1]])
# laplacian
laplacian=np.array([[0, 1, 0],
                    [1,-4, 1],
                    [0, 1, 0]])
# 空間フィルタをリスト化
filters = [mean_filter, gaussian, laplacian, sobel_x, sobel_y]
# グラフ用にタイトルを順番にリスト化
filter_name = ['mean_filter', 'gaussian','laplacian', 'sobel_x', 'sobel_y']
# 各空間フィルタを2DFFTにより空間周波数フィルタへ
fft_filters = [np.fft.fft2(x) for x in filters]#空間周波数フィルタ化
fft_shift = [np.fft.fftshift(y) for y in fft_filters]#swap
#空間周波数フィルタをパワースペクトル画像へ
mag_spectrum = [np.log(np.abs(z)+1) for z in fft_shift] #float64
#空間周波数フィルタの行列を処理対象画像と同じサイズへリサイズ。
mag_spectrum = [cv2.resize(z,(256,256),cv2.INTER_LANCZOS4) for z in mag_spectrum]
# 処理対象画像の周波数空間画像を取得
fft_chest = fft2(img)
# 先に空間周波数フィルタを画像として表示
_, filters = plt.subplots(1, 5, figsize=(14, 14))
filters = filters.flatten()
for i in range(5):
  filters[i].imshow(mag_spectrum[i])
  filters[i].set_title(filter_name[i])
plt.show()
# フィルタリング処理結果の表示
_, filters = plt.subplots(1, 5, figsize=(14, 14))
filters = filters.flatten()
for i in range(5):
  # 空間フィルタとは異なり空間周波数画像全体に同じサイズのフィルタを乗じる
  # フィルタの重みが高いところは強調され低いところは抑制される
  f_fft_chest = np.copy(fft_chest) * mag_spectrum[i]
  invert = ifft2(f_fft_chest)
  filters[i].imshow(invert.real,cmap='gray')
plt.show() 

2値化処理

import cv2
import matplotlib.pyplot as plt

img = cv2.imread('drive/My Drive/PythonCode/img/chestx-ray.png', cv2.IMREAD_GRAYSCALE)
# cv2.inRange(src=入力画像ピクセル配列, lowerb=抽出する下限ピクセル値, upperb=上限ピクセル値)
# lowerb <= pixle value <= upperb内のピクセルを255に置き換える
mask = cv2.inRange(src=img, lowerb=90, upperb=250)
#比較表示
plt.subplot(1,2,1),plt.imshow(img,'gray')
plt.subplot(1,2,2),plt.imshow(mask,'gray')

画像の合成

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

# 画像のロード(src1,src2は同じデータタイプとする)
src1 = cv2.imread('drive/My Drive/PythonCode/img/brats.png',cv2.IMREAD_UNCHANGED)
src2 = cv2.imread('drive/My Drive/PythonCode/img/bratsmask.png',cv2.IMREAD_UNCHANGED)

alpha = 0.7 
beta = (1.0 - alpha) 
#合成:cv2.addWeighted(画像1, alpha, 画像2, beta, 積算する定数)
comp = cv2.addWeighted(src1, alpha, src2, beta, 0.0)

plt.subplot(1,3,1),plt.imshow(src1,'gray')
plt.subplot(1,3,2),plt.imshow(src2,'gray')
plt.subplot(1,3,3),plt.imshow(comp,'gray')

アフィン変換

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

img = cv2.imread('drive/My Drive/PythonCode/img/chestx-ray.png',cv2.IMREAD_UNCHANGED)
rows,cols = img.shape#512,512
#変換前の画像の任意の3点(基準点)を設定
pts1 = np.float32([[0,0],[511,0],[0,511],[511,511]])
#変換後に基準点が移動する位置を指定
pts2 = np.float32([[10,100],[300,50],[50,450],[480,450]])
#変換行列を求める
M = cv2.getPerspectiveTransform(pts1,pts2)
#変換実行:cv2.warpPerspective(入力,変換行列,(行,列))
trs = cv2.warpPerspective(img,M,(rows,cols))
#画像を確認
plt.subplot(1,3,1),plt.imshow(img,cmap="gray"),plt.title('Input')
plt.subplot(1,3,2),plt.imshow(trs,cmap="gray"),plt.title('Output')
#変換画像を元に戻して確認(画像の四隅が分かっている場合)
M = cv2.getPerspectiveTransform(pts2,pts1)
trs2 = cv2.warpPerspective(trs,M,(rows,cols))
plt.subplot(1,3,3),plt.imshow(trs2,cmap="gray"),plt.title('Invert')
plt.show()

まとめ

今回は、初心者向けにPythonによる画像処理入門!ライブラリから基本までを解説しました。

実際に、ライブラリや基礎から、最後はpythonでの実装まで解説しました。

ぜひ、今回紹介したもの以外にもたくさんあるのでチャレンジしてみてくださいね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次