読み込み中...

Pythonによる画像処理の領域抽出手法と応用例13選

領域抽出 徹底解説 Python
この記事は約30分で読めます。

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

本記事のサンプルコードを活用して機能追加、目的を達成できるように作ってありますので、是非ご活用ください。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を満たす現役のプログラマチームによって監修されています。

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

●Pythonによる領域抽出とは?

画像処理技術の分野で注目を集めている領域抽出。

写真や動画から必要な部分だけを切り取る技術のことです。

Pythonを使えば、この複雑な作業が驚くほど簡単になります。

領域抽出は、画像内の特定の物体や領域を識別し、抽出する過程です。

例えば、風景写真から人物だけを切り出したり、医療画像から腫瘍を検出したりする際に活用されます。

○画像処理における領域抽出の重要性

画像処理の分野で、領域抽出は非常に重要な役割を果たします。

単に画像を見やすくするだけでなく、様々な応用があります。

例えば、自動運転車の開発では、道路上の歩行者や障害物を正確に検出する必要があります。

また、医療分野では、MRIやCT画像から異常を検出し、早期診断に役立てています。

さらに、セキュリティカメラの映像から不審者を自動検出したり、農業で作物の生育状況を分析したりする際にも、領域抽出技術が活用されています。

○Pythonが選ばれる5つの理由

Pythonは、画像処理や機械学習の分野で広く使用されているプログラミング言語です。

特に領域抽出のタスクにおいて、Pythonが選ばれる理由はいくつかあります。

  1. 豊富なライブラリ -> OpenCV、NumPy、SciPyなど、画像処理に特化したライブラリが充実しています。
  2. 簡潔な文法 -> Pythonは読みやすく書きやすい文法を持ち、初心者でも学びやすいです。
  3. 高速な開発 -> プロトタイピングから本番環境まで、素早く開発できます。
  4. 大きなコミュニティ -> 問題解決やノウハウ共有のためのリソースが豊富です。
  5. 機械学習との親和性 -> TensorFlowやPyTorchなど、機械学習ライブラリとの連携が容易です。

○サンプルコード1:簡単な領域抽出プログラム

では、実際にPythonを使って簡単な領域抽出プログラムを作成してみましょう。

OpenCVライブラリを使用し、画像から特定の色の領域を抽出します。

import cv2
import numpy as np

# 画像を読み込む
img = cv2.imread('sample.jpg')

# BGRからHSV色空間に変換
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 青色の範囲を定義
lower_blue = np.array([110,50,50])
upper_blue = np.array([130,255,255])

# マスクを作成
mask = cv2.inRange(hsv, lower_blue, upper_blue)

# 元の画像にマスクを適用
result = cv2.bitwise_and(img, img, mask=mask)

