Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

TouchDesignerでOpenCVをはじめーる(Windows10、Python3.7、OpenCV4.0)

はじめに

TouchDesignerでOpenCVやっていきます。導入からMobileNetSSDまで。

開発環境

  • Windows10(RTX2080 Max-Q、i7-8750H、RAM16GB)
  • TouchDesigner 2020.24520
  • Anaconda 2020.02
  • Python 3.7
  • OpenCV 4.0

導入

TouchDesignerからインストールします。
サインインして、Keyを作成しましょう。

開いたらこんな感じ。
image.png

OpenCVを入れる

メニューのDialog->Textport and DATsを開きます。
image.png

下記プログラムを実行して、PythonとOpenCVのバージョンと場所を確認しましょう。

python >>> import sys
python >>> sys.version
'3.7.2 (heads/3.7-Derivative:052feb9e72, Mar  7 2019, 16:29:45) [MSC v.1900 64 bit (AMD64)]'
python >>> import cv2
python >>> cv2.__version__
'4.0.0'
python >>> cv2
<module 'cv2.cv2' from 'C:\\Program Files\\Derivative\\TouchDesigner\\bin\\lib\\site-packages\\cv2\\cv2.cp37-win_amd64.pyd'>

同じ環境をanacondaで作成しましょう。opencv-contribも入れます。

conda create -n td python=3.7
conda activate td
pip install opencv-python
pip install opencv-contrib-python

anaconda promptを開いて、pythonインタプリタを開き、OpenCVの場所を確認します。

(td) C:\Users\good_\Documents\PythonProjects>python
Python 3.7.7 (default, May  6 2020, 11:45:54) [MSC v.1916 64 bit (AMD64)] :: Anaconda, Inc. on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> cv2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'cv2' is not defined
>>> import cv2
>>> cv2
<module 'cv2.cv2' from 'C:\\Users\\gachimoto\\anaconda3\\envs\\td\\lib\\site-packages\\cv2\\cv2.cp37-win_amd64.pyd'>

anacondaで作成したpydファイルをC:\Program Files\Derivative\TouchDesigner\bin\lib\site-packages\cv2\へ上書きします。

TouchDesignerで機械学習(ObjectDetection)動かしてみたを参考に、メニューのEdit->Preferencesを開き、Python 64-bit Module Pathにanacondaで作成した環境のsite-packagesへのパスを指定します。
image.png

C:\Users\gachimoto\anaconda3\envs\td\lib\site-packages

image.png

