Python OpenCV実戦:画像処理応用
はじめに
OpenCV (Open Source Computer Vision Vision Library) は、画像処理やコンピュータビジョンに関する機能を提供する、オープンソースのライブラリです。C++で書かれていますが、Python、Java、MATLABなど多くの言語に対応するAPIを提供しており、特にPythonとの組み合わせは、その記述の容易さから研究開発から実用アプリケーションまで幅広く利用されています。
このチュートリアルでは、PythonとOpenCVを用いた基本的な画像処理技術から、より実践的な応用例までを詳しく解説します。
1. OpenCVとPythonのセットアップ
まず、OpenCVをPython環境にインストールする必要があります。pipを使って簡単にインストールできます。
bash
pip install opencv-python numpy
2. 画像の読み込み、表示、保存
OpenCVで画像を扱う際の基本は、画像の読み込み、画面への表示、そして処理結果の保存です。
“`python
import cv2
画像の読み込み
(例: Deadpool/images/test.jpg を使用)
img = cv2.imread(‘Deadpool/images/test.jpg’)
if img is None:
print(“Error: Could not load image.”)
else:
# 画像の表示
cv2.imshow(‘Original Image’, img)
# キーが押されるまで待機
cv2.waitKey(0)
# ウィンドウを閉じる
cv2.destroyAllWindows()
# 画像の保存
cv2.imwrite('output_image.jpg', img)
print("Image saved as output_image.jpg")
“`
cv2.imread() は画像をNumPyの配列として読み込みます。OpenCVでは、色の表現がBGR (Blue, Green, Red) の順であることに注意してください。cv2.imshow() で画像を表示し、cv2.waitKey(0) は任意のキーが押されるまで待機します。cv2.destroyAllWindows() は開いているすべてのウィンドウを閉じます。
3. 基本的な画像操作
3.1 グレースケール変換
カラー画像をモノクロ(グレースケール)に変換することは、多くの画像処理の前処理として行われます。
python
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('Grayscale Image', gray_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
3.2 リサイズ
画像のサイズを変更します。拡大・縮小の両方が可能です。
“`python
幅を200ピクセルに、アスペクト比を維持してリサイズ
height, width = img.shape[:2]
ratio = 200 / width
dim = (200, int(height * ratio))
resized_img = cv2.resize(img, dim, interpolation=cv2.INTER_AREA)
cv2.imshow(‘Resized Image’, resized_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
“`
cv2.INTER_AREA は縮小に適しており、cv2.INTER_CUBIC や cv2.INTER_LINEAR は拡大に適しています。
3.3 切り抜き (クロッピング)
画像の一部を切り抜きます。NumPyの配列スライス操作を利用します。
“`python
例: 縦100pxから200px、横50pxから250pxを切り抜く
cropped_img = img[100:200, 50:250]
cv2.imshow(‘Cropped Image’, cropped_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
“`
4. 画像フィルタリング
画像フィルタリングは、ノイズ除去や特徴強調など、様々な目的で行われます。
4.1 平滑化(ブラー)
画像をぼかすことで、ノイズを低減したり、エッジを滑らかにしたりします。
-
ガウシアンブラー (Gaussian Blur): ガウス関数に基づいて重み付けされた平均を計算します。ノイズ除去に広く使われます。
python
blurred_img = cv2.GaussianBlur(img, (5, 5), 0) # カーネルサイズ5x5
cv2.imshow('Gaussian Blurred Image', blurred_img)
cv2.waitKey(0)
cv2.destroyAllWindows() -
メディアンブラー (Median Blur): 指定した領域内のピクセル値の中央値を使用します。特にソルト&ペッパーノイズに効果的です。
python
median_blurred_img = cv2.medianBlur(img, 5) # カーネルサイズ5x5
cv2.imshow('Median Blurred Image', median_blurred_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
4.2 エッジ検出
画像内の境界線(エッジ)を見つけ出す技術です。
-
Cannyエッジ検出: 複数のステップ(ノイズ除去、勾配計算、非最大値抑制、ヒステリシス閾値処理)を経てエッジを検出するため、非常に高品質なエッジを生成します。
python
edges = cv2.Canny(gray_img, 100, 200) # 閾値100と200
cv2.imshow('Canny Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()
5. 二値化 (Thresholding)
画像を白と黒の2色に変換する処理です。特定の対象領域を分離するのに使われます。
-
単純な二値化: ある固定値(閾値)を基準に二値化します。
python
ret, binary_img = cv2.threshold(gray_img, 127, 255, cv2.THRESH_BINARY)
cv2.imshow('Binary Image (Simple)', binary_img)
cv2.waitKey(0)
cv2.destroyAllWindows() -
適応的二値化 (Adaptive Thresholding): 画像の領域ごとに異なる閾値を適用します。明るさが不均一な画像に有効です。
python
adaptive_binary_img = cv2.adaptiveThreshold(gray_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, 11, 2)
cv2.imshow('Adaptive Binary Image', adaptive_binary_img)
cv2.waitKey(0)
cv2.destroyAllWindows() -
Otsuの二値化 (Otsu’s Binarization): 閾値を自動的に決定する手法です。
python
ret_otsu, otsu_binary_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
cv2.imshow('Otsu Binary Image', otsu_binary_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
6. モルフォロジー演算
画像の形状に基づいた処理で、ノイズ除去、穴埋め、オブジェクトの分離などに使用されます。
-
膨張 (Dilation): 白い領域を広げます。欠損した領域を結合したり、小さな穴を埋めたりするのに使われます。
python
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
dilated_img = cv2.dilate(binary_img, kernel, iterations=1)
cv2.imshow('Dilated Image', dilated_img)
cv2.waitKey(0)
cv2.destroyAllWindows() -
収縮 (Erosion): 白い領域を縮小します。小さなノイズを除去したり、オブジェクトを分離したりするのに使われます。
python
eroded_img = cv2.erode(binary_img, kernel, iterations=1)
cv2.imshow('Eroded Image', eroded_img)
cv2.waitKey(0)
cv2.destroyAllWindows() -
オープニング (Opening): 収縮の後に膨張を行うことで、小さなノイズ(白い点)を除去します。
python
opening_img = cv2.morphologyEx(binary_img, cv2.MORPH_OPEN, kernel)
cv2.imshow('Opening Image', opening_img)
cv2.waitKey(0)
cv2.destroyAllWindows() -
クロージング (Closing): 膨張の後に収縮を行うことで、小さな穴(黒い点)を埋めます。
python
closing_img = cv2.morphologyEx(binary_img, cv2.MORPH_CLOSE, kernel)
cv2.imshow('Closing Image', closing_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
7. 輪郭検出 (Contour Detection)
画像内の接続された曲線(オブジェクトの境界)を見つけます。
“`python
輪郭検出には二値画像が適しています。ここではOtsuの二値化結果を使用します。
findContoursは画像を破壊するため、コピーを渡します。
contours, hierarchy = cv2.findContours(otsu_binary_img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
元画像に輪郭を描画
contour_img = img.copy()
cv2.drawContours(contour_img, contours, -1, (0, 255, 0), 2) # すべての輪郭を緑色で描画
cv2.imshow(‘Contours’, contour_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
print(f”Detected {len(contours)} contours.”)
各輪郭の情報を取得 (例: 面積、外接矩形)
for i, cnt in enumerate(contours):
area = cv2.contourArea(cnt)
x, y, w, h = cv2.boundingRect(cnt)
print(f”Contour {i}: Area={area}, Bounding Box=(x:{x}, y:{y}, w:{w}, h:{h})”)
# 外接矩形を描画
cv2.rectangle(contour_img, (x, y), (x+w, y+h), (255, 0, 0), 2)
cv2.imshow(‘Contours with Bounding Boxes’, contour_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
“`
8. オブジェクト検出 (簡易版)
8.1 テンプレートマッチング
画像内に特定のテンプレート画像がどこにあるかを検出する手法です。
“`python
テンプレート画像 (例: Deadpool/images/test.jpgの一部を切り抜いて作成)
実際の使用では、検出したいオブジェクトの画像を別途用意します。
ここでは例として、元の画像の中心部分をテンプレートとします。
template = img[120:180, 100:160] # 適当な領域をテンプレートとする
if template.size == 0:
print(“Error: Template image is empty.”)
else:
w, h = template.shape[1], template.shape[0]
# テンプレートマッチングを実行
res = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)
# マッチング結果から最大値の座標を取得
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
# 最高のマッチング位置
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
# 結果を元画像に描画
result_img = img.copy()
cv2.rectangle(result_img, top_left, bottom_right, (0, 0, 255), 2)
cv2.imshow('Template Matching Result', result_img)
cv2.imshow('Template', template) # テンプレート画像も表示
cv2.waitKey(0)
cv2.destroyAllWindows()
“`
8.2 顔検出 (Haar Cascade)
OpenCVは、事前に学習されたカスケード分類器を用いて、顔などの特定のオブジェクトを検出できます。
“`python
Haar Cascade分類器の読み込み (XMLファイルが必要)
通常はOpenCVのインストールディレクトリに含まれています。
またはGitHubなどからダウンロードしてください。
例: haarcascade_frontalface_default.xml
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + ‘haarcascade_frontalface_default.xml’)
if face_cascade.empty():
print(“Error: Could not load face cascade classifier.”)
else:
# グレースケール画像で検出
faces = face_cascade.detectMultiScale(gray_img, 1.1, 4)
# 検出された顔に矩形を描画
face_detected_img = img.copy()
for (x, y, w, h) in faces:
cv2.rectangle(face_detected_img, (x, y), (x+w, y+h), (255, 0, 0), 2)
cv2.imshow('Face Detection', face_detected_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
“`
9. まとめ
このチュートリアルでは、Python OpenCVを使った基本的な画像処理から、エッジ検出、二値化、モルフォロジー演算、輪郭検出、そして簡単なオブジェクト検出までを網羅しました。OpenCVはこれ以外にも、特徴点検出、画像認識、機械学習との統合、ビデオ処理など、非常に多岐にわたる機能を提供しています。
これらの基礎を理解することで、より複雑なコンピュータビジョンシステムを構築するための強力な基盤を築くことができます。ぜひ、様々な画像を試したり、異なるパラメータを調整したりして、OpenCVの奥深い世界を探求してみてください。