OpenCV のクイック スタート: 動体検出とターゲット追跡

記事ディレクトリ


序文

今日のデジタル世界では、コンピュータービジョン技術が急速に発展し、さまざまな場面で広く使用されています。特に移動物体検知や目標追跡の分野では、この技術は安全監視システムにとって極めて重要であるだけでなく、自動運転、インタラクティブメディア、ロボット工学などの多くの分野でも重要な役割を果たしています。

この記事では、OpenCVを使った動体検知やターゲット追跡の基礎知識、各種アルゴリズムの原理や公式、実際のコード実装などを紹介します。移動物体検出の基本概念から始めて、テンプレート、特徴、密度、モデル、学習ベースの追跡技術など、さまざまなタイプの物体追跡方法について詳しく説明します。この記事では、これらのテクノロジの理論的基礎を理解できるだけでなく、提供されているコード例を通じてこれらのテクノロジを実際のプロジェクトに適用する方法を学ぶことができます。
OpenCVのロゴ


1. 動体検知と目標追跡の概要

1.1 動体検知の基本概念

動体検出とは、ビデオ シーケンス内で動的に変化する物体を識別して位置を特定することを指します。通常、このプロセスには次の手順が含まれます。

  1. 背景モデリング: 動画内の静的な背景を特定します。これは、どの部分が静的であるかを見つけることを目的として、一連のフレームを分析することによって行われます。

  2. 前景の検出: アルゴリズムは、モデルと一致しない背景の部分を識別します。これらは通常、移動するオブジェクトです。

  3. データ処理: フィルタリングとしきい値処理によってノイズを除去し、移動物体に関する情報を正確に抽出します。

1.2 動体検出アルゴリズムの種類

  1. 背景減算ベースの方法: これは、現在のフレームから背景フレームを減算することで移動オブジェクトを検出する最も直感的な方法です。これには、背景が静的であるか、優れたバックグラウンド更新メカニズムが必要です。

  2. オプティカル フロー手法: オプティカル フローとは、画像シーケンスにおける物体表面の動きのパターンを指します。これらのパターンの変化を解析することで、物体の動きを推測することができます。

  3. フレーム差分ベースの方法: この方法は、連続するフレーム間の差分を比較することによって動きを検出します。高速で移動する物体には特に効果的ですが、低速で移動する物体は検出できない場合があります。

  4. 機械学習ベースのメソッド: これらのメソッドはトレーニング データを使用して移動物体を識別します。たとえば、深層学習アルゴリズムを使用してトレーニングされたモデルは、複雑な環境でオブジェクトを効果的に検出および分類できます。

オブジェクト追跡の主なタスクは、連続するビデオ フレーム内の特定のオブジェクトを識別して追跡することです。この技術は、セキュリティ監視、人間とコンピュータのインタラクション、自動運転などの分野で広く使用されています。このパートでは、オブジェクト追跡の基本概念とさまざまな種類の追跡アルゴリズムについて説明します。

1.3 ターゲット追跡の基本概念

ターゲット追跡プロセスには、通常、ターゲットの検出とターゲットの位置特定という 2 つの主要なステップが含まれます。まず、ビデオの最初のフレームまたは最初のフレームで対象のオブジェクトが識別されます。これはオブジェクト検出と呼ばれるステップです。次に、システムはターゲットが移動したり形状が変化したりした場合でも、後続のビデオ フレーム内でターゲットの位置を特定する必要があります。このステップはターゲットの位置決めと呼ばれます。

ターゲット追跡プロセス中、アルゴリズムは、ターゲットの急速な動き、オクルージョン、照明の変化、スケールの変化など、さまざまな課題に対処する必要があります。効果的なターゲット追跡アルゴリズムは、これらの課題にもかかわらず、安定してターゲットを追跡できます。

1.4 ターゲット追跡アルゴリズムの種類

  1. テンプレート ベースのトラッキング: このタイプのアルゴリズムは、オブジェクトの最初の外観をテンプレートとして使用し、後続のフレームで最も一致する領域を検索します。この方法はシンプルで直感的ですが、ターゲットの外観が大きく変化する場合にはうまく機能しません。

  2. 特徴ベースの追跡: この方法は、ターゲットの主要な特徴 (エッジ、コーナーなど) の検出と追跡に依存します。フィーチャベースのトラッキングは、特定の外観の変化を処理できますが、複雑なシーンにおけるオクルージョンや照明の変化に敏感です。

  3. 密度ベースのトラッキング: この方法は、ピクセル レベルで動きを推定することによってオブジェクトを追跡します(オプティカル フロー方法など)。高速な動きや局所的なオクルージョンへの適応性は優れていますが、計算コストが高くなります。

  4. モデルベースのトラッキング: このタイプのアルゴリズムは、ターゲットの 3D モデルを構築し、すべてのフレームでそのモデルと一致しようとします。複雑な形状や動きを扱うのに非常に効果的ですが、大量の計算リソースと正確な初期モデルが必要です。

  5. 学習ベースの追跡: 近年、機械学習、特にディープ ラーニングの開発に伴い、学習ベースの追跡手法が大幅に進歩しました。このタイプのアルゴリズムは、ニューラル ネットワークをトレーニングすることでターゲットを効果的に追跡する方法を自動的に学習し、さまざまな複雑なシナリオや課題に対処できます。

各アルゴリズムには利点と制限があり、実際のアプリケーションでは、通常、どの追跡アルゴリズムを選択するかは、特定のタスクのニーズと利用可能なコンピューティング リソースによって決まります。 OpenCV を通じて、これらのさまざまなタイプの追跡アルゴリズムを実装し、実際のターゲット追跡タスクに適用できます。

