はじめに
TouchDesignerでOpenCVやっていきます。導入からMobileNetSSDまで。
開発環境
- Windows10(RTX2080 Max-Q、i7-8750H、RAM16GB)
- TouchDesigner 2020.24520
- Anaconda 2020.02
- Python 3.7
- OpenCV 4.0
導入
TouchDesignerからインストールします。
サインインして、Keyを作成しましょう。
OpenCVを入れる
メニューのDialog->Textport and DATsを開きます。
下記プログラムを実行して、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へのパスを指定します。
C:\Users\gachimoto\anaconda3\envs\td\lib\site-packages
これで、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にします。
TouchDesigner で Python を使ってみよう!(2) #外部エディタの使い方を参考に、スクリプトをVSCodeで編集するように設定しましょう。
C:\Users\gachimoto\AppData\Local\Programs\Microsoft VS Code\Code.exe
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]に表示してみましょう。
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で人検出結果を切り取り表示することができます。
人検出して切り取り表示#MobileNetSSD #TouchDesigner #OpenCV #Python pic.twitter.com/wf6BEvNDUV
— 藤本賢志(ガチ本)@pixivFANBOXはじめました (@sotongshi) June 19, 2020
お疲れ様でした。
追記
def onPostCook(changeOp):
image = changeOp.numpyArray(delayed=True)
image = np.array(image)
image = np.uint8(image * 255.0)
image = np.flipud(image)
この画像入力の逆をやってTOPに画像をreturnしたいのですが、どうやるんでしょうか?