# 結果を表示
cv2.imshow('Result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

このコードは、画像から青色の領域を抽出します。

まず、画像をHSV色空間に変換し、青色の範囲を定義します。次に、inRange関数を使ってマスクを作成し、bitwise_and関数で元の画像に適用します。

実行結果は、元の画像から青色の部分だけが抽出された画像が表示されます。

この簡単な例でも、領域抽出の基本的な流れを理解することができます。

●OpenCVを使った高度な領域抽出テクニック

さて、基本的な領域抽出について理解したところで、より高度なテクニックに挑戦してみましょう。

OpenCVには、複雑な領域抽出を可能にする様々な関数が用意されています。

○サンプルコード2:findContours関数の基本

findContours関数は、二値化画像から輪郭を検出するための強力なツールです。

この関数を使うことで、画像内の物体の形状を簡単に抽出することができます。

import cv2
import numpy as np

# グレースケール画像を読み込む
img = cv2.imread('shapes.jpg', 0)

# 二値化
_, thresh = cv2.threshold(img, 127, 255, 0)

# 輪郭を検出
contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 元の画像に輪郭を描画
img_color = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
cv2.drawContours(img_color, contours, -1, (0,255,0), 2)

# 結果を表示
cv2.imshow('Contours', img_color)
cv2.waitKey(0)
cv2.destroyAllWindows()

このコードでは、まず画像を二値化し、findContours関数で輪郭を検出します。

その後、検出された輪郭を元の画像上に緑色で描画しています。

実行結果は、画像内の物体の輪郭が緑色で描かれた状態で表示されます。

このテクニックは、物体の形状分析や数の計測などに活用できます。

○サンプルコード3:Cannyエッジ検出で輪郭抽出

Cannyエッジ検出は、画像内のエッジ(輪郭)を高精度で検出する方法です。

ノイズに強く、細かいエッジも検出できるため、複雑な画像の領域抽出に適しています。

import cv2
import numpy as np

# 画像を読み込む
img = cv2.imread('sample.jpg', 0)

# Cannyエッジ検出を適用
edges = cv2.Canny(img, 100, 200)

# 結果を表示
cv2.imshow('Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

このコードでは、Canny関数を使ってエッジを検出しています。

100と200は、エッジ検出の閾値で、これらの値を調整することで検出感度を変更できます。

実行結果は、元の画像のエッジだけが白く表示された画像になります。

この方法は、物体の輪郭を正確に抽出したい場合に非常に有効です。

○サンプルコード4:ROI(Region of Interest)の指定方法

ROI(Region of Interest)は、画像内の特定の領域のことを指します。

OpenCVを使えば、簡単にROIを指定し、その領域だけを処理することができます。

import cv2
import numpy as np

# 画像を読み込む
img = cv2.imread('sample.jpg')

# ROIを指定(例:画像の中央部分)
height, width = img.shape[:2]
start_row, start_col = int(height * .25), int(width * .25)
end_row, end_col = int(height * .75), int(width * .75)

roi = img[start_row:end_row, start_col:end_col]

# ROIをグレースケールに変換
gray_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)

# 元の画像にグレースケール化したROIを戻す
img[start_row:end_row, start_col:end_col] = cv2.cvtColor(gray_roi, cv2.COLOR_GRAY2BGR)

# 結果を表示
cv2.imshow('ROI', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

このコードでは、画像の中央部分をROIとして指定し、その部分だけをグレースケールに変換しています。

実行結果は、画像の中央部分だけがグレースケールになった状態で表示されます。

この方法は、画像の特定部分だけを処理したい場合に非常に便利です。

●物体検出と追跡の実践

画像処理は奥が深く、面白さが尽きません。

中でも物体検出と追跡は、まるで魔法のような技術です。

静止画や動画から特定の物体を見つけ出し、追いかける。

そんな高度な技術も、Pythonを使えば驚くほど簡単に実現できるのです。

物体検出と追跡は、セキュリティシステムや自動運転車、さらにはスポーツ分析など、様々な分野で活用されています。

例えば、サッカーの試合分析では、選手やボールの動きを自動で追跡し、戦略立案に役立てています。

また、小売業では、店内の顧客の動きを追跡することで、商品配置の最適化や混雑状況の把握に活用しています。

まさに、現代社会に欠かせない技術と言えるでしょう。

○サンプルコード6:静止画での物体検出

静止画での物体検出は、画像処理の基本中の基本です。

OpenCVには、物体検出のための様々な手法が用意されていますが、ここではHaar Cascadeという手法を使って顔検出を行ってみましょう。

import cv2

# 顔検出器を読み込む
face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')

# 画像を読み込む
img = cv2.imread('people.jpg')

# グレースケールに変換
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 顔を検出
faces = face_cascade.detectMultiScale(gray, 1.1, 4)

# 検出された顔に矩形を描画
for (x, y, w, h) in faces:
    cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)

# 結果を表示
cv2.imshow('Detected Faces', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

このコードでは、まず顔検出器を読み込みます。

次に画像をグレースケールに変換し、detectMultiScale関数を使って顔を検出します。

検出された顔の位置に青い矩形を描画して結果を表示します。

実行結果は、元の画像に青い矩形で顔の位置が示されたものになります。

画像内の人物の顔が自動的に検出されているのが確認できるはずです。

○サンプルコード7:動画中の物体追跡

動画中の物体追跡は、静止画での検出をさらに一歩進めた技術です。

ここでは、OpenCVのTrackerKCFという軽量で高速な追跡アルゴリズムを使用します。

import cv2

# トラッカーを初期化
tracker = cv2.TrackerKCF_create()

# 動画を読み込む
video = cv2.VideoCapture('video.mp4')

# 最初のフレームを読み込む
ret, frame = video.read()

# 追跡する領域を選択
bbox = cv2.selectROI(frame, False)

# トラッカーを初期化
ok = tracker.init(frame, bbox)

while True:
    # フレームを読み込む
    ret, frame = video.read()
    if not ret:
        break

    # トラッキングを更新
    ok, bbox = tracker.update(frame)

    # トラッキングが成功した場合
    if ok:
        # 追跡領域を矩形で描画
        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)
    else:
        # トラッキングが失敗した場合
        cv2.putText(frame, "Tracking failure detected", (100,80), 
                    cv2.FONT_HERSHEY_SIMPLEX, 0.75,(0,0,255),2)

    # 結果を表示
    cv2.imshow("Tracking", frame)

    # 'q'キーで終了
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

video.release()
cv2.destroyAllWindows()

このコードでは、まず動画の最初のフレームで追跡したい対象を選択します。

その後、各フレームでトラッカーを更新し、追跡対象の位置に青い矩形を描画します。

実行結果は、動画内の選択した対象が青い矩形で追跡されているのが確認できます。

対象が動いても矩形が追従していくのが見られるはずです。

○サンプルコード8:テンプレートマッチングによる検出

テンプレートマッチングは、画像内から特定のパターン(テンプレート)を探し出す手法です。

例えば、ロゴや特定の物体を探すのに適しています。

import cv2
import numpy as np

# 画像とテンプレートを読み込む
img = cv2.imread('main_image.jpg', 0)
template = cv2.imread('template.jpg', 0)
h, w = template.shape

# テンプレートマッチングを実行
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)
cv2.rectangle(img, top_left, bottom_right, 255, 2)