2. 動体検出の差分法

差分法は監視やリアルタイム追跡システムに適したシンプルで効果的な動体検出技術です。中心的なアイデアは、連続するビデオ フレーム間の差異を比較することによって移動オブジェクトを識別することです。

2.1 差分法の原理

差分法の基本原理は、2 つ以上の連続した画像間のピクセルの差分を比較することです。静止した背景の場合、隣接するフレーム間の差は小さくなりますが、動くオブジェクトの場合、位置の変化により隣接するフレーム間のピクセル値の差が大きくなります。

2.2 差分法の計算式

I ( x , y , t ) I(x, y, t) I(x,y,t) の期間 t t 瞬間、画像は ( x , y ) (x, y) (x,y) のピクセル値。差分法では、2 つの隣接するフレーム間の差分を計算することで移動オブジェクトを検出します。

D ( x , y , t ) = ∣ I ( x , y , t ) − I ( x , y , t − 1 ) ∣ D(x, y, t) = |I(x, y, t) - I (x, y, t-1)|D(x,y,t)=I(x,y,t)I(x,y,t1)

その中、 D ( x , y , t ) D(x, y, t) D(x,y,t)表示时刻 t t t と時刻 t − 1 t-1 t1之间在位置 ( x , y ) (x, y) (x,y)的像素差异。

2.3 コードの実装

2.3.1 ビデオまたはカメラによる移動物体の検出

以下は、Difference メソッドを実装する簡単な例です。

import cv2

# # 初始化摄像头
# cap = cv2.VideoCapture(0)
# 读取视频
cap = cv2.VideoCapture('video.mp4')

# 读取第一帧
ret, frame1 = cap.read()
gray1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)

# 定义矩形结构元素
rectangle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

while True:
    # 读取下一帧
    ret, frame2 = cap.read()
    if not ret:
        break  # 如果视频结束,跳出循环

    gray2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)

    # 计算两帧的差异
    diff = cv2.absdiff(gray1, gray2)

    # 二值化以突出差异
    _, thresh = cv2.threshold(diff, 30, 255, cv2.THRESH_BINARY)
    thresh = cv2.dilate(thresh, rectangle_kernel, iterations=2)  # 膨胀操作,使轮廓更清晰

    # 找出轮廓
    _, contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 识别面积最大的轮廓
    if contours:
        largest_contour = max(contours, key=cv2.contourArea)
        x, y, w, h = cv2.boundingRect(largest_contour)
        cv2.rectangle(frame2, (x, y), (x + w, y + h), (0, 255, 0), 2)  # 用绿色矩形框出

    # 显示结果
    thresh_img = cv2.merge([thresh, thresh, thresh])
    cv2.imshow('Difference', cv2.hconcat([frame2, thresh_img]))
    # 准备下一次迭代
    gray1 = gray2

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

# 释放资源
cap.release()
cv2.destroyAllWindows()

このコードは、最初にカメラを初期化し、次にループで画像の各フレームを読み取ります。移動物体は、連続する 2 つのフレーム間のグレースケール画像の差を計算し、しきい値処理によってこれらの差を強調表示することによって検出されます。

違い1
違い2

2.3.2 ランダムアニメーションによる動体検出

アニメーション生成コードAnimation.py

import cv2
import numpy as np
import random

class Animation:
    def __init__(self, width=800, height=800, num_shapes=10):
        self.width, self.height = width, height
        self.canvas = np.zeros((height, width, 3), dtype=np.uint8)
        self.shapes = [self.Shape(width, height) for _ in range(num_shapes)]
        self.running = False

    class Shape:
        def __init__(self, width, height):
            self.type = random.choice(["rectangle", "circle", "ellipse"])
            self.color = tuple(np.random.randint(0, 255, (3,)).tolist())
            self.center = np.random.randint(0, min(width, height), (2,))
            self.size = np.random.randint(10, 50)
            self.velocity = np.random.randint(-5, 5, (2,))
            self.width = width
            self.height = height

        def move(self):
            self.center += self.velocity
            for i in range(2):
                if self.center[i] < 0 or self.center[i] > (self.width if i == 0 else self.height):
                    self.velocity[i] *= -1
                    self.center[i] += self.velocity[i]

        def draw(self, canvas):
            if self.type == "rectangle":
                top_left = (self.center - self.size).astype(int)
                bottom_right = (self.center + self.size).astype(int)
                cv2.rectangle(canvas, tuple(top_left), tuple(bottom_right), self.color, -1)
            elif self.type == "circle":
                cv2.circle(canvas, tuple(self.center), self.size, self.color, -1)
            else:  # ellipse
                axes = (self.size, self.size // 2)
                cv2.ellipse(canvas, tuple(self.center), axes, 0, 0, 360, self.color, -1)

    def start(self):
        self.running = True
        while self.running:
            self.canvas[:] = 0
            for shape in self.shapes:
                shape.move()
                shape.draw(self.canvas)
            cv2.imshow("Animation", self.canvas)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                self.stop()

    def stop(self):
        self.running = False
        cv2.destroyAllWindows()

    def get_frame(self):
        self.canvas[:] = 0
        for shape in self.shapes:
            shape.move()
            shape.draw(self.canvas)
        return self.canvas.copy()

# 使用方法:
# animation = Animation()
# animation.start()         # 开始动画
# animation.get_frame()     # 获取一帧画面

動体検知コード

import cv2
import Animation

animation = Animation.Animation(500, 400, 10)
frame1 = animation.get_frame()
gray1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY)

# 定义矩形结构元素
rectangle_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

