LoginSignup
35
30

More than 3 years have passed since last update.

アート作品の鑑賞状況をOpenCVで可視化する

Last updated at Posted at 2020-10-01

概要

  • アート作品の価値を可視化するシステムを作りたいと、福岡のアーティストの方より依頼があった。
  • アート作品をどれだけの人が、どのくらいの時間鑑賞したかをできるだけ安価なシステムで実現できないか検討した。
  • RaspberryPiをアート作品の前に設置し、OpenCVで顔検出した時間を累積することとした。
  • データ可視化サービスとしてAmbient(https://ambidata.io) を使った。
  • データのアップロードはRaspberryPiのWifi経由とした。
  • インターネットにカメラ映像は流れず、送信する数値データのみとすることにした。

スクリーンショット 2020-10-01 9.18.26.png
福岡市のスタートアップ支援施設 FGN(https://growth-next.com) に設置し運用してみた様子。
スクリーンショット 2020-10-01 9.24.23.png
IMG_4946.jpeg
IMG_4945.jpeg

用意するもの

  • Raspberry Pi3 Model B (4でもおそらく大丈夫)
  • Raspberry Pi用のケース
  • Raspberry Pi用のヒートシンク
  • Raspberry Pi3 Model B B+ 対応 電源セット(5V 3.0A)
  • aspberry Pi用のカメラ
  • HDMI入力が付いたモニターまたはTV
  • 100円ショップの三脚

準備

  • RaspberryPiのセットアップをしWifi接続できるようにしておく。
    https://www.raspberrypi.org/downloads/
  • OpenCVとAmbient(IoTの可視化サービス)のライブラリが使用できるようにしておく。
  • Ambientにてダッシュボードを作成し、チャネルIDとライトキーを取得しておく。
    https://ambidata.io/refs/python/

プログラミング

  • OpenCVとAmbient(IoTの可視化サービス)のライブラリを使用
  • 顔検出のフレーム、5分毎の訪問数、総滞在時間をカメラ映像にオーバーレイ表示
  • 5分毎の訪問数、総滞在時間Ambientに送信し可視化
  • 訪問数のカウントは顔検出された時間よりおおまかに推定
  • およそ3週間の展示だったため、CPU温度も取得しAmbientに送信
detect_face_camera.py
import sys

sys.path.append('/home/pi/.local/lib/python2.7/site-packages')

import numpy as np

import cv2

import time

import datetime

import ambient

args = sys.argv

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')

cap = cv2.VideoCapture(0)

flg = 0

stime =  0

am = ambient.Ambient(xxxx, 'xxxxxxxxxxxxxxxx')  #AmbientのチャネルID/ライトキー(訪問数・滞在時間)

am2 = ambient.Ambient(xxxx, 'xxxxxxxxxxxxxxxx')  #AmbientのチャネルID/ライトキー(CPU温度)

acnt = 0

while(True):

    t3 = time.time()

    cnt = 0

    ret, frame = cap.read()

    # 読み込んだ画像の高さと幅を取得

    height = frame.shape[0]

    width = frame.shape[1]

    import sys

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

    faces = face_cascade.detectMultiScale(gray, 1.3, 5)

    for (x,y,w,h) in faces:

        t1 = time.time()

        cv2.rectangle(frame,(x,y),(x+w,y+h),(152,145,234),2)

        roi_gray = gray[y:y+h, x:x+w]

        roi_color = frame[y:y+h, x:x+w]

        eyes = eye_cascade.detectMultiScale(roi_gray)

        cnt += 1

        for (ex,ey,ew,eh) in eyes:

            cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(108,97,232),2)

        t2 = time.time()

        stime += (t2 - t1) * 1000 / 60

        acnt = acnt + cnt

    cv2.putText(frame, 'count: ' + str(acnt / 100), (10, 420), cv2.FONT_HERSHEY_DUPLEX, 1.0, (0,255,0), thickness=2)

    cv2.putText(frame, 'stay[sec]: ' + str('{:.1f}'.format(stime)), (10, 460), cv2.FONT_HERSHEY_DUPLEX, 1.0, (0,255,0), thickness=2)

    cv2.putText(frame, 'senseart v.0.0.1b', (410, 20), cv2.FONT_HERSHEY_PLAIN, 1.5, (0,255,0), thickness=2)

    resized_img = cv2.resize(frame,(width*2, height*2))

    cv2.imshow('senceart (v.0.0.1 beta)', resized_img)

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

        break

    t4 = time.time()

    f = open("/sys/class/thermal/thermal_zone0/temp","r")  #CPU温度

    for t in f:

        tmp = t[:2]+"."+t[2:5]

    f.close()

    fps = cap.get(cv2.CAP_PROP_FPS)

    now = datetime.datetime.now() 

    minute = '{0:%M}'.format(now)

    second = '{0:%S}'.format(now)

    print('count', acnt / 100)

    print('stay', stime)

    print("minute", minute)

    print("second", second)

    print("temp", tmp)

    print("\n")

    if int(minute) % 5 == 0 and int(second) == 0:

        r = am.send({'d1': acnt / 100, 'd2': stime})  #訪問数と滞在時間をAmbientに送る

        r = am2.send({'d1': tmp})  #CPU温度をAmbientに送る

        r.close()
        acnt = 0

        cnt = 0

        print("******************sended*****************\n")

        continue

    if int(minute) % 10 == 0 and int(second) == 0:

        r = am.send({'d1': acnt / 100, 'd2': stime})  #訪問数と滞在時間をAmbientに送る

        r = am2.send({'d1': tmp})  #CPU温度をAmbientに送る

        r.close()

        acnt = 0

        cnt = 0

        print("******************sended*****************\n")

        continue

cap.release()
  • RaspberryPiのデスクトップにシェルスクリプトを設置し、Pythonのプログラムが起動するようにしておく。
  • 現場のオペレーションとして、アイコンのダブルクリックで起動するようにしておく。
senceart.sh
#! /bin/bash
cd /home/pi/opencv_programs/
sudo python3 detect_face_camera.py

注意点

  • 当初、福岡市の公衆Free Wifi(時間制限なし)で接続をしていたが、数日で切断されてしまったのでWifiルーター経由に切り替えた。(原因不明…)
  • リモートメンテナンス(今回は広島→福岡)ができるようVNC等リモート操作ソフトが必要。
  • トラブル発生時に現地の施設スタッフがある程度対応できるようマウス・キーボード・マニュアルが必要。

使ってみて

  • 3週間のうち1度だけダウンしたが、概ね安定して動いた。
  • 実験的なものだったので、訪問数のカウントロジックが詰めきれていない。何度も実地検証をしてみる必要がある。
  • 動作は軽いとは言えなかったので、RaspberryPi4でどの程度パフォーマンスが上がるのか興味がある。
35
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
35
30