OpenCVの特徴的な機能
【概要】 OpenCVには、色空間変換、局所的コントラスト強調、動体追跡、幾何学的変換、形状解析、多重解像度解析、パターン検出、適応的二値化、セグメンテーション等の多彩な機能がある。これらの機能は、照明変動への対応、動き検出、形状認識など、実用的な画像処理に有効である。
【目次】
- Python のインストールと必要なPythonライブラリのインストール
- 色空間変換
- CLAHE
- オプティカルフロー
- アフィン変換
- モルフォロジー演算
- 画像ピラミッド
- テンプレートマッチング
- 適応的閾値処理
- GrabCut画像セグメンテーション
- カラー画像表示
- パソコンカメラ表示
【サイト内の関連情報】
ドクセルの URL: https://www.docswell.com/s/6674398749/51X845-2022-02-18-085434
Python のインストールと必要なPythonライブラリのインストール(Windows上)
- Python 3.12 のインストール
インストール済みの場合は実行不要。
管理者権限でコマンドプロンプトを起動(手順:Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)し、以下を実行する。管理者権限は、wingetの--scope machineオプションでシステム全体にソフトウェアをインストールするために必要である。
REM Python をシステム領域にインストール winget install --scope machine --id Python.Python.3.12 -e --silent --accept-source-agreements --accept-package-agreements REM パス長制限の解除 reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f reg query "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled REM Python のパス設定 set "PYTHON_PATH=C:\Program Files\Python312" set "PYTHON_SCRIPTS_PATH=C:\Program Files\Python312\Scripts" echo "%PATH%" | find /i "%PYTHON_PATH%" >nul if errorlevel 1 setx PATH "%PATH%;%PYTHON_PATH%" /M >nul echo "%PATH%" | find /i "%PYTHON_SCRIPTS_PATH%" >nul if errorlevel 1 setx PATH "%PATH%;%PYTHON_SCRIPTS_PATH%" /M >nul【関連する外部ページ】
Python の公式ページ: https://www.python.org/
- AI エディタ Windsurf のインストール
Pythonプログラムの編集・実行には、AI エディタの利用を推奨する。ここでは、Windsurfのインストールを説明する。
管理者権限でコマンドプロンプトを起動(手順:Windowsキーまたはスタートメニュー > cmd と入力 > 右クリック > 「管理者として実行」)し、以下を実行して、Windsurfをシステム全体にインストールする。管理者権限は、wingetの--scope machineオプションでシステム全体にソフトウェアをインストールするために必要となる。
winget install --scope machine --id Codeium.Windsurf -e --silent --accept-source-agreements --accept-package-agreements【関連する外部ページ】
Windsurf の公式ページ: https://windsurf.com/
- 必要なPythonライブラリのインストール
【関連する外部ページ】
【サイト内の関連ページ】
色空間変換
概要
色空間変換とは、デジタル画像の色表現を異なる色空間へと変換する画像処理である。BGRからHSVへの変換を行うことで、色相(Hue)、彩度(Saturation)、明度(Value)を独立させることができる。これにより、照明条件が変化する環境下での色検出が容易になる。
使用されている技術
- HSV色空間:色相・彩度・明度の3要素で色を表現する。人の色知覚に近い表現形式である。
- L*a*b*色空間:L*が輝度、a*とb*が色度を表す。色度成分は照明変動の影響を受けにくい。
- cv2.cvtColor:OpenCVの色空間変換関数である。
ソースコード: BGRからHSV色空間への変換
BGRからHSV色空間への変換を行うプログラムである。
import cv2
import urllib.request
# 画像のダウンロード
url = "https://raw.githubusercontent.com/opencv/opencv/master/samples/data/fruits.jpg"
urllib.request.urlretrieve(url, "fruits.jpg")
# 色空間変換
img = cv2.imread("fruits.jpg")
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
cv2.imshow('HSV', hsv)
cv2.waitKey(0)
cv2.destroyAllWindows()
ソースコード: BGRからL*a*b*色空間への変換
BGRからL*a*b*色空間への変換を行うプログラムである。
import cv2
import urllib.request
# 画像のダウンロード
url = "https://raw.githubusercontent.com/opencv/opencv/master/samples/data/fruits.jpg"
urllib.request.urlretrieve(url, "fruits.jpg")
# 色空間変換
img = cv2.imread("fruits.jpg")
lab = cv2.cvtColor(img, cv2.COLOR_BGR2Lab)
cv2.imshow('L*a*b*', lab)
cv2.waitKey(0)
cv2.destroyAllWindows()
CLAHE
概要
CLAHE(Contrast Limited Adaptive Histogram Equalization、適応的ヒストグラム平衡化)は、画像の局所領域ごとにコントラストを強調する手法である。通常のヒストグラム平衡化と異なり、局所領域ごとに処理を行うため、画像全体の視認性を均一に向上させることができる。
使用されている技術
- cv2.createCLAHE:CLAHEオブジェクトを生成する関数である。
- clipLimit:コントラスト強調の上限を制御するパラメータである。
- tileGridSize:局所領域のサイズを指定するパラメータである。
ソースコード: CLAHEによるコントラスト強調(グレースケール画像)
グレースケール画像に対してCLAHEを適用するプログラムである。
import cv2
import urllib.request
url = "https://raw.githubusercontent.com/opencv/opencv/master/samples/data/fruits.jpg"
urllib.request.urlretrieve(url, "fruits.jpg")
img = cv2.imread("fruits.jpg", 0)
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
cl1 = clahe.apply(img)
cv2.imshow('CLAHE', cl1)
cv2.waitKey(0)
cv2.destroyAllWindows()
ソースコード: CLAHEによるコントラスト強調(カラー画像)
カラー画像に対してCLAHEを適用するプログラムである。L*a*b*色空間に変換し、L*成分のみにCLAHEを適用することで、色情報を保持したままコントラストを強調する。
import cv2
import urllib.request
# 画像のダウンロード
url = "https://raw.githubusercontent.com/opencv/opencv/master/samples/data/fruits.jpg"
urllib.request.urlretrieve(url, "fruits.jpg")
# 色空間変換
img = cv2.imread("fruits.jpg")
lab = cv2.cvtColor(img, cv2.COLOR_BGR2Lab)
# L*a*b*の各チャネルを分離
l, a, b = cv2.split(lab)
# L*成分にCLAHEを適用
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
cl1 = clahe.apply(l)
# チャネルを結合
lab_clahe = cv2.merge([cl1, a, b])
# BGRに戻す
bgr = cv2.cvtColor(lab_clahe, cv2.COLOR_Lab2BGR)
cv2.imshow('Result', bgr)
cv2.waitKey(0)
cv2.destroyAllWindows()
オプティカルフロー
概要
オプティカルフローは、連続する画像フレーム間の各画素の動きをベクトルとして検出する技術である。動体追跡やモーション解析に用いられる。
使用されている技術
- Farneback法:全画素の動きを計算するDense Optical Flowアルゴリズムである。
- cv2.calcOpticalFlowFarneback:Farneback法によるオプティカルフロー計算関数である。
ソースコード(2つの画像に関する処理)
2枚の連続画像間の動きを検出し、HSV色空間で可視化するプログラムである。動きの方向を色相、大きさを明度で表現する。
import cv2
import numpy as np
import urllib.request
url1 = "https://raw.githubusercontent.com/opencv/opencv/master/samples/data/rubberwhale1.png"
url2 = "https://raw.githubusercontent.com/opencv/opencv/master/samples/data/rubberwhale2.png"
urllib.request.urlretrieve(url1, "frame1.png")
urllib.request.urlretrieve(url2, "frame2.png")
prev_img = cv2.imread('frame1.png', cv2.IMREAD_GRAYSCALE)
next_img = cv2.imread('frame2.png', cv2.IMREAD_GRAYSCALE)
# オプティカルフローの計算
flow = cv2.calcOpticalFlowFarneback(prev_img, next_img, None, 0.5, 3, 15, 3, 5, 1.2, 0)
# フロー可視化用のHSV画像を生成
hsv = np.zeros((prev_img.shape[0], prev_img.shape[1], 3), dtype=np.uint8)
hsv[..., 1] = 255
# フローの大きさと角度を計算
mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])
hsv[..., 0] = ang * 180 / np.pi / 2
hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
# HSVからBGRに変換して表示
bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
# 結果を表示
cv2.imshow('Optical Flow', bgr)
cv2.waitKey(0)
cv2.destroyAllWindows()
ソースコード(動画に関する処理)
動画またはWebカメラからオプティカルフローを計算するプログラムである。引数により入力ソースを切り替えることができる。
- 引数なし:サンプル動画を使用
- 数字を指定:指定番号のWebカメラを使用
- ファイル名を指定:指定動画ファイルを使用
import cv2
import numpy as np
import urllib.request
import sys
import os
def print_usage():
print("Usage:")
print(" No argument: Download and use sample video (vtest.avi)")
print(" Number (0,1,...): Use webcam with specified device number")
print(" Filename: Use specified video file")
# 入力ソースの決定
if len(sys.argv) == 1:
# 引数なし: サンプル動画をダウンロードして使用
print("Using sample video (vtest.avi)")
video_url = "https://github.com/opencv/opencv/raw/master/samples/data/vtest.avi"
urllib.request.urlretrieve(video_url, "vtest.avi")
cap = cv2.VideoCapture("vtest.avi")
elif sys.argv[1].isdigit():
# 数字: WebCamを使用
device_num = int(sys.argv[1])
print(f"Using webcam device {device_num}")
cap = cv2.VideoCapture(device_num)
else:
# その他: ファイル名として解釈
filename = sys.argv[1]
if not os.path.exists(filename):
print(f"Error: File '{filename}' not found")
print_usage()
exit()
print(f"Using video file: {filename}")
cap = cv2.VideoCapture(filename)
# 最初のフレームの読み込みとグレースケール変換
ret, prev_frame = cap.read()
if not ret:
print("Error opening video source")
print_usage()
exit()
prev_gray = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)
# HSV画像の準備
hsv = np.zeros_like(prev_frame)
hsv[..., 1] = 255
while True:
# 次のフレームの読み込み
ret, next_frame = cap.read()
if not ret:
break
next_gray = cv2.cvtColor(next_frame, cv2.COLOR_BGR2GRAY)
# オプティカルフローの計算
flow = cv2.calcOpticalFlowFarneback(prev_gray, next_gray, None, 0.5, 3, 15, 3, 5, 1.2, 0)
# フローの大きさと角度を計算
mag, ang = cv2.cartToPolar(flow[..., 0], flow[..., 1])
hsv[..., 0] = ang * 180 / np.pi / 2
hsv[..., 2] = cv2.normalize(mag, None, 0, 255, cv2.NORM_MINMAX)
# HSVからBGRに変換して表示
bgr = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
cv2.imshow('Optical Flow', bgr)
# 'q'キーを押すと終了
if cv2.waitKey(30) & 0xFF == ord('q'):
break
# 現在のフレームを次のループのprev_frameとして設定
prev_gray = next_gray
cap.release()
cv2.destroyAllWindows()
アフィン変換
概要
アフィン変換は、画像に対して平行移動、回転、拡大縮小、せん断などの幾何学的変換を行う手法である。変換後も平行線は平行線として保存される。
使用されている技術
- アフィン変換行列:2×3の行列で幾何学的変換を表現する。
- cv2.getAffineTransform:3組の対応点からアフィン変換行列を計算する関数である。
- cv2.warpAffine:アフィン変換行列を用いて画像を変換する関数である。
ソースコード
3組の対応点を指定してアフィン変換を行うプログラムである。
import cv2
import numpy as np
import urllib.request
url = "https://raw.githubusercontent.com/opencv/opencv/master/samples/data/fruits.jpg"
urllib.request.urlretrieve(url, "fruits.jpg")
img = cv2.imread("fruits.jpg")
rows, cols, ch = img.shape
# 変換元の点を画像サイズ内に制限
pts1 = np.float32([[min(50, cols-1), min(50, rows-1)],
[min(200, cols-1), min(50, rows-1)],
[min(50, cols-1), min(200, rows-1)]])
# 変換先の点を画像サイズ内に制限
pts2 = np.float32([[min(10, cols-1), min(100, rows-1)],
[min(200, cols-1), min(50, rows-1)],
[min(100, cols-1), min(250, rows-1)]])
M = cv2.getAffineTransform(pts1, pts2)
dst = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('Affine Transform', dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
モルフォロジー演算
概要
モルフォロジー演算は、画像の形状に基づく処理を行う演算である。主に二値画像に対して適用され、ノイズ除去や形状の整形に用いられる。基本演算として膨張(dilation)と収縮(erosion)がある。
使用されている技術
- 収縮(erosion):構造要素内の最小値を出力する演算である。物体を縮小させ、小さなノイズを除去する。
- 膨張(dilation):構造要素内の最大値を出力する演算である。物体を拡大させ、穴を埋める。
- 構造要素(kernel):演算の処理範囲を定義する行列である。
ソースコード
収縮処理を行うプログラムである。
import cv2
import numpy as np
import urllib.request
url = "https://raw.githubusercontent.com/opencv/opencv/master/samples/data/fruits.jpg"
urllib.request.urlretrieve(url, "fruits.jpg")
img = cv2.imread("fruits.jpg", 0)
# kernelサイズを画像サイズに応じて設定
kernel_size = max(3, min(5, img.shape[0]//100))
kernel = np.ones((kernel_size, kernel_size), np.uint8)
erosion = cv2.erode(img, kernel, iterations=1)
cv2.imshow('Erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
画像ピラミッド
概要
画像ピラミッドは、同一画像を異なる解像度で階層的に表現する手法である。物体検出やテンプレートマッチングにおいて、スケールの異なる対象を効率的に探索するために用いられる。
使用されている技術
- cv2.pyrDown:画像の解像度を半分に縮小する関数である。
- cv2.pyrUp:画像の解像度を2倍に拡大する関数である。
ソースコード
画像の解像度を縮小・拡大するプログラムである。
import cv2
import urllib.request
url = "https://raw.githubusercontent.com/opencv/opencv/master/samples/data/fruits.jpg"
urllib.request.urlretrieve(url, "fruits.jpg")
img = cv2.imread("fruits.jpg")
lower = cv2.pyrDown(img)
higher = cv2.pyrUp(lower)
cv2.imshow('Lower Resolution', lower)
cv2.imshow('Higher Resolution', higher)
cv2.waitKey(0)
cv2.destroyAllWindows()
テンプレートマッチング
概要
テンプレートマッチングは、画像内から指定したテンプレート画像と類似する領域を検出する手法である。
使用されている技術
- cv2.matchTemplate:テンプレートマッチングを実行する関数である。
- TM_CCOEFF_NORMED:正規化相互相関係数による類似度計算手法である。-1から1の値をとり、1に近いほど類似度が高い。
ソースコード
テンプレートマッチングにより類似領域を検出するプログラムである。類似度0.8以上の領域を緑色矩形、テンプレート位置を赤色矩形で表示する。
import cv2
import numpy as np
import urllib.request
url = "https://raw.githubusercontent.com/opencv/opencv/master/samples/data/smarties.png"
urllib.request.urlretrieve(url, "smarties.png")
img = cv2.imread("smarties.png", cv2.IMREAD_COLOR) # カラー画像として読み込み
# テンプレート領域
template_x, template_y = 350, 50
template_w, template_h = 60, 60
template = img[template_y:template_y+template_h, template_x:template_x+template_w].copy() # copyで切り出し
# 表示用画像のコピー作成
img_display = img.copy()
# テンプレートマッチング
result = cv2.matchTemplate(img, template, cv2.TM_CCOEFF_NORMED)
# スコア0.8以上の位置を緑色で表示
locations = np.where(result >= 0.8)
for y, x in zip(*locations):
_ = cv2.rectangle(img_display, (x, y), (x+template_w, y+template_h), (0,255,0), 2)
# テンプレート位置を赤色で表示
_ = cv2.rectangle(img_display, (template_x,template_y), (template_x+template_w,template_y+template_h), (0,0,255), 2)
cv2.imshow('Template Matching', img_display)
cv2.waitKey(0)
cv2.destroyAllWindows()
適応的閾値処理
概要
適応的閾値処理は、画像の局所領域ごとに閾値を計算して二値化を行う手法である。照明が不均一な画像に対しても適切な二値化が可能である。
使用されている技術
- cv2.adaptiveThreshold:適応的閾値処理を実行する関数である。
- ADAPTIVE_THRESH_GAUSSIAN_C:ガウシアン重み付けにより局所領域の閾値を計算する手法である。
- blockSize:閾値計算に用いる局所領域のサイズである。奇数を指定する。
ソースコード
適応的閾値処理により二値化を行うプログラムである。
import cv2
import urllib.request
url = "https://raw.githubusercontent.com/opencv/opencv/master/samples/data/sudoku.png"
urllib.request.urlretrieve(url, "sudoku.png")
img = cv2.imread("sudoku.png", 0)
# 画像サイズに応じたブロックサイズの設定
blockSize = max(3, min(img.shape[0], img.shape[1]) // 50)
if blockSize % 2 == 0:
blockSize += 1 # ブロックサイズは奇数である必要がある
thresh = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY, blockSize, 2)
cv2.imshow('Adaptive Threshold', thresh)
cv2.waitKey(0)
cv2.destroyAllWindows()
GrabCut画像セグメンテーション
概要
GrabCutは、画像の前景と背景を分離するセグメンテーションアルゴリズムである。ユーザが指定した矩形領域を基に、グラフカットによる最適化で前景を抽出する。
使用されている技術
- cv2.grabCut:GrabCutアルゴリズムを実行する関数である。
- GC_INIT_WITH_RECT:矩形領域を初期値として前景抽出を行うモードである。
ソースコード
矩形領域を指定して前景を抽出するプログラムである。
import cv2
import numpy as np
import urllib.request
url = "https://raw.githubusercontent.com/opencv/opencv/master/samples/data/messi5.jpg"
urllib.request.urlretrieve(url, "messi5.jpg")
img = cv2.imread("messi5.jpg")
mask = np.zeros(img.shape[:2], np.uint8)
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)
rect = (50, 50, 450, 290)
cv2.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
img = img * mask2[:, :, np.newaxis]
cv2.imshow('GrabCut', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
カラー画像表示
概要
カラー画像を読み込み、表示用に適切なサイズへ縮小するプログラムである。画像幅が1024ピクセルを超える場合に縮小処理を行う。
使用されている技術
- cv2.resize:画像のサイズを変更する関数である。
- INTER_AREA:縮小に適した補間手法である。面積平均により画質劣化を抑える。
ソースコード
画像を読み込み、必要に応じて縮小して表示するプログラムである。
import cv2
import urllib.request
# 画像のダウンロード
url = "https://raw.githubusercontent.com/opencv/opencv/master/samples/data/fruits.jpg"
urllib.request.urlretrieve(url, "fruits.jpg")
# 画像表示
img = cv2.imread("fruits.jpg")
height, width = img.shape[:2]
# 幅を1024以下にするための1/2または1/4倍リサイズ
if width > 1024:
scale_factor = 0.5 if width / 2 > 1024 else 0.25
new_width = int(width * scale_factor)
new_height = int(height * scale_factor)
resized_img = cv2.resize(img, (new_width, new_height),
interpolation=cv2.INTER_AREA)
else:
resized_img = img
cv2.imshow('Resized Image', resized_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
パソコンカメラ表示
概要
パソコンのカメラから映像を取得し、表示用に適切なサイズへ縮小するプログラムである。
使用されている技術
- cv2.VideoCapture:カメラや動画ファイルから映像を取得するクラスである。
- INTER_AREA:縮小に適した補間手法である。
ソースコード
カメラ映像を取得し、縮小して表示するプログラムである。qキーで終了する。
import cv2
# カメラのキャプチャ
cap = cv2.VideoCapture(0)
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
height, width = frame.shape[:2]
# 幅を1024以下にするための1/2または1/4倍リサイズ
if width > 1024:
scale_factor = 0.5 if width / 2 > 1024 else 0.25
new_width = int(width * scale_factor)
new_height = int(height * scale_factor)
resized_frame = cv2.resize(frame, (new_width, new_height),
interpolation=cv2.INTER_AREA)
else:
resized_frame = frame
cv2.imshow('Webcam', resized_frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()