while True:
    # 读取下一帧
    frame2 = animation.get_frame()

    gray2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)

    # 计算两帧的差异
    diff = cv2.absdiff(gray1, gray2)

    # 二值化以突出差异
    _, thresh = cv2.threshold(diff, 30, 255, cv2.THRESH_BINARY)
    # 闭运算操作
    thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, rectangle_kernel,iterations=2)

    # 找出轮廓
    _, contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 识别面积最大的轮廓
    for contour in contours:
        x, y, w, h = cv2.boundingRect(contour)
        cv2.rectangle(frame2, (x, y), (x + w, y + h), (0, 255, 0), 2)  # 用绿色矩形框出

    # 显示结果
    thresh_img = cv2.merge([thresh, thresh, thresh])
    cv2.imshow('Difference', cv2.hconcat([frame2, thresh_img]))
    # 准备下一次迭代
    gray1 = gray2

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

cv2.destroyAllWindows()

違い3

3. テンプレートベースの追跡

テンプレートベースの追跡は、オブジェクト追跡のシンプルで直感的な方法です。この方法では、オブジェクトの最初の外観をテンプレートとして使用し、ビデオの後続のフレームでこのテンプレートに最もよく一致する領域を検索します。このアプローチの鍵となるのは、テンプレートを定義して使用する方法、および新しいフレームでそのテンプレートを検索する方法です。

3.1 テンプレート追跡原理

テンプレートベースの追跡には通常、次の手順が含まれます。

  1. テンプレートの選択: ビデオの最初のフレーム内の領域または特定のフレームをトラッキングのターゲット テンプレートとして選択します。
  2. 類似性測定: テンプレートと新しいフレーム内の候補領域間の類似性を計算するための測定基準を定義します。一般的な指標には、二乗差、相関係数などが含まれます。
  3. 一致を検索: 後続のフレームでテンプレートに最も類似した領域を検索します。これは、スライディング ウィンドウと類似性の尺度によって実現できます。

3.2 テンプレート追跡式

一般的な類似性の尺度は正規化された相互相関係数であり、その式は次のとおりです。

R ( x , y ) = ∑ x ' , y ' [ T ( x ' , y ' ) ⋅ I ( x + x ' , y + y ' ) ] ∑ x ' , y ' [ T ( x ' , y ' ) 2 ] ∑ x ' , y ' [ I ( x + x ' , y + y ' ) 2 ] R(x, y) = \frac{\sum_{x', y'}[T (x', y') \cdot I(x + x', y + y')]}{\sqrt{\sum_{x', y'}[T (x', y')^2] \cdot \sum_{x', y'}[I(x + x', y + y')^2]} }R(x,y)=バツ'y' [T(x'そして')2]バツ'y' [I(x+バツ'そして+そして')2] バツ'y' [T(x'そして')I(x+バツ'そして+そして')]

其中, R ( x , y ) R(x, y) R(x,y) は位置 (x, y) での相関係数です。 T T T是模板图像,而 I I I は、現在のフレームの検索エリアです。

3.3 コードの実装

3.3.1 ビデオまたはカメラでのターゲット追跡

以下は、テンプレートベースの追跡の簡単な例です。
import cv2

# # 初始化摄像头
# cap = cv2.VideoCapture(0)
# 读取视频
cap = cv2.VideoCapture('video.mp4')

# 读取第一帧并选择模板
ret, frame = cap.read()
template = cv2.selectROI("Select Template", frame, fromCenter=False)
template_img = frame[int(template[1]):int(template[1] + template[3]), int(template[0]):int(template[0] + template[2])]
h, w = template_img.shape[:2]