これで、OpenCVが使えるようになります。
Increment Filename on SaveをOffにしておくと、ファイルを保存した時に数字が付かなくなります。
(※TouchDesigner のパフォーマンスチューニング & TIPS #バージョン管理は他でやる事が多いのでバックアップは作らない

画像サイズを取得してみる

VideoDeviceIn[TOP]、Null[TOP]、Script[CHOP]を配置します。script1_callbacksを削除し、OP Execute[DAT]を配置し、opexec1のMonitor OPsにnull1を指定、Post CookをONにします。
image.png

image.png

TouchDesigner で Python を使ってみよう!(2) #外部エディタの使い方を参考に、スクリプトをVSCodeで編集するように設定しましょう。

C:\Users\gachimoto\AppData\Local\Programs\Microsoft VS Code\Code.exe

image.png

opexec1のEditからscriptを以下のように編集します。

import cv2
import numpy as np

def onPostCook(changeOp):
    image = changeOp.numpyArray(delayed=True)
    image = np.array(image)
    image = np.uint8(image * 255.0)
    image = np.flipud(image)
    gray = image[:, :, 0]

    out = op('script1')
    out.clear()
    out.numSamples = 1
    w = out.appendChan('w')
    h = out.appendChan('h')
    ch = out.appendChan('ch')
    h[0], w[0] = gray.shape
    ch[0] = 1
    return

script1に画像サイズ(幅、高さ、チャンネル数)が表示されたら完了です。

DNNモジュールを用いて人検出してみる

OpenCVのDNNモジュールを用いて、MobileNetSSDで人検出した値(BoundingBoxの左上の座標(x, y)と幅と高さ(w,h))をScript[CHOP]に表示してみましょう。

image.png

MobilNet_SSD_opencvをダウンロードし、MobileNetSSD_deploy.prototxt、MobileNetSSD_deploy.caffemodelを、TouchDesignerのプロジェクトと同じフォルダに置いてください。

opexec1のスクリプトを以下のように編集してください。

import cv2
import numpy as np


def onPostCook(changeOp):
    image = changeOp.numpyArray(delayed=True)
    image = np.array(image)
    image = np.uint8(image * 255.0)
    image = np.flipud(image)
    image = cv2.cvtColor(image, cv2.COLOR_RGBA2BGR)

    out = op('script1')
    out.clear()

    inWidth = 300
    inHeight = 300
    inScaleFactor = 0.007843
    meanVal = 127.5
    classNames = ('background', 'aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat', 'chair', 'cow',
                  'diningtable', 'dog', 'horse', 'motorbike', 'person', 'pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor')
    net = cv2.dnn.readNetFromCaffe(
        "MobileNetSSD_300x300.prototxt", "MobileNetSSD_train.caffemodel")
    blob = cv2.dnn.blobFromImage(
        image, inScaleFactor, (inWidth, inHeight), meanVal, swapRB=True, crop=False)
    net.setInput(blob)
    detections = net.forward()

    cols = image.shape[1]
    rows = image.shape[0]
    persons = []
    for i in range(detections.shape[2]):
        class_id = int(detections[0, 0, i, 1])
        if classNames[class_id] == 'person':
            confidence = detections[0, 0, i, 2]
            if confidence > 0.2:
                xLeftBottom = int(detections[0, 0, i, 3] * cols)
                yLeftBottom = int(detections[0, 0, i, 4] * rows)
                xRightTop = int(detections[0, 0, i, 5] * cols)
                yRightTop = int(detections[0, 0, i, 6] * rows)
                w = float(xRightTop - xLeftBottom)
                h = float(yRightTop - yLeftBottom)
                x = float((xRightTop + xLeftBottom)/2.0)
                y = float(rows - (yRightTop + yLeftBottom)/2.0)
                persons.append([x, y, w, h])
                # cv2.rectangle(image, (xLeftBottom, yLeftBottom),
                #               (xRightTop, yRightTop), (0, 255, 0))
                # label = classNames[class_id] + ": " + str(confidence)
                # labelSize, baseLine = cv2.getTextSize(
                #     label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 1)
                # cv2.rectangle(image, (xLeftBottom, yLeftBottom - labelSize[1]), (
                #     xLeftBottom + labelSize[0], yLeftBottom + baseLine), (255, 255, 255), cv2.FILLED)
                # cv2.putText(image, label, (xLeftBottom, yLeftBottom),
                #             cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 0))
                # cv2.imwrite("dnn.png", image)

    if len(persons) > 0:
        out.numSamples = len(persons)
    else:
        out.numSamples = 1

    x = out.appendChan('x')
    y = out.appendChan('y')
    w = out.appendChan('w')
    h = out.appendChan('h')

    if len(persons) > 0:
        for index, person in enumerate(persons):
            x[index] = person[0]
            y[index] = person[1]
            w[index] = person[2]
            h[index] = person[3]
    else:
        x[0] = 0.
        y[0] = 0.
        w[0] = 0.
        h[0] = 0.

    return

TouchDesignerでOpenCVを使った簡単な顔認識についてを参考にして、ごにょごにょするとrenderで人検出結果を切り取り表示することができます。

お疲れ様でした。

追記

def onPostCook(changeOp):
    image = changeOp.numpyArray(delayed=True)
    image = np.array(image)
    image = np.uint8(image * 255.0)
    image = np.flipud(image)

この画像入力の逆をやってTOPに画像をreturnしたいのですが、どうやるんでしょうか?

参考文献

SatoshiGachiFujimoto
高専で制御を学び、大学でセンシングを学び、次は脳みそ。SLAMに関連したロボット/ドローンやMRの研究開発をしています。
https://www.gachimoto.com
knowledgecommunication-inc
クラウドインテグレーター、AI・VRの分野で様々なソリューションを展開
http://www.knowledgecommunication.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away