# 結果を表示
cv2.imshow('Template Matching Result', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

このコードでは、matchTemplate関数を使ってテンプレートマッチングを行います。

マッチング結果の最大値の位置を見つけ、その位置にテンプレートと同じサイズの矩形を描画します。

実行結果は、元の画像内でテンプレートと最もマッチする箇所に白い矩形が描画されます。

テンプレート画像が正確に検出されているのが確認できるはずです。

○サンプルコード9:複数輪郭の管理と描画

複数の物体が存在する画像から、全ての物体の輪郭を検出し管理する方法を見てみましょう。

import cv2
import numpy as np

# 画像を読み込む
img = cv2.imread('shapes.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 二値化
ret, thresh = cv2.threshold(gray, 127, 255, 0)

# 輪郭を検出
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 検出された全ての輪郭を描画
for i, contour in enumerate(contours):
    # 輪郭の面積を計算
    area = cv2.contourArea(contour)

    # 小さすぎる輪郭は無視
    if area < 100:
        continue

    # ランダムな色を生成
    color = np.random.randint(0, 255, size=3).tolist()

    # 輪郭を描画
    cv2.drawContours(img, [contour], 0, color, 2)

    # 輪郭の重心を計算
    M = cv2.moments(contour)
    if M['m00'] != 0:
        cx = int(M['m10']/M['m00'])
        cy = int(M['m01']/M['m00'])

        # 輪郭番号を描画
        cv2.putText(img, str(i), (cx, cy), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2)

# 結果を表示
cv2.imshow('Contours', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

このコードでは、findContours関数で検出された全ての輪郭に対して処理を行います。

各輪郭をランダムな色で描画し、さらに輪郭の重心位置に輪郭番号を表示します。

実行結果は、元の画像内の各物体の輪郭が異なる色で描画され、各輪郭に番号が振られているのが確認できます。

複数の物体を個別に管理できているのが分かるはずです。

●よくあるエラーと対処法

プログラミングの道は決して平坦ではありません。

特に画像処理のような複雑な分野では、様々なエラーに遭遇することがあります。

しかし、エラーは成長の糧。一つ一つ解決していくことで、より深い理解が得られるのです。

○ノイズによる誤検出の解決策

ノイズによる誤検出は、画像処理において非常によく遭遇する問題です。

例えば、顔検出プログラムが背景の模様を顔と誤認識してしまうなどの現象が起こります。

解決策の一つは、画像の前処理です。

ガウシアンフィルタを使用してノイズを軽減できます。

import cv2
import numpy as np

# 画像を読み込む
img = cv2.imread('noisy_image.jpg')

# ガウシアンフィルタを適用
blurred = cv2.GaussianBlur(img, (5, 5), 0)

# 結果を表示
cv2.imshow('Original', img)
cv2.imshow('Blurred', blurred)
cv2.waitKey(0)
cv2.destroyAllWindows()

このコードでは、GaussianBlur関数を使用してノイズを軽減しています。

(5, 5)はカーネルサイズで、大きくするほど強くぼかされますが、処理時間も増加します。

実行結果は、元の画像と比べてノイズが軽減された画像が表示されます。

細かな斑点やノイズが減少し、全体的になめらかになっているのが確認できるはずです。

○エッジ検出の閾値設定のコツ

エッジ検出は非常に有用な技術ですが、適切な閾値設定が重要です。

閾値が低すぎるとノイズまでエッジとして検出してしまい、高すぎると重要なエッジを見逃してしまいます。

一つの解決策は、適応的閾値処理を使用することです。

import cv2
import numpy as np

# 画像を読み込む
img = cv2.imread('image.jpg', 0)

# 適応的閾値処理を適用
thresh = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                               cv2.THRESH_BINARY, 11, 2)

# Cannyエッジ検出を適用
edges = cv2.Canny(thresh, 100, 200)

# 結果を表示
cv2.imshow('Original', img)
cv2.imshow('Adaptive Threshold', thresh)
cv2.imshow('Edges', edges)
cv2.waitKey(0)
cv2.destroyAllWindows()

このコードでは、まず適応的閾値処理を適用し、その結果に対してCannyエッジ検出を行っています。

適応的閾値処理により、画像の局所的な明るさの変化に対応できます。

実行結果は、元の画像、適応的閾値処理後の画像、エッジ検出後の画像が表示されます。

適応的閾値処理によって、画像全体の明るさの違いに関わらず、適切にエッジが検出されているのが確認できるはずです。

○メモリ不足エラーへの対処

大きな画像や動画を処理する際、メモリ不足エラーに遭遇することがあります。

特に、高解像度の画像や長時間の動画を扱う場合に発生しやすい問題です。

解決策の一つは、画像をブロックに分割して処理する方法です。

import cv2
import numpy as np

def process_image_in_blocks(image, block_size=1000):
    height, width = image.shape[:2]
    for y in range(0, height, block_size):
        for x in range(0, width, block_size):
            # ブロックを切り出す
            block = image[y:min(y+block_size, height), x:min(x+block_size, width)]

            # ブロックに対して処理を行う(例:エッジ検出)
            processed_block = cv2.Canny(block, 100, 200)

            # 処理結果を元の画像に戻す
            image[y:min(y+block_size, height), x:min(x+block_size, width)] = processed_block

    return image

# 大きな画像を読み込む
img = cv2.imread('large_image.jpg')

# ブロックごとに処理
processed_img = process_image_in_blocks(img)

# 結果を表示
cv2.imshow('Processed Image', processed_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

このコードでは、画像を1000×1000ピクセルのブロックに分割して処理しています。

各ブロックに対して個別に処理を行うことで、メモリ使用量を抑えることができます。

実行結果は、大きな画像全体にエッジ検出が適用された状態で表示されます。

メモリ不足エラーを回避しつつ、大きな画像全体を処理できているのが確認できるはずです。

この方法は、特に超高解像度の画像や長時間の動画を扱う際に非常に有効です。

例えば、衛星画像の解析や監視カメラの長時間録画データの処理など、大規模なデータを扱う場面で活躍します。

さらに、並列処理を組み合わせることで、処理速度を大幅に向上させることも可能です。

マルチコアCPUやGPUを活用することで、各ブロックの処理を同時に行うことができます。

import cv2
import numpy as np
from multiprocessing import Pool

def process_block(args):
    block, x, y = args
    # ブロックに対して処理を行う(例:エッジ検出)
    processed_block = cv2.Canny(block, 100, 200)
    return (processed_block, x, y)

def process_image_in_blocks_parallel(image, block_size=1000):
    height, width = image.shape[:2]
    blocks = []
    for y in range(0, height, block_size):
        for x in range(0, width, block_size):
            # ブロックを切り出す
            block = image[y:min(y+block_size, height), x:min(x+block_size, width)]
            blocks.append((block, x, y))

    # 並列処理
    with Pool() as p:
        results = p.map(process_block, blocks)

    # 処理結果を元の画像に戻す
    for processed_block, x, y in results:
        image[y:min(y+block_size, height), x:min(x+block_size, width)] = processed_block

    return image

# 大きな画像を読み込む
img = cv2.imread('large_image.jpg')

# ブロックごとに並列処理
processed_img = process_image_in_blocks_parallel(img)

# 結果を表示
cv2.imshow('Processed Image', processed_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

このコードでは、multiprocessingモジュールのPoolを使用して並列処理を実現しています。

各ブロックの処理が独立して行われるため、マルチコアCPUの性能を最大限に活用できます。

実行結果は、先ほどと同様にエッジ検出が適用された大きな画像が表示されますが、処理時間が大幅に短縮されているはずです。

特に、コア数の多いCPUで効果を発揮します。

●領域抽出の驚くべき応用例

画像処理技術の進歩は、私たちの生活に革命をもたらしています。

特に領域抽出技術は、様々な分野で驚くべき応用が見られます。

自動運転車から医療診断、セキュリティシステム、そして農業に至るまで、領域抽出は今や欠かせない技術となっています。

実際の現場では、領域抽出技術がどのように活用されているのでしょうか。

具体的な例を見ていきましょう。皆さんの想像を超える応用例に、きっと驚かれることでしょう。

○サンプルコード10:自動運転における障害物検知

自動運転技術の発展において、障害物検知は最も重要な要素の一つです。

車の前方にある物体を正確に検出し、その位置や大きさを把握することが求められます。

Pythonを使えば、比較的簡単にこの機能を実装できます。

import cv2
import numpy as np

def detect_obstacles(image):
    # グレースケールに変換
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # エッジ検出
    edges = cv2.Canny(gray, 50, 150)

    # 輪郭検出
    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 一定の大きさ以上の輪郭を障害物とみなす
    obstacles = []
    for contour in contours:
        if cv2.contourArea(contour) > 1000:  # 閾値は適宜調整
            x, y, w, h = cv2.boundingRect(contour)
            obstacles.append((x, y, w, h))

    return obstacles

# カメラからの入力をシミュレート
cap = cv2.VideoCapture(0)

while True:
    ret, frame = cap.read()
    if not ret:
        break

    # 障害物検知
    obstacles = detect_obstacles(frame)

    # 検出された障害物を矩形で囲む
    for (x, y, w, h) in obstacles:
        cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)

    # 結果表示
    cv2.imshow('Obstacle Detection', frame)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

このコードでは、カメラからの入力画像に対して、エッジ検出と輪郭抽出を行い、一定の大きさ以上の輪郭を障害物として検出しています。

実際の自動運転システムでは、より高度なアルゴリズムやセンサーを組み合わせていますが、基本的な考え方は同じです。

実行結果では、カメラに映る物体が緑色の矩形で囲まれて表示されます。

自動車の前方カメラにこのシステムを搭載すれば、前方の障害物をリアルタイムで検知できるわけです。

まさに、自動運転の目の役割を果たしているのです。

○サンプルコード11:医療画像診断支援システム

医療分野における画像診断は、患者の生命に直結する重要な作業です。

しかし、画像を目視で確認するには時間がかかり、見落としのリスクもあります。

そこで、AIによる画像診断支援システムが注目されています。

import cv2
import numpy as np
from tensorflow.keras.models import load_model

def analyze_medical_image(image_path, model_path):
    # 画像を読み込み、前処理
    image = cv2.imread(image_path)
    image = cv2.resize(image, (224, 224))
    image = image / 255.0
    image = np.expand_dims(image, axis=0)

    # モデルを読み込み
    model = load_model(model_path)

    # 予測
    prediction = model.predict(image)

    return prediction[0][0]

# 使用例
image_path = 'chest_xray.jpg'
model_path = 'pneumonia_detection_model.h5'

result = analyze_medical_image(image_path, model_path)

print(f'肺炎の可能性: {result*100:.2f}%')

# 結果を可視化
image = cv2.imread(image_path)
cv2.putText(image, f'Pneumonia: {result*100:.2f}%', (10, 30),
            cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.imshow('Medical Image Analysis', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

このコードでは、事前に学習された深層学習モデルを使用して、胸部X線画像から肺炎の可能性を予測しています。

実際の医療現場では、より複雑なモデルと大量のデータを使用しますが、基本的な流れは同じです。

実行結果では、入力された胸部X線画像に肺炎の可能性が数値で表示されます。

医師はこの結果を参考にしながら、最終的な診断を下すことができます。

AI技術が医師の判断を支援し、診断の精度向上と効率化に貢献しているのです。

○サンプルコード12:監視カメラ映像の異常検知

セキュリティの分野では、監視カメラの映像から異常を自動検知するシステムが注目されています。

人間が常に監視するのは困難ですが、AIを使えば24時間365日、休むことなく監視を続けることができます。

import cv2
import numpy as np

def detect_motion(frame, background):
    # フレーム間の差分を計算
    diff = cv2.absdiff(background, frame)

    # 差分を二値化
    _, thresh = cv2.threshold(diff, 30, 255, cv2.THRESH_BINARY)

    # ノイズ除去
    kernel = np.ones((5,5), np.uint8)
    thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)

    # 輪郭検出
    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 一定以上の大きさの輪郭を動体とみなす
    motion_detected = False
    for contour in contours:
        if cv2.contourArea(contour) > 1000:  # 閾値は適宜調整
            motion_detected = True
            break

    return motion_detected, thresh

# カメラからの入力をシミュレート
cap = cv2.VideoCapture(0)

# 最初のフレームを背景として保存
ret, background = cap.read()
background = cv2.cvtColor(background, cv2.COLOR_BGR2GRAY)

while True:
    ret, frame = cap.read()
    if not ret:
        break

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 動体検知
    motion_detected, thresh = detect_motion(gray, background)

    # 結果表示
    if motion_detected:
        cv2.putText(frame, 'Motion Detected!', (10, 30),
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

    cv2.imshow('Motion Detection', frame)
    cv2.imshow('Threshold', thresh)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

このコードでは、背景差分法という手法を使って動体検知を行っています。

カメラの映像から背景を差し引くことで、動いている物体を検出します。

実行結果では、カメラに映る動く物体が検出され、「Motion Detected!」という警告が表示されます。

実際の監視システムでは、この検知結果を基に警報を鳴らしたり、セキュリティ担当者に通知したりします。

人間の目の届かないところでも、AIが常に警戒しているのです。

○サンプルコード13:農業における作物の生育状況分析

農業分野でも、画像処理技術が活躍しています。

ドローンで撮影した畑の画像を解析することで、作物の生育状況や病気の兆候を早期に発見できます。

import cv2
import numpy as np

def analyze_crop_health(image):
    # HSV色空間に変換
    hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

    # 緑色の範囲を定義
    lower_green = np.array([30, 40, 40])
    upper_green = np.array([90, 255, 255])

    # マスク作成
    mask = cv2.inRange(hsv, lower_green, upper_green)

    # 緑色領域の割合を計算
    green_ratio = cv2.countNonZero(mask) / (image.shape[0] * image.shape[1])

    # 簡易的な健康度評価
    if green_ratio > 0.5:
        health = '良好'
    elif green_ratio > 0.3:
        health = '注意'
    else:
        health = '要対策'

    return health, green_ratio, mask

# 画像を読み込む(ドローンからの空撮画像を想定)
image = cv2.imread('field.jpg')

# 作物の健康度を分析
health, green_ratio, mask = analyze_crop_health(image)

# 結果を表示
print(f'作物の健康度: {health}')
print(f'緑色領域の割合: {green_ratio*100:.2f}%')

cv2.putText(image, f'Health: {health}', (10, 30),
            cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.imshow('Crop Health Analysis', image)
cv2.imshow('Green Mask', mask)
cv2.waitKey(0)
cv2.destroyAllWindows()

このコードでは、画像内の緑色領域の割合を計算することで、作物の健康度を簡易的に評価しています。

実際の農業現場では、より複雑なアルゴリズムや多様なセンサーデータを組み合わせて分析を行います。

実行結果では、入力された畑の画像に作物の健康度が表示されます。

また、緑色領域を示すマスク画像も同時に表示されます。

農家の方々は、この情報を基に適切なタイミングで水やりや施肥、病気対策を行うことができます。

AIが農業の効率化と品質向上をサポートしているのです。

まとめ

本記事では、基本的な領域抽出の手法から、実践的な応用例まで幅広く紹介しました。

サンプルコードを通じて、皆さんもその魅力を感じ取っていただけたのではないでしょうか。

今後、AIと画像処理技術はますます発展し、私たちの生活に深く浸透していくでしょう。

その時、今回学んだ知識が、きっと皆さんの力になるはずです。

ぜひ、この記事を出発点として、さらなる学習を続けてください。