# 开始跟踪
while True:
    _, frame = cap.read()
    if not ret:
        break

    # 匹配模板
    res = cv2.matchTemplate(frame, template_img, cv2.TM_CCOEFF_NORMED)
    _, _, _, max_loc = cv2.minMaxLoc(res)

    # 绘制跟踪结果
    top_left = max_loc
    bottom_right = (top_left[0] + w, top_left[1] + h)
    cv2.rectangle(frame, top_left, bottom_right, (0, 255, 0), 2)

    cv2.imshow("Tracking", frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放资源
cap.release()
cv2.destroyAllWindows()

追跡

この例では、まずビデオの最初のフレームからテンプレート領域を選択します。次に、cv2.matchTemplate 関数を使用して、そのテンプレートに最もよく一致する各フレーム内の領域を見つけます。この方法は、ターゲットの外観が大きく変化する場合にはうまく機能しない可能性がありますが、ターゲットの外観が比較的安定している場合には効果的に機能します。

実際の作業では、紛失や位置ずれなどの問題が発生します。
正确定位:
エラー箇所
错误定位:
エラー箇所

3.3.2 ランダムアニメーションでのターゲット追跡

import cv2
import Animation

animation = Animation.Animation(500, 400, 10)
frame = animation.get_frame()

template = cv2.selectROI("Select Template", frame, fromCenter=False)
template_img = frame[int(template[1]):int(template[1] + template[3]), int(template[0]):int(template[0] + template[2])]
h, w = template_img.shape[:2]

# 开始跟踪
while True:
    frame = animation.get_frame()

    # 匹配模板
    res = cv2.matchTemplate(frame, template_img, cv2.TM_CCOEFF_NORMED)
    _, _, _, max_loc = cv2.minMaxLoc(res)

    # 绘制跟踪结果
    top_left = max_loc
    bottom_right = (top_left[0] + w, top_left[1] + h)
    cv2.rectangle(frame, top_left, bottom_right, (0, 255, 0), 2)

    cv2.imshow("Tracking", frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()

追跡

4. 特徴ベースの追跡

コンピューター ビジョンでは、特徴ベースの追跡は、ビデオ シーケンス内のオブジェクトの主要な特徴点を識別して追跡することに重点を置いています。

4.1 特徴追跡原理

特徴ベースの追跡は通常、特徴点の検出と特徴点のマッチングという 2 つの主要なステップで構成されます。

  1. 特徴点の検出: まず、アルゴリズムは最初のフレーム内の主要な特徴点を特定します。これらのポイントは、コーナー、エッジなど、画像内の固有の領域です。

  2. 特徴点マッチング: これらの特徴点は後続のフレームで追跡されます。これは、隣接するフレーム内の特徴点の外観と位置を比較することによって行われます。

4.2 特徴追跡式

一般的に使用される特徴点検出アルゴリズムはShi-Tomasiコーナー検出器であり、その計算式は次のとおりです。

R = 最小 ( λ 1 , λ 2 ) R = 最小 (\lambda_1, \lambda_2)R=(λ1 2 )

其中, λ 1 \lambda_1 1 λ 2 \lambda_2 2 は、画像内の特定の点の近傍の勾配の共分散行列の固有値です。大きい R R R の値は、そのポイントが強力なコーナー ポイントであることを意味します。

4.3 コードの実装

4.3.1 ビデオまたはカメラでのオブジェクト追跡

特徴ベースの追跡のサンプル コードは次のとおりです。

import numpy as np
import cv2

# # 初始化摄像头
# cap = cv2.VideoCapture(0)
# 读取视频
cap = cv2.VideoCapture('video.mp4')

# Shi-Tomasi角点检测参数
feature_params = dict(maxCorners=100, qualityLevel=0.3, minDistance=7, blockSize=7)

# 光流法参数
lk_params = dict(winSize=(15, 15), maxLevel=2, criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

# 随机颜色
color = np.random.randint(0, 255, (100, 3))

# 读取第一帧
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)

# 创建一个掩模用于绘制轨迹
mask = np.zeros_like(old_frame)

while True:
    ret, frame = cap.read()
    if not ret:
        break
        
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 计算光流以获取新的特征点位置
    p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
    # 如果p1为None,重新检测特征点
    if p1 is None:
        p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)
        continue
    # 选取好的特征点
    good_new = p1[st == 1]
    good_old = p0[st == 1]

    # 绘制轨迹
    for i, (new, old) in enumerate(zip(good_new, good_old)):
        a, b = new.ravel()
        c, d = old.ravel()
        mask = cv2.line(mask, (a, b), (c, d), color[i].tolist(), 2)
        frame = cv2.circle(frame, (a, b), 5, color[i].tolist(), -1)
    img = cv2.add(frame, mask)

    cv2.imshow('Frame', img)

    # 更新上一帧的图像和特征点位置
    old_gray = frame_gray.copy()
    p0 = good_new.reshape(-1, 1, 2)

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

# 释放资源和关闭窗口
cv2.destroyAllWindows()

シトマシ特徴追跡

4.3.2 ランダムアニメーションでのターゲット追跡

import numpy as np
import cv2
import Animation

animation = Animation.Animation(500, 400, 2)

# Shi-Tomasi角点检测参数
feature_params = dict(maxCorners=100, qualityLevel=0.3, minDistance=7, blockSize=7)

# 光流法参数
lk_params = dict(winSize=(15, 15), maxLevel=2, criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

# 随机颜色
color = np.random.randint(0, 255, (100, 3))

# 读取第一帧
old_frame = animation.get_frame()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)

# 创建一个掩模用于绘制轨迹
mask = np.zeros_like(old_frame)

while True:
    frame = animation.get_frame()
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 计算光流以获取新的特征点位置
    p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
    # 如果p1为None,重新检测特征点
    if p1 is None:
        p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)
        continue
    # 选取好的特征点
    good_new = p1[st == 1]
    good_old = p0[st == 1]

    # 绘制轨迹
    for i, (new, old) in enumerate(zip(good_new, good_old)):
        a, b = new.ravel()
        c, d = old.ravel()
        mask = cv2.line(mask, (a, b), (c, d), color[i].tolist(), 2)
        frame = cv2.circle(frame, (a, b), 5, color[i].tolist(), -1)
    img = cv2.add(frame, mask)

    cv2.imshow('Frame', img)

    # 更新上一帧的图像和特征点位置
    old_gray = frame_gray.copy()
    p0 = good_new.reshape(-1, 1, 2)

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

# 释放资源和关闭窗口
cv2.destroyAllWindows()

シトマシ特徴追跡
シトマシ特徴追跡

5. 密度ベースの追跡

5.1 平均シフト法によるターゲット追跡

5.1.1 平均値シフト法の原理

平均値シフト法の基本的な考え方は、サンプル点の密度分布を使用してクラスタリングを実行することです。アルゴリズム プロセス中、各サンプル ポイントはその近傍の密度中心に向かって移動し、このプロセスは最大の局所密度を持つポイントに到達するまで反復され続けます。このようにして、同様の特性を持つサンプル点が徐々に集まり、クラスターを形成します。平均シフト アルゴリズムの鍵は、各点の近傍とその密度中心をどのように決定するかです。

5.1.2 平均シフト法の計算式

平均移動法の中心となる式には、各点の近傍にあるサンプル ポイントの平均値を移動方向として計算することが含まれます。具体的な式は次のとおりです。

