”プライバシーに配慮したAIカメラ”を、OpenVINOを使って無料で作ってみよう!

このご時世、「お店や施設の混雑状況が分かると嬉しいですね。でもプライバシーにも配慮しないとね。」というAIカメラ製品・ソリューションがいろいろと出てきていますね。今回はそれをOpenVINOで無料でやってみようという試みです。

実際に使う場合はいろいろと考慮する点がありますが、やっつけ的に実装していますので何かとご容赦ください。

実行結果

まずは実行結果からご覧ください。

使用した動画

https://github.com/intel-iot-devkit/sample-videos

face-demographics-walking.mp4 を使いました。

実行結果と比較するとわかりますが、無事、誰かわからないようになっていますね。

考え方

OpenVINOで人検出(person-detection)を行い、検出した人の位置を利用して、静止画に置き換えるという流れになります。

参考までに、検出した人の上に静止画を載っけると、以下のような状態になります。位置をそのまま利用していることがわかりますね。

検出したエリアをモザイク処理するという事でも良いですが、記号化することでよりプライバシーに配慮している。ということになるのでしょうか。

使用した部品など

”OpenVINOを簡単に扱えるラッパー”をyas-simさんが公開されていますので、今回はそちらを利用させて頂きました。ありがとうございます!

https://github.com/yas-sim/openvino-wrapper

また、マスク処理について、様々なページを参考にさせて頂きました。ありがとうございます!

全体のフォルダ構成

intelフォルダ配下には、モデル(person-detection-retail-0013)を格納しています。

ソース・使用画像

さて、ようやく本題のプログラムになります。繰り返しになりますが、やっつけ的な部分があります。動作検証ということでご理解ください。

image_compose.py

## fncImgCompose(front_img, back_img, size, pos)
##
## front_image ... charactor
## back_image  ... background
## size        ... size of charactor(x,y)
## pos         ... position of charactor(x,y)

import cv2
import numpy as np

def fncMakeMask(figure):

    # HSV に変換する。
    hsv = cv2.cvtColor(figure, cv2.COLOR_BGR2HSV)

    # 2値化する。
    bin_img = cv2.inRange(hsv, (0, 10, 0), (255, 255, 255))

    # 輪郭抽出する。
    contours, _ = cv2.findContours(bin_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 面積が最大の輪郭を取得する
    contour = max(contours, key=lambda x: cv2.contourArea(x))

    # マスク画像を作成する。
    mask = np.zeros_like(bin_img)
    cv2.drawContours(mask, [contour], -1, color=255, thickness=-1)

    return mask


def fncImgCompose(front_img, back_img, size, pos):
    
    # front_image ... charactor
    # back_image  ... background
    # size  ... size of charactor(x,y)
    # pos   ... position of charactor(x,y)

    front_img = cv2.resize(front_img,size)
    mask = fncMakeMask(front_img)

    x, y = pos
    
    # 幅、高さは前景画像と背景画像の共通部分をとる
    w = min(front_img.shape[1], back_img.shape[1] - x)
    h = min(front_img.shape[0], back_img.shape[0] - y)

    # 合成する領域
    fg_roi = front_img[:h, :w]               # 前景画像のうち、合成する領域
    bg_roi = back_img[y : y + h, x : x + w]  # 背景画像のうち、合成する領域

    # 合成する。
    bg_roi[:] = np.where(mask[:h, :w, np.newaxis] == 0, bg_roi, fg_roi)

    return back_img

person_detection_async.py

import iewrap

import time

import cv2
import numpy as np
import image_compose as img_cmp

imgBuf = {}

def callback(infId, output):
    global imgBuf,im_back

    output = output.reshape((200,7))
    img = imgBuf.pop(infId)
    img_h, img_w, _ = img.shape

    im_figure = cv2.imread(r'rsc/figure_standing.jpg')
    
    for obj in output:
        imgid, clsid, confidence, x1, y1, x2, y2 = obj
        if confidence>0.5:              # Draw a bounding box and label when confidence>0.8
            x1 = int(x1 * img_w)
            y1 = int(y1 * img_h)
            x2 = int(x2 * img_w)
            y2 = int(y2 * img_h)

            #cv2.rectangle(im_back, (x1, y1), (x2, y2), (255,0,0), thickness=4 ) #blue

            im_back = img_cmp.fncImgCompose(im_figure, im_back, (x2-x1,y2-y1),(x1,y1))

    cv2.imshow('result',im_back)
    cv2.waitKey(1)


def main():
    global imgBuf,im_back

    cap = cv2.VideoCapture(r'.\rsc\mov\face-demographics-walking.mp4')
    
    ie = iewrap.ieWrapper(r'.\intel\person-detection-retail-0013\FP16\person-detection-retail-0013.xml', 'CPU', 10)
    ie.setCallback(callback)

    while True:
        ret, img = cap.read()
        if ret==False:
            break

        img = cv2.resize(img,(1600,900))    
        im_back = cv2.imread(r'rsc/background.png')

        refId = ie.asyncInfer(img)     # Inference
        imgBuf[refId]=img

if __name__ == '__main__':
    main()

画像

background.png
figure_standing.jpg

実行結果

上記プログラムを実行すると、以下の結果が得られます。OpenVINOを使って人の位置を検出するという部分までは本当にお手軽に確認出来るので、あとは画像の料理次第ですね!ぜひお試しください。

ご参考

今回の環境はこちらです。渋谷の交差点のライブカメラなどではさすがに処理が増えてしまいますが、普段使いの場合は問題は無いと思います。

  • Windows 10 home (20H2)
  • Intel(R) Core(TM) i5-7260U CPU @ 2.20GHz
  • メモリ 4GB
  • OpenVINO 2021.1
  • person-detection-retail-0013\FP16\person-detection-retail-0013