[OpenCV] 一定期間動かないものだけを撮影する

2020.03.02

1 はじめに

CX事業本部の平内(SIN)です。

OpenCVでは、背景差分という手法で、動くものだけを検出する作業がよく紹介されています。

今回は、店舗で商品の監視など場合などに、お客さんの伸ばした手や、人影などが、その監視にノイズとなって入ることを避けるため、「動かないもの」のみを撮影してみました。

商品のように数が増減するものは、監視の対象となりますので、背景差分のように、最初に完全な背景を設定するのではなく、前のフレームとの差分を確認しながら、「一定期間 動かないもの」を撮影するイメージです。

最初に、動作している様子を御覧ください。 左が、監視画面で、右は、普通のモニターです。手などが入ってきても、それは、無視されます。

2 差分検出

1つ前のフレームとの比較を行う場合、差分検出を単純化させるため、以下の処理としました。

  1. フレーム画像をグレースケールに変換する
  2. 2つの画像の差分画像を生成する
  3. 差分画像を2値化する
  4. 2値化した画像の白の要素(変化部分)数をカウントする

最終的にカウントされた白の要素(変化部分)数が、敷居値(threshold=1000)以下の場合は、変化がないと判断して、カウンターをインクリメントします。

カウンターが静止間隔(span=50 50フレーム 2秒弱)を超えたら、画面は静止していると判断し、監視画面を更新します。

3 コード

全てのコードは、以下のとおりです。

import cv2

# 2値化
def binarization(img, threshold=100):
    ret, img = cv2.threshold(img, threshold, 255, cv2.THRESH_BINARY)
    return img

# 差分を数値化
def getDiff(img1, img2):
    # グレースケール変換
    img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
    img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
    # 差分取得
    mask = cv2.absdiff(img1, img2)
    # 2値化
    mask = binarization(mask)
    return cv2.countNonZero(mask) # 白の要素数


span = 50  # 静止間隔
threshold = 1000 # 変化の敷居値

# 動画ファイルのキャプチャ
cap = cv2.VideoCapture(1)
cap.set(cv2.CAP_PROP_FPS, 30) 
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 420)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)

# 最初のフレームを背景画像に設定
ret, previous = cap.read()

counter=0

while(cap.isOpened()):
    # フレームの取得
    ret, frame = cap.read()

    # 差分計算    
    diff = getDiff(previous, frame)

    if(diff < threshold):
        counter+=1
    else:
        counter=0

    print("diff:{} counter:{}".format(diff,counter))

    # 一定以下の変化量が、一定時間続いたら描画する
    if(span < counter):
        counter = 0
        # 監視画面を更新
        cv2.imshow("previous", frame)

    # フレームを表示
    cv2.imshow("Flame", frame)

    # 今回のフレームを1つ前として保存する
    previous = frame

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

cap.release()
cv2.destroyAllWindows()

4 利用例

参考に、この「動かないものだけ撮影する」仕組みで、機械学習のモデルの精度を試している様子です。

Amazon Rekognition Custom Labelsを使用しています。私の作ったモデルは、けっして精度が良いとは言えませんが、数枚(12枚です)の写真でモデルが作成出来てしまうところが凄いと思います。

モデルの精度をテストをする場合も、できるだけ短い時間のRUNNINGで、より効果的に確認を行うためには、このようなやり方も悪くないかも知れません。

5 最後に

今更ですが、動画、画像を扱う場合、OpenCVのようなツールで必要な画像処理を加えることは、サービスを組み立てる上で必須だと思います。

何をどのように組み合わせると、どのような事ができるのか、日頃から色々確認しておく事が必要でしょう。