x 1 , x 2 , … , x n x_1, x_2, \ldots, x_n バツ1 バツ2 バツn はサンプル ポイントです。各サンプル ポイントの x i x_i バツi 、平均シフト アルゴリズムは、次の手順で位置を更新します。

  1. ウィンドウ サイズの選択: まず、「ウィンドウ」または「カーネル」(通常はガウス カーネルまたは均一カーネル) と、対応する帯域幅パラメータを選択します。< a i= 2> はぁ

  2. ウィンドウ内の平均を計算します: 各データ ポイントについて x i x_i バツi 、周囲の帯域幅を計算します h h h 内のすべてのサンプル ポイントの平均。この平均は、通常はカーネル関数によって決定される重みを使用して計算されます。平均の計算式は次のとおりです。
    m ( x i ) = ∑ x j ∈ N ( x i ) K ( x i − x j ) x j ∑ x j ∈ N ( x i ) K ( x i − x j ) m(x_i ) = \frac{\sum_{x_j \in N(x_i)} K(x_i - x_j) x_j}{\sum_{x_j \in N(x_i)} K(x_i - x_j)} m(xi )=バツj N(xi ) K(xi バツj )バツj N(xi ) K(xi バツj )xj
    其中, N ( x i ) N(x_i) N(xi ) 表示 x i x_i バツi K K 周辺K はカーネル関数です。

  3. データ ポイントの位置を更新する: 各データ ポイントを変更します x i x_i バツi 計算平均値に移動 m ( x i ) m(x_i) m(xi ) 移動します。

  4. 反復: すべてのポイントの移動距離が特定のしきい値未満になるか、事前に設定された反復回数に達するまで、ステップ 2 と 3 を繰り返します。

平均シフト アルゴリズムの鍵は、カーネル関数と帯域幅パラメータの選択にあります h h h の設定。カーネル関数の選択により、サンプル ポイントの重み分布と帯域幅が決まります。 h h h はローカル近傍のサイズを決定します。このようにして、平均シフトによりデータの密度ピークを見つけることができ、それによってデータのクラスタリングが達成されます。

5.1.3 コードの実装

次に、平均シフト オブジェクト トラッキングの実装例を示します。
ビデオまたはカメラでのオブジェクト トラッキング:

import numpy as np
import cv2

# # 初始化摄像头
# cap = cv2.VideoCapture(0)
# 读取视频
cap = cv2.VideoCapture('video.mp4')

# 读取第一帧并选择跟踪目标
ret, frame = cap.read()
roi = cv2.selectROI(frame, False)
x, y, w, h = roi
track_window = (x, y, w, h)

# ROI的直方图
roi_img = frame[y:y+h, x:x+w]
hsv_roi = cv2.cvtColor(roi_img, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0,180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)

# 均值迁移参数
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)

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

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)

    # 应用均值迁移来获取新窗口位置
    ret, track_window = cv2.meanShift(dst, track_window, term_crit)

    # 绘制窗口
    x, y, w, h = track_window
    final_img = cv2.rectangle(frame, (x, y), (x+w, y+h), 255, 2)

    cv2.imshow('Mean Shift Tracking', final_img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

平均シフト追跡
ランダムアニメーションでのターゲット追跡:

import numpy as np
import cv2
import Animation

animation = Animation.Animation(500, 400, 2)

# 读取第一帧并选择跟踪目标
frame = animation.get_frame()
roi = cv2.selectROI(frame, False)
x, y, w, h = roi
track_window = (x, y, w, h)

# ROI的直方图
roi_img = frame[y:y+h, x:x+w]
hsv_roi = cv2.cvtColor(roi_img, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))
roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0,180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)

# 均值迁移参数
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)

