parent
355f23f410
commit
cfe0c1a7dd
19 changed files with 507 additions and 157 deletions
@ -0,0 +1,97 @@ |
|||||||
|
# 実験課題10 |
||||||
|
# 3.10 背景差分法(ラベリング・ノイズ処理含む) |
||||||
|
|
||||||
|
import cv2 |
||||||
|
import numpy as np |
||||||
|
|
||||||
|
# Webカメラの初期化 |
||||||
|
cap = cv2.VideoCapture(0) |
||||||
|
|
||||||
|
if not cap.isOpened(): |
||||||
|
print("カメラを開けませんでした。") |
||||||
|
else: |
||||||
|
print("背景差分法を開始します。") |
||||||
|
print("'q': 終了, 'r': 背景画像を現フレームで更新") |
||||||
|
|
||||||
|
# 最初のフレームを背景画像として取得するための準備 |
||||||
|
bg_gray = None |
||||||
|
|
||||||
|
while True: |
||||||
|
ret, frame = cap.read() |
||||||
|
if not ret: |
||||||
|
print("フレームを取得できませんでした。") |
||||||
|
break |
||||||
|
|
||||||
|
# 差分計算を安定させるため、現フレームをグレースケール化 |
||||||
|
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) |
||||||
|
|
||||||
|
# ガウシアンブラ(平滑化)を適用して、カメラ特有の細かいノイズを低減 |
||||||
|
gray = cv2.GaussianBlur(gray, (21, 21), 0) |
||||||
|
|
||||||
|
# 起動直後、または 'r' キーが押された場合に背景画像を保存・更新する |
||||||
|
if bg_gray is None: |
||||||
|
bg_gray = gray |
||||||
|
print("背景画像を保存しました。カメラの前から離れてください。") |
||||||
|
continue |
||||||
|
|
||||||
|
# --- 3.101 背景差分法:背景画像と現フレームの絶対差分を計算 --- |
||||||
|
frame_diff = cv2.absdiff(bg_gray, gray) |
||||||
|
|
||||||
|
# 差分画像を2値化して、動いている領域(前景)を白(255)にする |
||||||
|
# 閾値は環境に合わせて調整(ここでは例として 25) |
||||||
|
_, thresh = cv2.threshold(frame_diff, 25, 255, cv2.THRESH_BINARY) |
||||||
|
|
||||||
|
# --- 3.102 ノイズ処理(モルフォロジー演算:オープニング) --- |
||||||
|
# 3.7で学んだ手法を使い、背景に散らばる小さなチラツキノイズを消去 |
||||||
|
kernel = np.ones((5, 5), np.uint8) |
||||||
|
thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel) |
||||||
|
# 領域内の穴を埋めて結合を強める(クロージング) |
||||||
|
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel) |
||||||
|
|
||||||
|
# --- 3.102 ラベリング処理 --- |
||||||
|
# 2値化画像から、繋がっている白い領域(動体)を検出してラベルを貼る |
||||||
|
# nlabels: ラベルの総数(背景含む) |
||||||
|
# labels: 各画素にラベル番号(0, 1, 2...)が割り当てられた画像 |
||||||
|
# stats: 各領域の矩形座標や面積[x, y, w, h, area]の行列 |
||||||
|
# centroids: 各領域の中心座標 |
||||||
|
nlabels, labels, stats, centroids = cv2.connectedComponentsWithStats(thresh) |
||||||
|
|
||||||
|
# 各ラベルごとに色分けするためのランダムな色マップを作成(背景の0は黒にする) |
||||||
|
# 乱数のシードを固定して、フレーム間で色が激しく変わるのを防ぐ |
||||||
|
np.random.seed(42) |
||||||
|
colors = np.random.randint(0, 255, (nlabels, 3), dtype=np.uint8) |
||||||
|
colors[0] = [0, 0, 0] # ラベル0(背景)は黒に固定 |
||||||
|
|
||||||
|
# 画素ごとのラベル番号に対応する色を割り当てて、色分け画像(ラベリング画像)を作成 |
||||||
|
labeled_img = colors[labels] |
||||||
|
|
||||||
|
# 動体領域に矩形(枠線)を描画する |
||||||
|
for i in range(1, nlabels): # 0は背景なので1からループ |
||||||
|
x = stats[i, cv2.CC_STAT_LEFT] |
||||||
|
y = stats[i, cv2.CC_STAT_TOP] |
||||||
|
w = stats[i, cv2.CC_STAT_WIDTH] |
||||||
|
h = stats[i, cv2.CC_STAT_HEIGHT] |
||||||
|
area = stats[i, cv2.CC_STAT_AREA] |
||||||
|
|
||||||
|
# 面積が小さすぎる領域(微小なノイズの残り)は無視する |
||||||
|
if area > 500: |
||||||
|
# 動体を緑色の矩形で囲む |
||||||
|
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) |
||||||
|
# ラベル番号を画像上に描画 |
||||||
|
cv2.putText(frame, f"ID:{i}", (x, y - 10), |
||||||
|
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) |
||||||
|
|
||||||
|
# --- 結果の表示 --- |
||||||
|
cv2.imshow('Original Frame (Motion Detection)', frame) |
||||||
|
cv2.imshow('Foreground Mask (Thresh)', thresh) |
||||||
|
cv2.imshow('Labeled Components', labeled_img) |
||||||
|
|
||||||
|
# キー入力の受付 |
||||||
|
key = cv2.waitKey(1) & 0xFF |
||||||
|
if key == ord('q'): |
||||||
|
break |
||||||
|
elif key == ord('r'): |
||||||
|
bg_gray = None # 次のループで背景が再キャプチャされる |
||||||
|
|
||||||
|
cap.release() |
||||||
|
cv2.destroyAllWindows() |
||||||
@ -0,0 +1,87 @@ |
|||||||
|
# 実験課題11 |
||||||
|
# 3.11 トラッキング(任意) |
||||||
|
|
||||||
|
import cv2 |
||||||
|
|
||||||
|
# Webカメラの初期化 |
||||||
|
cap = cv2.VideoCapture(0) |
||||||
|
|
||||||
|
if not cap.isOpened(): |
||||||
|
print("カメラを開けませんでした。") |
||||||
|
else: |
||||||
|
print("トラッキングテストを開始します。") |
||||||
|
|
||||||
|
# 最初の1フレームを読み込む |
||||||
|
ret, frame = cap.read() |
||||||
|
|
||||||
|
if not ret: |
||||||
|
print("フレームを取得できませんでした。") |
||||||
|
else: |
||||||
|
# --- 追跡対象の選択(ROI) --- |
||||||
|
print("【操作方法】") |
||||||
|
print("1. 追跡したい物体をマウスでドラッグして四角く囲んでください。") |
||||||
|
print("2. 囲んだら Enter または Space キーを押して決定します。") |
||||||
|
print("3. やり直す場合は 'c' キーを押してください。") |
||||||
|
|
||||||
|
# ユーザーに追跡対象をマウスで選択させるウィンドウを表示 |
||||||
|
# bbox には選択された領域の (x, y, w, h) が格納される |
||||||
|
while True: |
||||||
|
# ユーザーに追跡対象をマウスで選択させる |
||||||
|
bbox = cv2.selectROI("Tracking", frame, fromCenter=False, showCrosshair=True) |
||||||
|
|
||||||
|
# 幅(bbox[2]) または 高さ(bbox[3]) が 0 の場合 |
||||||
|
# ('c'キーが押された、または未選択のままEnterが押された場合) |
||||||
|
if bbox[2] == 0 or bbox[3] == 0: |
||||||
|
print("領域がリセットされました。やり直します。") |
||||||
|
print("もう一度マウスをドラッグして対象を囲み、Enterキーを押してください。") |
||||||
|
# continueによってループの先頭に戻り、再度selectROIを実行する |
||||||
|
continue |
||||||
|
else: |
||||||
|
# 正しく領域が選択されたらループを抜けてトラッキング処理へ進む |
||||||
|
print("領域が確定しました。トラッキングを開始します。") |
||||||
|
break |
||||||
|
|
||||||
|
# --- トラッカーの生成と初期化 --- |
||||||
|
# 拡張モジュールに含まれる高精度なトラッカー「CSRT」を生成 |
||||||
|
# ※OpenCVのバージョンによっては legacy に分類されるため、try-exceptで安全に呼び出す |
||||||
|
try: |
||||||
|
tracker = cv2.TrackerCSRT_create() |
||||||
|
except AttributeError: |
||||||
|
tracker = cv2.legacy.TrackerCSRT_create() |
||||||
|
|
||||||
|
# 最初のフレームと、選択した領域(bbox)を渡してトラッカーに学習(初期化)させる |
||||||
|
tracker.init(frame, bbox) |
||||||
|
|
||||||
|
print("追跡中... 終了するには 'q' キーを押してください。") |
||||||
|
|
||||||
|
# --- トラッキングのループ処理 --- |
||||||
|
while True: |
||||||
|
ret, frame = cap.read() |
||||||
|
if not ret: |
||||||
|
break |
||||||
|
|
||||||
|
# 新しいフレームをトラッカーに渡し、対象がどこに移動したか推測させる |
||||||
|
# success: 追跡成功(True) / 失敗(False) |
||||||
|
# bbox: 新しい座標とサイズ (x, y, w, h) |
||||||
|
success, bbox = tracker.update(frame) |
||||||
|
|
||||||
|
if success: |
||||||
|
# 追跡成功時:新しい座標を整数に変換して青い枠線を描画 |
||||||
|
p1 = (int(bbox[0]), int(bbox[1])) |
||||||
|
p2 = (int(bbox[0] + bbox[2]), int(bbox[1] + bbox[3])) |
||||||
|
cv2.rectangle(frame, p1, p2, (255, 0, 0), 2, 1) |
||||||
|
cv2.putText(frame, "Tracking", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 0, 0), 2) |
||||||
|
else: |
||||||
|
# 追跡失敗時(画面外に出た、何かの裏に完全に隠れた等):赤い警告文を表示 |
||||||
|
cv2.putText(frame, "Lost", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) |
||||||
|
|
||||||
|
# 結果の表示 |
||||||
|
cv2.imshow("Tracking", frame) |
||||||
|
|
||||||
|
# 'q' キーで終了 |
||||||
|
if cv2.waitKey(1) & 0xFF == ord('q'): |
||||||
|
break |
||||||
|
|
||||||
|
# 終了処理 |
||||||
|
cap.release() |
||||||
|
cv2.destroyAllWindows() |
||||||
@ -0,0 +1,41 @@ |
|||||||
|
# 実験課題1 |
||||||
|
# 3.1 画像サイズ変換・画像の回転 |
||||||
|
|
||||||
|
import cv2 |
||||||
|
|
||||||
|
# 画像の読み込み(任意のカラー画像を用意し、ファイル名を指定してください) |
||||||
|
image_path = 'sample.jpg' |
||||||
|
img = cv2.imread(image_path) |
||||||
|
|
||||||
|
if img is None: |
||||||
|
print("画像を読み込めませんでした。ファイルパスを確認してください。") |
||||||
|
else: |
||||||
|
# --- 画像サイズ変換 --- |
||||||
|
# 元画像の高さと幅を取得 |
||||||
|
height, width = img.shape[:2] |
||||||
|
|
||||||
|
# 縦横を1/2のサイズに計算 |
||||||
|
new_width = width // 2 |
||||||
|
new_height = height // 2 |
||||||
|
|
||||||
|
# 画像のサイズを変更 |
||||||
|
resized_img = cv2.resize(img, (new_width, new_height)) |
||||||
|
|
||||||
|
# --- 画像の回転 --- |
||||||
|
# 回転の中心座標を計算(画像の中心) |
||||||
|
center = (width // 2, height // 2) |
||||||
|
|
||||||
|
# 45度回転するための変換行列を作成(スケールは1.0でそのまま) |
||||||
|
rotation_matrix = cv2.getRotationMatrix2D(center, 45, 1.0) |
||||||
|
|
||||||
|
# アフィン変換を適用して画像を回転 |
||||||
|
rotated_img = cv2.warpAffine(img, rotation_matrix, (width, height)) |
||||||
|
|
||||||
|
# --- 結果の表示 --- |
||||||
|
cv2.imshow('Original Image', img) |
||||||
|
cv2.imshow('Resized Image (1/2)', resized_img) |
||||||
|
cv2.imshow('Rotated Image (45 degrees)', rotated_img) |
||||||
|
|
||||||
|
# キー入力待ち(任意のキーを押すとウィンドウが閉じる) |
||||||
|
cv2.waitKey(0) |
||||||
|
cv2.destroyAllWindows() |
||||||
@ -0,0 +1,23 @@ |
|||||||
|
# 実験課題2 |
||||||
|
# 3.2 グレースケール化 |
||||||
|
|
||||||
|
import cv2 |
||||||
|
|
||||||
|
# 画像の読み込み(カラー画像を用意し、ファイル名を指定してください) |
||||||
|
image_path = 'sample.jpg' |
||||||
|
img = cv2.imread(image_path) |
||||||
|
|
||||||
|
if img is None: |
||||||
|
print("画像を読み込めませんでした。ファイルパスを確認してください。") |
||||||
|
else: |
||||||
|
# --- グレースケール化 --- |
||||||
|
# BGR形式のカラー画像をグレースケールに変換 |
||||||
|
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) |
||||||
|
|
||||||
|
# --- 結果の表示 --- |
||||||
|
cv2.imshow('Original Color Image', img) |
||||||
|
cv2.imshow('Grayscale Image', gray_img) |
||||||
|
|
||||||
|
# キー入力待ち |
||||||
|
cv2.waitKey(0) |
||||||
|
cv2.destroyAllWindows() |
||||||
@ -0,0 +1,31 @@ |
|||||||
|
# 実験課題3 |
||||||
|
# 3.3 2値化 |
||||||
|
|
||||||
|
import cv2 |
||||||
|
|
||||||
|
# 画像の読み込み(3.2と同じ画像を使用) |
||||||
|
image_path = 'sample.jpg' |
||||||
|
|
||||||
|
# 第2引数に 0 (cv2.IMREAD_GRAYSCALE) を指定し、最初からグレースケールとして読み込む |
||||||
|
gray_img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) |
||||||
|
|
||||||
|
if gray_img is None: |
||||||
|
print("画像を読み込めませんでした。ファイルパスを確認してください。") |
||||||
|
else: |
||||||
|
# --- 2値化処理 --- |
||||||
|
# 閾値(自身の画像に合わせて0〜255の間で適切な値に調整してください) |
||||||
|
threshold_value = 127 |
||||||
|
# 閾値を超えた画素に割り当てる値(白 = 255) |
||||||
|
max_value = 255 |
||||||
|
|
||||||
|
# 2値化を実行 |
||||||
|
# ret には使用された閾値が、binary_img には2値化後の画像が代入される |
||||||
|
ret, binary_img = cv2.threshold(gray_img, threshold_value, max_value, cv2.THRESH_BINARY) |
||||||
|
|
||||||
|
# --- 結果の表示 --- |
||||||
|
cv2.imshow('Original Grayscale Image', gray_img) |
||||||
|
cv2.imshow('Binarized Image (Threshold: 127)', binary_img) |
||||||
|
|
||||||
|
# キー入力待ち |
||||||
|
cv2.waitKey(0) |
||||||
|
cv2.destroyAllWindows() |
||||||
@ -0,0 +1,34 @@ |
|||||||
|
# 実験課題4 |
||||||
|
# 3.4 ROIの利用 |
||||||
|
|
||||||
|
import cv2 |
||||||
|
|
||||||
|
# 画像の読み込み(任意の画像を用意してください) |
||||||
|
image_path = 'sample.jpg' |
||||||
|
img = cv2.imread(image_path) |
||||||
|
|
||||||
|
if img is None: |
||||||
|
print("画像を読み込めませんでした。ファイルパスを確認してください。") |
||||||
|
else: |
||||||
|
# 画像の高さ、幅を取得 |
||||||
|
height, width = img.shape[:2] |
||||||
|
|
||||||
|
# --- ROI(関心領域)の指定 --- |
||||||
|
# 切り出す領域の開始位置と終了位置を計算(例として、画像の中心部分を切り出し) |
||||||
|
start_y = height // 4 |
||||||
|
end_y = height * 3 // 4 |
||||||
|
start_x = width // 4 |
||||||
|
end_x = width * 3 // 4 |
||||||
|
|
||||||
|
# --- 画像の切り出し --- |
||||||
|
# NumPy配列のスライス機能を使用して、指定した範囲を切り出す |
||||||
|
# 指定順序は [yの開始:yの終了, xの開始:xの終了] |
||||||
|
roi_img = img[start_y:end_y, start_x:end_x] |
||||||
|
|
||||||
|
# --- 結果の表示 --- |
||||||
|
cv2.imshow('Original Image', img) |
||||||
|
cv2.imshow('ROI (Region of Interest)', roi_img) |
||||||
|
|
||||||
|
# キー入力待ち |
||||||
|
cv2.waitKey(0) |
||||||
|
cv2.destroyAllWindows() |
||||||
@ -0,0 +1,43 @@ |
|||||||
|
# 実験課題5 |
||||||
|
# 3.5 エッジ処理 |
||||||
|
|
||||||
|
import cv2 |
||||||
|
|
||||||
|
# 画像の読み込み(エッジ検出は通常グレースケール画像に対して行います) |
||||||
|
image_path = 'sample.jpg' |
||||||
|
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) |
||||||
|
|
||||||
|
if img is None: |
||||||
|
print("画像を読み込めませんでした。ファイルパスを確認してください。") |
||||||
|
else: |
||||||
|
# --- Sobel(ソーベル)フィルタ --- |
||||||
|
# X方向の勾配(縦のエッジ)とY方向の勾配(横のエッジ)を計算 |
||||||
|
# 負の勾配を保持するため、出力データ型を cv2.CV_64F に指定 |
||||||
|
sobel_x = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) |
||||||
|
sobel_y = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) |
||||||
|
|
||||||
|
# 絶対値を取り、表示可能な8ビット符号なし整数(0〜255)に変換 |
||||||
|
sobel_x_abs = cv2.convertScaleAbs(sobel_x) |
||||||
|
sobel_y_abs = cv2.convertScaleAbs(sobel_y) |
||||||
|
|
||||||
|
# X方向とY方向の画像を1:1の割合で合成して全体のエッジ画像を作成 |
||||||
|
sobel_combined = cv2.addWeighted(sobel_x_abs, 0.5, sobel_y_abs, 0.5, 0) |
||||||
|
|
||||||
|
# --- Laplacian(ラプラシアン)フィルタ --- |
||||||
|
# 2次微分を用いて全方向のエッジを同時に検出 |
||||||
|
laplacian = cv2.Laplacian(img, cv2.CV_64F) |
||||||
|
laplacian_abs = cv2.convertScaleAbs(laplacian) |
||||||
|
|
||||||
|
# --- Canny(キャニー)法 --- |
||||||
|
# ノイズ除去と2つの閾値処理を組み合わせた、より高精度なエッジ検出アルゴリズム |
||||||
|
canny = cv2.Canny(img, 50, 150) |
||||||
|
|
||||||
|
# --- 結果の表示 --- |
||||||
|
cv2.imshow('Original Grayscale', img) |
||||||
|
cv2.imshow('Sobel Edge', sobel_combined) |
||||||
|
cv2.imshow('Laplacian Edge', laplacian_abs) |
||||||
|
cv2.imshow('Canny Edge', canny) |
||||||
|
|
||||||
|
# キー入力待ち |
||||||
|
cv2.waitKey(0) |
||||||
|
cv2.destroyAllWindows() |
||||||
@ -0,0 +1,44 @@ |
|||||||
|
# 実験課題7 |
||||||
|
# 3.7 膨張・収縮 |
||||||
|
|
||||||
|
import cv2 |
||||||
|
import numpy as np |
||||||
|
|
||||||
|
# 3.6の画像(色領域を抽出した画像)を準備するための前処理 |
||||||
|
image_path = 'person.jpg' |
||||||
|
img = cv2.imread(image_path) |
||||||
|
|
||||||
|
if img is None: |
||||||
|
print("画像を読み込めませんでした。ファイルパスを確認してください。") |
||||||
|
else: |
||||||
|
# 3.6の処理(肌色領域の抽出)を再現 |
||||||
|
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) |
||||||
|
lower_skin = np.array([0, 0, 70]) |
||||||
|
upper_skin = np.array([20, 255, 255]) |
||||||
|
skin_mask = cv2.inRange(hsv_img, lower_skin, upper_skin) |
||||||
|
extracted_img = cv2.bitwise_and(img, img, mask=skin_mask) |
||||||
|
|
||||||
|
# --- 膨張・収縮のための構造要素(カーネル)の定義 --- |
||||||
|
# 5x5の正方形のカーネルを作成 |
||||||
|
kernel = np.ones((5, 5), np.uint8) |
||||||
|
|
||||||
|
# --- ① 収縮 3回 → 膨張 3回(オープニング処理) --- |
||||||
|
# まず収縮(erode)を3回実行 |
||||||
|
eroded_first = cv2.erode(extracted_img, kernel, iterations=3) |
||||||
|
# その後、膨張(dilate)を3回実行 |
||||||
|
seq_opening = cv2.dilate(eroded_first, kernel, iterations=3) |
||||||
|
|
||||||
|
# --- ② 膨張 3回 → 収縮 3回(クロージング処理) --- |
||||||
|
# まず膨張(dilate)を3回実行 |
||||||
|
dilated_first = cv2.dilate(extracted_img, kernel, iterations=3) |
||||||
|
# その後、収縮(erode)を3回実行 |
||||||
|
seq_closing = cv2.erode(dilated_first, kernel, iterations=3) |
||||||
|
|
||||||
|
# --- 結果の表示 --- |
||||||
|
cv2.imshow('Original Extracted Image (3.6)', extracted_img) |
||||||
|
cv2.imshow('Sequence 1: Erosion 3 -> Dilation 3', seq_opening) |
||||||
|
cv2.imshow('Sequence 2: Dilation 3 -> Erosion 3', seq_closing) |
||||||
|
|
||||||
|
# キー入力待ち |
||||||
|
cv2.waitKey(0) |
||||||
|
cv2.destroyAllWindows() |
||||||
@ -0,0 +1,38 @@ |
|||||||
|
# 実験課題8 |
||||||
|
# 3.8 Webカメラ映像のキャプチャと表示 |
||||||
|
|
||||||
|
import cv2 |
||||||
|
|
||||||
|
# Webカメラのデバイスを初期化(引数の 0 は標準のカメラデバイスを指します) |
||||||
|
cap = cv2.VideoCapture(0) |
||||||
|
|
||||||
|
# カメラが正常に起動・接続できたかを確認 |
||||||
|
if not cap.isOpened(): |
||||||
|
print("カメラを開けませんでした。カメラの接続や権限を確認してください。") |
||||||
|
else: |
||||||
|
print("カメラ映像の表示を開始します。終了するには 'q' キーを押してください。") |
||||||
|
|
||||||
|
# 映像は「連続した静止画(フレーム)」なので、無限ループで取得し続けます |
||||||
|
while True: |
||||||
|
# カメラから1フレーム(1枚の画像)を読み込む |
||||||
|
# ret には取得成功の可否(True/False)、frame には画像データ(NumPy配列)が入ります |
||||||
|
ret, frame = cap.read() |
||||||
|
|
||||||
|
# 画像が正しく取得できなかった場合はループを終了 |
||||||
|
if not ret: |
||||||
|
print("フレームを正常に取得できませんでした。") |
||||||
|
break |
||||||
|
|
||||||
|
# 取得したフレームを画面に表示 |
||||||
|
cv2.imshow('Webcam Capture', frame) |
||||||
|
|
||||||
|
# 1ミリ秒だけキー入力を待機する |
||||||
|
# もし入力されたキーが 'q' であれば、ループを抜けて終了処理へ進む |
||||||
|
if cv2.waitKey(1) & 0xFF == ord('q'): |
||||||
|
break |
||||||
|
|
||||||
|
# --- 終了処理 --- |
||||||
|
# カメラデバイスを解放(プログラムからの占有を解除) |
||||||
|
cap.release() |
||||||
|
# 全てのウィンドウを閉じる |
||||||
|
cv2.destroyAllWindows() |
||||||
@ -0,0 +1,67 @@ |
|||||||
|
# 実験課題9 |
||||||
|
# 3.9 顔検出 |
||||||
|
|
||||||
|
import cv2 |
||||||
|
|
||||||
|
# --- カスケード分類器(学習済みデータ)の読み込み --- |
||||||
|
# OpenCVに標準で用意されている顔検出用のXMLファイルを指定 |
||||||
|
cascade_path = cv2.data.haarcascades + 'haarcascade_frontalface_default.xml' |
||||||
|
face_cascade = cv2.CascadeClassifier(cascade_path) |
||||||
|
|
||||||
|
# Webカメラの初期化 |
||||||
|
cap = cv2.VideoCapture(0) |
||||||
|
|
||||||
|
if not cap.isOpened(): |
||||||
|
print("カメラを開けませんでした。") |
||||||
|
else: |
||||||
|
print("顔検出を開始します。'q' キーで終了します。") |
||||||
|
|
||||||
|
while True: |
||||||
|
ret, frame = cap.read() |
||||||
|
if not ret: |
||||||
|
print("フレームを取得できませんでした。") |
||||||
|
break |
||||||
|
|
||||||
|
# 3.91 顔検出の精度と処理速度向上のため、グレースケール画像を作成 |
||||||
|
gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) |
||||||
|
|
||||||
|
# グレースケール画像から顔を検出 |
||||||
|
faces = face_cascade.detectMultiScale( |
||||||
|
gray_img, |
||||||
|
scaleFactor=1.1, |
||||||
|
minNeighbors=5, |
||||||
|
minSize=(30, 30) |
||||||
|
) |
||||||
|
|
||||||
|
# 検出されたすべての顔に対してループ処理 |
||||||
|
for (x, y, w, h) in faces: |
||||||
|
|
||||||
|
# --- 3.92 顔を隠す処理(別の画像の貼り付け) --- |
||||||
|
# 貼り付けたい画像(例: 'mask.jpg')を読み込んで顔の領域に上書きします |
||||||
|
mask_img = cv2.imread('mask.jpg') |
||||||
|
|
||||||
|
if mask_img is not None: |
||||||
|
# 読み込んだ画像を、検出された顔の横幅(w)と縦幅(h)と同じサイズにリサイズ |
||||||
|
mask_resized = cv2.resize(mask_img, (w, h)) |
||||||
|
# NumPyのスライス機能(ROI)を使い、元のフレームの顔領域を隠し用画像で上書き |
||||||
|
frame[y:y + h, x:x + w] = mask_resized |
||||||
|
else: |
||||||
|
# 'mask.jpg' が見つからない場合は、代わりに顔領域を黒い矩形で塗りつぶして隠す(値を0にする) |
||||||
|
# 資料の「顔を隠すような処理」を代替実行します |
||||||
|
frame[y:y + h, x:x + w] = 0 |
||||||
|
|
||||||
|
# --- 3.91 顔部分を矩形で囲む --- |
||||||
|
# 隠す処理の後に矩形を描画することで、枠線が隠されずに上から表示されます |
||||||
|
# 引数: (対象画像, 開始座標, 終了座標, 色(BGR), 線の太さ) |
||||||
|
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) |
||||||
|
|
||||||
|
# 結果を画面に表示 |
||||||
|
cv2.imshow('Face Detection & Masking', frame) |
||||||
|
|
||||||
|
# 'q' キーが押されたら終了 |
||||||
|
if cv2.waitKey(1) & 0xFF == ord('q'): |
||||||
|
break |
||||||
|
|
||||||
|
# 後片付け |
||||||
|
cap.release() |
||||||
|
cv2.destroyAllWindows() |
||||||
@ -1,36 +0,0 @@ |
|||||||
# 実験課題1 |
|
||||||
# 画像サイズ変換・画像の回転 |
|
||||||
|
|
||||||
import cv2 |
|
||||||
|
|
||||||
# 画像の読み込み(任意のカラー画像を用意し、ファイル名を指定してください) |
|
||||||
image_path = 'cat.jfif' |
|
||||||
img = cv2.imread(image_path) |
|
||||||
|
|
||||||
height, width = img.shape[:2] |
|
||||||
|
|
||||||
# 縦横を1/2のサイズに計算 |
|
||||||
new_width = width // 2 |
|
||||||
new_height = height // 2 |
|
||||||
|
|
||||||
# 画像のサイズを変更 |
|
||||||
resized_img = cv2.resize(img, (new_width, new_height)) |
|
||||||
|
|
||||||
# --- 画像の回転 --- |
|
||||||
# 回転の中心座標を計算(画像の中心) |
|
||||||
center = (width // 2, height // 2) |
|
||||||
|
|
||||||
# 45度回転するための変換行列を作成(スケールは1.0でそのまま) |
|
||||||
rotation_matrix = cv2.getRotationMatrix2D(center, 45, 1.0) |
|
||||||
|
|
||||||
# アフィン変換を適用して画像を回転 |
|
||||||
rotated_img = cv2.warpAffine(img, rotation_matrix, (width, height)) |
|
||||||
|
|
||||||
# --- 結果の表示 --- |
|
||||||
cv2.imshow('Original Image', img) |
|
||||||
cv2.imshow('Resized Image (1/2)', resized_img) |
|
||||||
cv2.imshow('Rotated Image (45 degrees)', rotated_img) |
|
||||||
|
|
||||||
# キー入力待ち(任意のキーを押すとウィンドウが閉じる) |
|
||||||
cv2.waitKey(0) |
|
||||||
cv2.destroyAllWindows() |
|
||||||
@ -1,20 +0,0 @@ |
|||||||
# 実験課題2 |
|
||||||
# グレースケール化 |
|
||||||
|
|
||||||
import cv2 |
|
||||||
|
|
||||||
# 画像の読み込み(カラー画像を用意し、ファイル名を指定してください) |
|
||||||
image_path = 'cat.jfif' |
|
||||||
img = cv2.imread(image_path) |
|
||||||
|
|
||||||
# --- グレースケール化 --- |
|
||||||
# BGR形式のカラー画像をグレースケールに変換 |
|
||||||
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) |
|
||||||
|
|
||||||
# --- 結果の表示 --- |
|
||||||
cv2.imshow('Original Color Image', img) |
|
||||||
cv2.imshow('Grayscale Image', gray_img) |
|
||||||
|
|
||||||
# キー入力待ち |
|
||||||
cv2.waitKey(0) |
|
||||||
cv2.destroyAllWindows() |
|
||||||
@ -1,28 +0,0 @@ |
|||||||
# 実験課題3 |
|
||||||
# 2値化 |
|
||||||
|
|
||||||
import cv2 |
|
||||||
|
|
||||||
# 画像の読み込み(3.2と同じ画像を使用) |
|
||||||
image_path = 'cat.jfif' |
|
||||||
|
|
||||||
# 第2引数に 0 (cv2.IMREAD_GRAYSCALE) を指定し、最初からグレースケールとして読み込む |
|
||||||
gray_img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) |
|
||||||
|
|
||||||
# --- 2値化処理 --- |
|
||||||
# 閾値(自身の画像に合わせて0〜255の間で適切な値に調整してください) |
|
||||||
threshold_value = 127 |
|
||||||
# 閾値を超えた画素に割り当てる値(白 = 255) |
|
||||||
max_value = 255 |
|
||||||
|
|
||||||
# 2値化を実行 |
|
||||||
# ret には使用された閾値が、binary_img には2値化後の画像が代入される |
|
||||||
ret, binary_img = cv2.threshold(gray_img, threshold_value, max_value, cv2.THRESH_BINARY) |
|
||||||
|
|
||||||
# --- 結果の表示 --- |
|
||||||
cv2.imshow('Original Grayscale Image', gray_img) |
|
||||||
cv2.imshow('Binarized Image (Threshold: 127)', binary_img) |
|
||||||
|
|
||||||
# キー入力待ち |
|
||||||
cv2.waitKey(0) |
|
||||||
cv2.destroyAllWindows() |
|
||||||
@ -1,31 +0,0 @@ |
|||||||
# 実験課題4 |
|
||||||
# ROIの利用 |
|
||||||
|
|
||||||
import cv2 |
|
||||||
|
|
||||||
# 画像の読み込み(任意の画像を用意してください) |
|
||||||
image_path = 'cat.jfif' |
|
||||||
img = cv2.imread(image_path) |
|
||||||
|
|
||||||
# 画像の高さ、幅を取得 |
|
||||||
height, width = img.shape[:2] |
|
||||||
|
|
||||||
# --- ROI(関心領域)の指定 --- |
|
||||||
# 切り出す領域の開始位置と終了位置を計算(例として、画像の中心部分を切り出し) |
|
||||||
start_y = height // 4 |
|
||||||
end_y = height * 3 // 4 |
|
||||||
start_x = width // 4 |
|
||||||
end_x = width * 3 // 4 |
|
||||||
|
|
||||||
# --- 画像の切り出し --- |
|
||||||
# NumPy配列のスライス機能を使用して、指定した範囲を切り出す |
|
||||||
# 指定順序は [yの開始:yの終了, xの開始:xの終了] |
|
||||||
roi_img = img[start_y:end_y, start_x:end_x] |
|
||||||
|
|
||||||
# --- 結果の表示 --- |
|
||||||
cv2.imshow('Original Image', img) |
|
||||||
cv2.imshow('ROI (Region of Interest)', roi_img) |
|
||||||
|
|
||||||
# キー入力待ち |
|
||||||
cv2.waitKey(0) |
|
||||||
cv2.destroyAllWindows() |
|
||||||
@ -1,40 +0,0 @@ |
|||||||
# 実験課題5 |
|
||||||
# 3.5 エッジ処理 |
|
||||||
|
|
||||||
import cv2 |
|
||||||
|
|
||||||
# 画像の読み込み(エッジ検出は通常グレースケール画像に対して行います) |
|
||||||
image_path = 'cat.jfif' |
|
||||||
img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) |
|
||||||
|
|
||||||
# --- Sobel(ソーベル)フィルタ --- |
|
||||||
# X方向の勾配(縦のエッジ)とY方向の勾配(横のエッジ)を計算 |
|
||||||
# 負の勾配を保持するため、出力データ型を cv2.CV_64F に指定 |
|
||||||
sobel_x = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) |
|
||||||
sobel_y = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3) |
|
||||||
|
|
||||||
# 絶対値を取り、表示可能な8ビット符号なし整数(0〜255)に変換 |
|
||||||
sobel_x_abs = cv2.convertScaleAbs(sobel_x) |
|
||||||
sobel_y_abs = cv2.convertScaleAbs(sobel_y) |
|
||||||
|
|
||||||
# X方向とY方向の画像を1:1の割合で合成して全体のエッジ画像を作成 |
|
||||||
sobel_combined = cv2.addWeighted(sobel_x_abs, 0.5, sobel_y_abs, 0.5, 0) |
|
||||||
|
|
||||||
# --- Laplacian(ラプラシアン)フィルタ --- |
|
||||||
# 2次微分を用いて全方向のエッジを同時に検出 |
|
||||||
laplacian = cv2.Laplacian(img, cv2.CV_64F) |
|
||||||
laplacian_abs = cv2.convertScaleAbs(laplacian) |
|
||||||
|
|
||||||
# --- Canny(キャニー)法 --- |
|
||||||
# ノイズ除去と2つの閾値処理を組み合わせた、より高精度なエッジ検出アルゴリズム |
|
||||||
canny = cv2.Canny(img, 50, 150) |
|
||||||
|
|
||||||
# --- 結果の表示 --- |
|
||||||
cv2.imshow('Original Grayscale', img) |
|
||||||
cv2.imshow('Sobel Edge', sobel_combined) |
|
||||||
cv2.imshow('Laplacian Edge', laplacian_abs) |
|
||||||
cv2.imshow('Canny Edge', canny) |
|
||||||
|
|
||||||
# キー入力待ち |
|
||||||
cv2.waitKey(0) |
|
||||||
cv2.destroyAllWindows() |
|
||||||
|
After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
Loading…
Reference in new issue