while True:
    frame = animation.get_frame()

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)

    # 应用均值迁移来获取新窗口位置
    ret, track_window = cv2.meanShift(dst, track_window, term_crit)

    # 绘制窗口
    x, y, w, h = track_window
    final_img = cv2.rectangle(frame, (x, y), (x+w, y+h), (0,255,0), 2)

    cv2.imshow('Mean Shift Tracking', final_img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()

平均シフト追跡
平均シフト追跡

5.2 オプティカルフロー方式のターゲット追跡

オプティカルフロー法は、連続動画中の対象物の動きを解析・追跡する技術です。コンピュータビジョンやビデオ処理の分野、特にターゲット追跡に広く使用されています。

5.2.1 オプティカルフロー方式の原理

オプティカル フロー手法は、画像シーケンス内のオブジェクトの動きが時間の経過とともに画像の明るさの変化を引き起こすという仮定に基づいています。したがって、これらの明るさの変化を分析することで、連続する 2 つのフレーム間の物体の動きを推測することができます。

オプティカル フローは本質的に、画像内の各ピクセルの動きの速度と方向のベクトル場です。これは実際のオブジェクトの速度ではなく、オブジェクトの動きを画像平面上に投影したものです。これらのベクトルを解析することで、物体の軌道、速度、方向を推定できます。

5.2.2 オプティカルフロー方式の計算式

オプティカル フロー メソッドの中核となる式は、一定の明るさ、つまり、連続する 2 つの画像フレーム内で点の明るさが変化しないという仮定に基づいています。画像の明るさを I ( x , y , t ) I(x, y, t) とします。I(x,y,(x, y) (x, y)(x,y) 和時間 t t t がわかっている場合、オプティカル フロー方程式は次のように表すことができます。

∂ I ∂ x v x + ∂ I ∂ y v y + ∂ I ∂ t = 0 \frac{\partial I}{\partial x}v_x + \frac{\partial I}{\partial y}v_y + \frac{\partial I }{\部分 t} = 0xI x +yI y +tI =0

その中、 ∂ I ∂ x \frac{\partial I}{\partial x} xI ∂ I ∂ y \frac{\partial I}{\partial y} yI は空間次元での画像の明るさの勾配です。 ∂ I ∂ t \frac{\partial I}{\partial t} tI は時間次元での明るさの変化です。 v x v_x x v y v_y y x x のピクセルです。x y y y 方向の移動速度。

オプティカル フロー メソッドの課題は、この方程式には方程式が 1 つしかないのに、未知数が 2 つあることです ( v x v_x x v y v_y y )、したがって、これは不適切な問題です。この問題を解決するには、通常、平滑性制約などの追加の制約を導入するか、さまざまな技術やアルゴリズムを使用して解を近似する必要があります。

実際のアプリケーションでは、オプティカル フロー手法はノイズ、照明の変化、オクルージョンなどの要因の影響を考慮する必要があるため、通常は他のアルゴリズムやテクノロジと組み合わせて精度と堅牢性を向上させます。オプティカル フロー手法は、ターゲット追跡、シーン分析、3D 構造再構成などの多くの分野で広く使用されています。

5.2.3 コードの実装

ここでのコード実装は3.3.1 ビデオまたはカメラでのターゲット追跡に似ています。

ビデオまたはカメラでのオブジェクト追跡:

import cv2

# # 初始化摄像头
# cap = cv2.VideoCapture(0)
# 读取视频
cap = cv2.VideoCapture('video.mp4')

# Shi-Tomasi角点检测参数
feature_params = dict(maxCorners=100, qualityLevel=0.3, minDistance=7, blockSize=7)

# 读取第一帧
ret, old_frame = cap.read()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)

# 光流法参数
lk_params = dict(winSize=(15, 15), maxLevel=2, criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

# 使用Shi-Tomasi方法检测角点
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)

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

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

    # 计算光流
    p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)

    # 选取好的特征点
    good_new = p1[st==1]
    good_old = p0[st==1]

    # 绘制特征点
    for i, (new, old) in enumerate(zip(good_new, good_old)):
        a, b = new.ravel()
        c, d = old.ravel()
        frame = cv2.line(frame, (a, b), (c, d), (0, 255, 0), 2)
        frame = cv2.circle(frame, (a, b), 5, (0, 255, 0), -1)

    cv2.imshow('Optical Flow Tracking', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

    old_gray = frame_gray.copy()
    p0 = good_new.reshape(-1, 1, 2)

cap.release()
cv2.destroyAllWindows()

オプティカル フロー トラッキング

ここでのコード実装は3.3.2 ランダム アニメーションでのターゲット追跡に似ています。

ランダムアニメーションでのターゲット追跡:

import cv2
import Animation

animation = Animation.Animation(500, 400, 2)

# Shi-Tomasi角点检测参数
feature_params = dict(maxCorners=100, qualityLevel=0.3, minDistance=7, blockSize=7)

# 读取第一帧
old_frame = animation.get_frame()
old_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)

# 光流法参数
lk_params = dict(winSize=(15, 15), maxLevel=2, criteria=(cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))

# 使用Shi-Tomasi方法检测角点
p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)

while True:
    frame = animation.get_frame()
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 计算光流
    p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None, **lk_params)
    # 如果p1为None,重新检测特征点
    if p1 is None:
        p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, **feature_params)
        continue
    # 选取好的特征点
    good_new = p1[st == 1]
    good_old = p0[st == 1]

    # 绘制特征点
    for i, (new, old) in enumerate(zip(good_new, good_old)):
        a, b = new.ravel()
        c, d = old.ravel()
        frame = cv2.line(frame, (a, b), (c, d), (0, 255, 0), 2)
        frame = cv2.circle(frame, (a, b), 5, (0, 255, 0), -1)

    cv2.imshow('Optical Flow Tracking', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

    old_gray = frame_gray.copy()
    p0 = good_new.reshape(-1, 1, 2)

cv2.destroyAllWindows()

オプティカル フロー トラッキング

6. モデルベースの追跡

6.1 モデル追跡の原理

モデルベースの追跡は、数学的モデルを使用してターゲットを表現および追跡する方法です。この追跡テクノロジーは通常、事前定義されたターゲット モデルに依存します。ターゲット モデルは、幾何学的形状、オブジェクトの 3D モデル、または特定の特性を持つモデルなどです。追跡プロセスには、モデルと観測データの間の最適な適合を保証するためにモデル パラメーターを継続的に調整することが含まれます。

6.2 モデル追跡式

モデルベースの追跡では、モデル追跡の公式の中核は最適化問題、つまり最適なモデル パラメータを見つけることです θ \theta θ により、モデルの予測が実際の観測値にできるだけ近くなります。通常、これは損失関数を最小化することによって達成されます。損失関数は、予測値と実際の観測値の差を測定します。

と \mathbf{y} y は観測されたデータ ポイント (たとえば、画像内のターゲットの位置)、 f ( θ ) f(\シータ)f(θ) 是模型预测,其中 θ \theta θ 是模型的参数。目标函数 L ( θ ) L(\theta) L(θ)(通常称为损失函数)可以表示为:

L ( θ ) = ∑ i ( y i − f ( θ ) i ) 2 L(\theta) = \sum_{i}(y_i - f(\theta)_i)^2L(θ)= (yi f(θ)i )2

这里, L ( θ ) L(\theta) L(θ) 是实际观测值 y i y_i そしてi 和模型预测 f ( θ ) i f(\theta)_i f(θ)i 間の差の二乗和。目標は、パラメータ θ \theta を見つけることです。θ,使得 L ( θ ) L(\theta) L(θ) 不変 >

最適化

  1. 勾配降下法: これはパラメータを更新するために一般的に使用される最適化手法です θ \theta θ を使用して損失関数を最小化します。パラメータの更新式は次のとおりです。

    θ : = θ − α ∇ θ L ( θ ) \theta := \theta - \alpha \nabla_\theta L(\theta) 。:=αθ L(θ)

    其中, α \alpha α 範囲を決定します。 ∇ θ L ( θ ) \nabla_\theta L(\theta) θ L(θ) 是损失函数关于 θ \theta θ 的梯度。

  2. 反復法: 実際のアプリケーションでは、勾配降下法は複数回反復され、各反復は勾配の方向に従って更新されます。 θ \ シータ θ は、損失関数の最小値が見つかるか、特定の停止条件に達するまで続きます。

このように、モデルベースの追跡方法では、各フレームのモデル パラメータ θ \theta を調整できます。θ を使用して、ターゲットに関するモデルの記述が実際の観測データに可能な限り近くなるようにし、ターゲットの効果的な追跡を実現します。

6.3 コードの実装

注:以下方法只适合简单图形

ビデオまたはカメラでのオブジェクト追跡:

import cv2
import numpy as np

# # 初始化摄像头
# cap = cv2.VideoCapture(0)
# 读取视频
cap = cv2.VideoCapture('video2.mp4')

# 读取第一帧并定义初始矩形位置
ret, frame = cap.read()
init_pos = cv2.selectROI("Frame", frame, False)
cv2.destroyWindow("Frame")  # 关闭选择窗口
x, y, w, h = init_pos
track_window = (x, y, w, h)

# 设置ROI并计算直方图
roi = frame[y:y+h, x:x+w]
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv_roi, np.array((0., 60., 32.)), np.array((180., 255., 255.)))
roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0, 180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)

# 设置跟踪模型
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)

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

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)
    ret, track_window = cv2.CamShift(dst, track_window, term_crit)

    # 绘制跟踪结果
    pts = cv2.boxPoints(ret)
    pts = np.int0(pts)
    img2 = cv2.polylines(frame, [pts], True, 255, 2)

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

# 释放资源
cap.release()
cv2.destroyAllWindows()

この例では、モデルベースの追跡に CamShift アルゴリズムを使用します。 CamShift は、ターゲット サイズの変化に対応できる適応型追跡方法です。追跡を開始するとき、ユーザーは ROI (関心領域) を選択する必要があります。その後、アルゴリズムが ROI 内の色情報に基づいて後続のフレームで最適な一致を見つけます。

カムシフト
ランダムアニメーションでのターゲット追跡:

import cv2
import numpy as np
import Animation

animation = Animation.Animation(500, 400, 2)
# 读取第一帧并定义初始矩形位置
frame = animation.get_frame()
init_pos = cv2.selectROI("Frame", frame, False)
cv2.destroyWindow("Frame")  # 关闭选择窗口
x, y, w, h = init_pos
track_window = (x, y, w, h)

# 设置ROI并计算直方图
roi = frame[y:y + h, x:x + w]
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv_roi, np.array((0., 60., 32.)), np.array((180., 255., 255.)))
roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0, 180])
cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX)

# 设置跟踪模型
term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)

while True:
    frame = animation.get_frame()

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)
    ret, track_window = cv2.CamShift(dst, track_window, term_crit)

    # 绘制跟踪结果
    pts = cv2.boxPoints(ret)
    pts = np.int0(pts)
    img2 = cv2.polylines(frame, [pts], True, (0, 255, 0), 2)

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

# 释放资源
cv2.destroyAllWindows()

カムシフト

カムシフト

6.4 不正確な追跡と測位の理由

  1. 最初の ROI 選択: cv2.selectROI 関数を使用して、ビデオの最初のフレーム内の領域を手動で選択します。この領域の色情報は、追跡を初期化するために使用されます。

  2. カラー ヒストグラム: このコードは、選択した ROI の HSV 色空間のカラー ヒストグラムを計算します。このヒストグラムは、後続のフレームで同じまたは類似した色分布を持つ領域を検索するために使用されます。

  3. 色分布の依存: CamShift アルゴリズムのオブジェクト追跡能力は、初期 ROI の色分布に大きく依存します。ビデオ内の他のフレームに同様の色の分布がない場合、または追跡対象の色が大きく変化する場合、追跡効果は大幅に低下します。

  4. トラッキング ウィンドウの更新: 各フレームで、CamShift アルゴリズムはトラッキング ウィンドウの位置を更新し、最初のヒストグラムと同様の領域を一致させようとします。ターゲットが最初の ROI とは異なる色分布を持つ領域に移動すると、追跡が失敗する可能性があります。

  5. 環境要因: 照明の変化、オクルージョン、同系色の背景などの要因がトラッキングの精度に影響を与える可能性があります。

7. 学習ベースの追跡

7.1 学習追跡の原則

学習ベースの追跡方法には、機械学習アルゴリズムを使用してモデルをトレーニングし、ビデオ内のオブジェクトを識別して追跡することが含まれます。これらの方法には通常、特徴抽出、モデル トレーニング、オンライン追跡が含まれます。

  1. 特徴抽出: ビデオ フレームから効果的な特徴を抽出します。これは、ターゲットの重要な属性を表すことができます。

  2. モデル トレーニング: 抽出された特徴を使用して分類子または回帰モデルをトレーニングし、ターゲットと背景を区別します。

  3. オンライン トラッキング: トレーニングされたモデルをビデオ ストリームに適用し、ターゲットの変化に適応するためにモデル パラメータをリアルタイムで更新します。

OpenCV は、KCF (Kernelized Correlation Filters) や CSRT (Channel and Spatial Reliability Tracker) など、いくつかの組み込みの学習ベースのトラッカーを提供します。

7.2 KCFトラッカー

7.2.1 KCF トラッカーの原理と計算式

KCF トラッカーは相関フィルターの概念に基づいており、循環行列と高速フーリエ変換 (FFT) を使用して効率的にターゲット追跡を実現します。

1. 循環行列と相関
KCF トラッカーの中核は、トレーニング サンプル (つまり、ターゲットの周囲の画像パッチ) を変換することで達成される循環行列を構築することです。という循環構造。このような巡回行列により、高速フーリエ変換 (FFT) を通じてサンプル間の相関を効率的に計算できるようになり、計算速度が大幅に向上します。

2. 目的関数
KCF トラッカーの目的は、新しい画像フレームの応答関数を最大化するフィルターを学習することです。応答関数は次のように定義されます。
f ( w ) = ∑ i = 1 n ( y i − w T ϕ ( x i ) ) 2 + λ ∥ w ∥ 2 f(\mathbf{w }) = \sum_{i=1}^{n} \left( y_i - \mathbf{w}^T \phi(\mathbf{x}_i) \right)^2 + \lambda \|\mathbf{w }\| ^2 f(w)=i=1n (yi Tϕ(xi ))2+λw2
在这里, w \mathbf{w} w表示滤波器的权重, ϕ ( x i ) \phi(\mathbf{x}_i) ϕ(xi ) は、カーネル関数によってマップされた機能です。 y i y_i そしてi はターゲットの応答値、 λ \lambda λ は、過学習を防ぐために使用される正則化パラメータです。

3. カーネル相関
KCF は、カーネル技術を使用してデータを高次元の特徴空間にマッピングすることで、より複雑な特徴の関係をキャプチャできます。カーネル相関関数は次のように定義できます。
K ( x , z ) = ϕ ( x ) T ϕ ( z ) K(\mathbf{x}, \mathbf{z}) = \ファイ( \mathbf{x})^T \ファイ(\mathbf{z}) K(x,z)=ϕ(x)Tϕ(z)
里、 x \mathbf{x} x z \mathbf{z} z是特征向量,而 ϕ \phi ϕ はカーネル関数のマッピングです。

4. フィルタ トレーニング
フィルタ トレーニングには、上記の目的関数の最適解を解くことが含まれます。フーリエ変換とカーネル技術を使用すると、このプロセスを効率的に実行できます。

5. ターゲットの位置特定
新しいビデオ フレームでは、学習されたフィルタを使用して、ターゲットの位置を特定するための関連応答が計算されます。ターゲット位置は通常、応答プロットの最大値に対応します。

6. 更新メカニズム
ターゲットの外観の変化に適応するために、KCF トラッカーには新しい追跡結果に基づいてフィルターを段階的に更新するメカニズムが含まれています。

KCF トラッカーは、速度とパフォーマンスのバランスが優れていることで人気があります。 FFT とカーネル技術を使用することで、リアルタイム ビデオ ストリーム内のターゲットを効果的に追跡でき、高速追跡処理が必要なアプリケーション シナリオに特に適しています。

7.2.2 コードの実装

ビデオまたはカメラでのオブジェクト追跡:

import cv2

# 创建KCF跟踪器的实例
tracker = cv2.TrackerKCF_create()

# 读取视频
cap = cv2.VideoCapture('video.mp4')

# 读取视频的第一帧
ret, frame = cap.read()

# 选择要跟踪的目标
bbox = cv2.selectROI(frame, False)

# 初始化跟踪器
ok = tracker.init(frame, bbox)

while True:
    # 读取新的帧
    ret, frame = cap.read()
    if not ret:
        break

    # 更新跟踪器
    ok, bbox = tracker.update(frame)

    # 绘制跟踪框
    if ok:
        (x, y, w, h) = [int(v) for v in bbox]
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2, 1)

    # 显示结果
    cv2.imshow("Tracking", frame)

    # 退出条件
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放资源
cap.release()
cv2.destroyAllWindows()

KCF追跡
ランダムアニメーションでのターゲット追跡:

import cv2
import Animation

animation = Animation.Animation(500, 400, 10)

# 创建KCF跟踪器的实例
tracker = cv2.TrackerKCF_create()

# 读取视频的第一帧
frame = animation.get_frame()

# 选择要跟踪的目标
bbox = cv2.selectROI(frame, False)

# 初始化跟踪器
ok = tracker.init(frame, bbox)

while True:
    # 读取新的帧
    frame = animation.get_frame()

    # 更新跟踪器
    ok, bbox = tracker.update(frame)

    # 绘制跟踪框
    if ok:
        (x, y, w, h) = [int(v) for v in bbox]
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2, 1)

    # 显示结果
    cv2.imshow("Tracking", frame)

    # 退出条件
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放资源
cv2.destroyAllWindows()

KCF追跡


要約する

この記事の学習を通じて、移動物体検出とターゲット追跡の分野における OpenCV のアプリケーションについて包括的に理解できました。基本的な差分メソッドから複雑な学習トラッカーまで、各メソッドには独自の利点とアプリケーション シナリオがあります。差分法は単純ですが、特定の状況では非常に効果的です。テンプレート、機能、および密度ベースの方法は、より高い柔軟性と精度を提供し、より複雑なシナリオに適しています。モデルベースおよび学習ベースの方法は、ターゲット追跡テクノロジーの最新の進歩を表しており、非常に複雑な追跡環境を処理できます。

さまざまな追跡テクノロジにはそれぞれ独自の利点があり、さまざまな種類の問題の解決に適しています。ダイナミックに発展している分野として、コンピューター ビジョンとターゲット追跡テクノロジーにはまだ開発の余地が多く、将来的にはさらに多くの革新と画期的な進歩がもたらされることは間違いありません。

おすすめ

転載: blog.csdn.net/qq_31463571/article/details/134646806