ラベル 機械学習 の投稿を表示しています。 すべての投稿を表示
ラベル 機械学習 の投稿を表示しています。 すべての投稿を表示

2019年5月10日金曜日

Jetson Nano で MNISTをラズパイカメラから動かしてみる

あれから、MNIST関係色々見てました。
詳しいことはよくわからなかったけど、層をたくさん経由すると「deep」になるとのこと。
だから、前回のはディープラーニングではないようです。
とはいっても、根本的な意味はよくわかっていないので、今後の課題とします。
ざっくりとした理解だけれども、今回の教師あり学習に関して言えば、画像から分布を作って(学習)、その分布に当てはめて近い値が出たらそれが答えだ!的な感じっぽい。
ディープの部分は写経なんだけれども、学習データ保存して、読込して、カメラから画像取得して読み込んだ学習データに照らし合わせてリアルタイムに数字認識するプログラムを書いてみた。
参考にしたサイトのリンク貼っておきます。

http://blog.brainpad.co.jp/entry/2016/02/25/153000

https://qiita.com/JUN_NETWORKS/items/6514e017e89b9adbfb8d

https://qiita.com/tsutof/items/2d2248ec098c1b8d3e32

ソース見たほうが早いかな。

import tensorflow as tf
import numpy as np
import os,sys
import cv2
from PIL import Image, ImageEnhance,ImageDraw

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

def conv2d(x, W):
  return tf.nn.conv2d(x,W,strides=[1, 1, 1, 1],padding='SAME')

def max_pool_2x2(x):
  return tf.nn.max_pool(x,ksize=[1, 2, 2, 1],strides=[1, 2, 2, 1],padding='SAME')

x = tf.placeholder(tf.float32, shape=[None, 784])
y_ = tf.placeholder(tf.float32, shape=[None, 10])

# 画像をリシェイプ 第2引数は画像数(-1は元サイズを保存するように自動計算)、縦x横、チャネル
x_image = tf.reshape(x, [-1, 28, 28, 1])
print(x_image)

### 1層目 畳み込み層
# 畳み込み層のフィルタ重み、引数はパッチサイズ縦、パッチサイズ横、入力チャネル数、出力チャネル数
# 5x5フィルタで32チャネルを出力(入力は白黒画像なので1チャンネル)
W_conv1 = weight_variable([5, 5, 1, 32])
# 畳み込み層のバイアス
b_conv1 = bias_variable([32])
# 活性化関数ReLUでの畳み込み層を構築
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)

### 2層目 プーリング層
# 2x2のマックスプーリング層を構築
h_pool1 = max_pool_2x2(h_conv1)

### 3層目 畳み込み層
# パッチサイズ縦、パッチサイズ横、入力チャネル、出力チャネル
# 5x5フィルタで64チャネルを出力
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)

### 4層目 プーリング層
h_pool2 = max_pool_2x2(h_conv2)

### 5層目 全結合層
# オリジナル画像が28x28で、今回畳み込みでpadding='SAME'を指定しているため
# プーリングでのみ画像サイズが変わる。2x2プーリングで2x2でストライドも2x2なので
# 縦横ともに各層で半減する。そのため、28 / 2 / 2 = 7が現在の画像サイズ

# 全結合層にするために、1階テンソルに変形。画像サイズ縦と画像サイズ横とチャネル数の積の次元
# 出力は1024(この辺は決めです) あとはSoftmax Regressionと同じ
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])

h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

# ドロップアウトを指定
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

### 6層目 Softmax Regression層
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])

y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

### 訓練 ###
cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))


saver = tf.train.Saver()

config = tf.ConfigProto()
config.gpu_options.allow_growth = True
config.gpu_options.visible_device_list="0"
with  tf.Session(config=config) as sess:
  sess.run(tf.initialize_all_variables())

  os.makedirs("./model_2",exist_ok=True)

  ckpt = tf.train.get_checkpoint_state('./model_2')
  if ckpt:
    saver.restore(sess, ckpt.model_checkpoint_path)
  else:
    for i in range(1500):
      batch = mnist.train.next_batch(50)
      if i%100 == 0:
        train_accuracy = accuracy.eval(feed_dict={x:batch[0], y_: batch[1],keep_prob: 1.0})
        print("step %d, training accuracy %g"%(i, train_accuracy))
      train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

    saver.save(sess, "./model_2/model.ckpt")

  num_test = len(mnist.test.labels)
  sum_accuracy = 0
  for i in range(0, num_test, 50):
    sum_accuracy = sum_accuracy + accuracy.eval(feed_dict={x: mnist.test.images[i:i+50], y_: mnist.test.labels[i:i+50], keep_prob: 1.0})
  print("test accuracy:", sum_accuracy/(num_test/50))


  GST_STR = 'nvarguscamerasrc \
      ! video/x-raw(memory:NVMM), width=320, height=240, format=(string)NV12, framerate=(fraction)10/1 \
      ! nvvidconv ! video/x-raw, width=(int)320, height=(int)240, format=(string)BGRx \
      ! videoconvert \
      ! appsink'
  WINDOW_NAME = 'Camera Test'

  cap = cv2.VideoCapture(GST_STR, cv2.CAP_GSTREAMER)

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

    pilImg = Image.fromarray(np.uint8(img))
    #print(pilImg.format, pilImg.size, pilImg.mode)
    img_width, img_height = pilImg.size
    draw = ImageDraw.Draw(pilImg)
    draw.rectangle(((img_width - 150) // 2,
                         (img_height - 150) // 2,
                         (img_width + 150) // 2,
                         (img_height + 150) // 2), outline=(255, 255, 255))

    mnistImg = Image.fromarray(np.uint8(img))
    mnistImg = mnistImg.crop(((img_width - 150) // 2,
                         (img_height - 150) // 2,
                         (img_width + 150) // 2,
                         (img_height + 150) // 2))
    mnistImg = mnistImg.convert("L")
    color = ImageEnhance.Color(mnistImg)
    mnistImg = color.enhance(1.5)
    contrast = ImageEnhance.Contrast(mnistImg)
    mnistImg = contrast.enhance(1.5)
    brightness = ImageEnhance.Brightness(mnistImg)
    mnistImg = brightness.enhance(1.5)
    sharpness = ImageEnhance.Sharpness(mnistImg)
    mnistImg = sharpness.enhance(1.5)
    mnistImg = mnistImg.resize((28, 28), Image.LANCZOS)
    #print(mnistImg)
    mnistImg = map(lambda x: 255 - x, mnistImg.getdata())
    mnistImg = np.fromiter(mnistImg, dtype=np.uint8)
    mnistImg = mnistImg.reshape(1, 784)
    mnistImg = mnistImg.astype(np.float32)
    mnistImg = np.multiply(mnistImg, 1.0 / 255.0)
    # print(mnistImg)
    for i in range(len(mnistImg[0])):
      num=mnistImg[0][i]
      if num<0.4:
        print('    ', end="")
      else:
        print('%03d ' % (num*1000), end="")
      if i % 28 == 0:
        print('\n')

    #学習データと読み込んだ数値との比較を行う
    pred = sess.run(y_conv, feed_dict={x:mnistImg, y_: [[0.0] * 10], keep_prob: 1.0})[0]
    # print(pred)
    if not np.max(pred) < 0.5 :
      print(np.argmax(pred) ,np.max(pred))
      draw.text((10,10),f'{np.argmax(pred)} {round(np.max(pred)*100,2)}%')


    imgArray = np.asarray(pilImg)
    cv2.imshow(WINDOW_NAME, imgArray)

    key = cv2.waitKey(10)
    if key == 27: # ESC 
      break
起動すると、ウインドウが開いてカメラの画像が出ます。
真ん中の白枠に手書きの文字を入れると、上に値が出るってわけ。
認識率悪くて、コントラスト上げたり、明度あげたり、色々やってみてる。
コンソールに、プログラムからみたテンソルを表示しています。

色々やってて思ったのが、Jetson Nanoだと、何するにしてもメモリ不足で死にます。
これは、僕の書き方の問題なのかもしれないけど、いろいろシンドかった。
学習するにしても、バッチサイズ減らしてやらないと落ちるし、学習データの読み込みでも、ブラウザは落としておかないと死ぬ。
こういったあたりも、今後調べていきたい。
次は、自分で教師データ作って学ばせてあげたい。
できるかな?

2019年4月22日月曜日

Jetson Nano に Openpose 入れてみる

jetson nano 買ったからにはガンガン使わなくてはという謎の使命感から、僕でも知ってる超有名シリーズ「nightmare」「yolo」に続き、「Openpose」を入れてみることにしました。


セットアップ


セットアップは、こっちの前半に書いてあります。

https://toramamma.blogspot.com/2019/04/jetson-nano-darknet.html


インストール


基本はここを参考に、実際に打ったコマンドを書き残しておくスタンス。

https://qiita.com/myoshimi/items/cf64c91cd22c516bb49b


cmakeをインストール


$ sudo apt-get install qtbase5-dev build-essential gdebi libopencv-dev
$ wget https://github.com/Kitware/CMake/releases/download/v3.13.4/cmake-3.13.4.tar.gz
$ tar xzvf cmake-3.13.4.tar.gz
$ cd cmake-3.13.4
$ ./configure --qt-gui
$ ./bootstrap
$ make -j6
$ sudo make install


GPGPU関連


GPGPU関連のセットアップは終わってるものとしてスルー


Openposeのビルド


今までのもHome直下に入れてるので、若干パスをいじって入れる。

$ git clone https://github.com/CMU-Perceptual-Computing-Lab/openpose
$ cd openpose
$ sudo bash ./scripts/ubuntu/install_deps.sh
$ mkdir build
$ cd build
$ cmake ..
$ make -j4
$ sudo make install


実行


まずはサンプル動画をやってみまあす

$ cd ~/
$ ./build/examples/openpose/openpose.bin --write_json outputJSON/ --display 0 --model_folder ./models --video "./examples/media/video.avi" --write_video outputVideo.avi
OpenPose demo successfully finished. Total time: 1198.628352 seconds.

20分かかりました(汗)


では、リアルタイムをば・・・

$ ./build/examples/openpose/openpose.bin --model_folder ./models
Starting OpenPose demo...
Configuring OpenPose...
Starting thread(s)...
Auto-detecting camera index... Detected and opened camera 0.
Auto-detecting all available GPUs... Detected 1 GPU(s), using 1 of them starting at GPU 0.
Gtk-Message: 12:50:18.435: Failed to load module "canberra-gtk-module"

なんか、落ちたのでライブラリ入れます。

$ sudo apt install canberra-gtk*

実行してみます。

$ ./build/examples/openpose/openpose.bin --model_folder ./models

出ました!
0.2FPS!!

メモリ食いつぶしてますね。


解像度を下げてやってみます。

$ ./build/examples/openpose/openpose.bin --model_folder ./models --net_resolution 320x176

これで、2.3FPS達成!!
このくらい出ると、まあまぁ遊べるかな。


ホネホネが自分に合わせて動くサマを見ていると、あらためてすごい技術だなぁと思いました。

ちなみに、--face と --hand はリアルタイムでは動作しませんでした。
というのも、--face_net_resolution、--hand_net_resolutionを低めに設定しないと読み込まれず、低くすると精度悪くて検出できないようです。

次は何動かしてみようかな。

2019年4月19日金曜日

Jetson Nano 買ったので darknet で Nightmare と YOLO を動かすまで

巷で話題のJetson Nanoが届いたので、僕でも知ってる超有名シリーズ「darknet」入れて「nightmare」「yolo」あたりを動かしてみたいと思います。


準備



■ 周辺機器揃える


せっかくなので、はりきって電源は5V4Aで、ファンもつけました。


※追記 Jetson Nanoのファン購入に気をつけろ!
コチラの記事にあるように、5Vのファンじゃないと回らない(回りにくい?)ようなのでファンのリンクを追記しました。


一応こっちでも回ってます。



買ったものはこんなところか。
※ 良い子は技適は守ろう。

キーボードやマウス、ディスプレイは、そのへんに転がっているものでOK!!


■ セットアップ


https://dev.classmethod.jp/hardware/nvidia-jetson-nano-setup/

Etcherを使ってイメージを焼く。


■ 刹活孔を突く



・ フルパワー化


https://www.jetsonhacks.com/2019/04/10/jetson-nano-use-more-power/
$ sudo nvpmodel -m 0 
$ sudo jetson_clocks


・ スワップ作成


https://www.jetsonhacks.com/2019/04/14/jetson-nano-use-more-memory/

https://github.com/JetsonHacksNano/installSwapfile
$ cd installSwapfile
$ ./installSwapfile


・ カメラの確認


https://www.jetsonhacks.com/2019/04/02/jetson-nano-raspberry-pi-camera/

基本指すだけ
動いてるか確認する。

$ gst-launch-1.0 nvarguscamerasrc ! 'video/x-raw(memory:NVMM),width=3820, height=2464, framerate=21/1, format=NV12' ! nvvidconv flip-method=0 ! 'video/x-raw,width=960, height=616' ! nvvidconv ! nvegltransform ! nveglglessink -e


実践



■ CUDAサンプルとVisionWorksのサンプルの動作確認


https://gihyo.jp/admin/serial/01/ubuntu-recipe/0563?page=4


・ CUDA


$ cp -a /usr/local/cuda-10.0/samples/ ~/
$ cd ~/samples
$ make

すげー時間かかるので気長に待つ。
個別buildの方法もリンク先に書いてある。

ここにビルドされてるので、移動してそれっぽいやつ実行確認。

$ cd bin/aarch64/linux/release
$ ./deviceQuery
$ ./oceanFFT
$ ./smokeParticles
$ ./nbody


・ VisionWorks


$ /usr/share/visionworks/sources/install-samples.sh ~/visionworks/
$ cd ~/visionworks/VisionWorks-1.6-Samples/
$ make

時間かかるので気長に待つ。
ここにビルドされてるので、移動してそれっぽいやつ実行確認。

$ cd bin/aarch64/linux/release/
$ ./nvx_demo_hough_transform
$ ./nvx_demo_motion_estimation

ここまで動けば、環境的には何の問題もないはず。


本題



■ DARKNETインストール


http://takesan.hatenablog.com/entry/2019/04/09/001852
真ん中あたり、DARKNET(YOLO)のインストール


・ makefileの修正

makefileの修正で、-gencodeもコメントしないとダメでした。

GPU=1 # 修正
CUDNN=1 # 修正
CUDNN_HALF=1 # 修正
OPENCV=1 # 修正
AVX=0
OPENMP=0
LIBSO=0
ZED_CAMERA=0

# set GPU=1 and CUDNN=1 to speedup on GPU
# set CUDNN_HALF=1 to further speedup 3 x times (Mixed-precision on Tensor Cores) GPU: Volta, Xavier, Turing and higher
# set AVX=1 and OPENMP=1 to speedup on CPU (if error occurs then set AVX=0)

DEBUG=0

ARCH= -gencode arch=compute_30,code=sm_30 \
            -gencode arch=compute_35,code=sm_35 \
            -gencode arch=compute_50,code=[sm_50,compute_50] \
            -gencode arch=compute_52,code=[sm_52,compute_52] \
           # -gencode arch=compute_61,code=[sm_61,compute_61] # 修正

OS := $(shell uname)

# Tesla V100
# ARCH= -gencode arch=compute_70,code=[sm_70,compute_70]

# GeForce RTX 2080 Ti, RTX 2080, RTX 2070, Quadro RTX 8000, Quadro RTX 6000, Quadro RTX 5000, Tesla T4, XNOR Tensor Cores
# ARCH= -gencode arch=compute_75,code=[sm_75,compute_75]

# Jetson XAVIER
# ARCH= -gencode arch=compute_72,code=[sm_72,compute_72]

# GTX 1080, GTX 1070, GTX 1060, GTX 1050, GTX 1030, Titan Xp, Tesla P40, Tesla P4
# ARCH= -gencode arch=compute_61,code=sm_61 -gencode arch=compute_61,code=compute_61

# GP100/Tesla P100 - DGX-1
# ARCH= -gencode arch=compute_60,code=sm_60

# For Jetson TX1, Tegra X1, DRIVE CX, DRIVE PX - uncomment:
ARCH= -gencode arch=compute_53,code=[sm_53,compute_53]  # 修正

# For Jetson Tx2 or Drive-PX2 uncomment:
# ARCH= -gencode arch=compute_62,code=[sm_62,compute_62]
  :


・ make


$ PATH=/usr/local/cuda/bin:$PATH make

気長に待つ。


・実行


ビルドできてれば以下が出力されるはず。

$ ./darknet
usage: ./darknet <function>


■ Nightmare


$ wget http://pjreddie.com/media/files/vgg-conv.weights
$ ./darknet nightmare cfg/vgg-conv.cfg vgg-conv.weights data/scream.jpg 10


なんだか、結果がポクない。。
なにか間違えたか?


■ YOLO


$ wget https://pjreddie.com/media/files/yolov3.weights
$ ./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg


リアルタイムは、raspi camera 繋がってるんだけど、camera stopedとかなって終わった。

$ ./darknet detector demo cfg/coco.data cfg/yolov3.cfg yolov3.weights

引き続き実験。


--------- 追記 ----------------------------------------

$ sudo apt-get install libv4l-dev v4l-utils
$ v4l2-ctl --list-devices
vi-output, imx219 6-0010 (platform:54080000.vi:0):
 /dev/video0
$ v4l2-ctl -d /dev/video0 --all
Driver Info (not using libv4l2):
 Driver name   : tegra-video
 Card type     : vi-output, imx219 6-0010
 Bus info      : platform:54080000.vi:0
 Driver version: 4.9.140
 Capabilities  : 0x84200001
  Video Capture
  Streaming
  Extended Pix Format
  Device Capabilities
 Device Caps   : 0x04200001
  Video Capture
  Streaming
  Extended Pix Format
Priority: 2
Video input : 0 (Camera 0: no power)
Format Video Capture:
 Width/Height      : 640/480
 Pixel Format      : 'RG10'
 Field             : None
 Bytes per Line    : 1280
 Size Image        : 614400
 Colorspace        : sRGB
 Transfer Function : Default (maps to sRGB)
 YCbCr/HSV Encoding: Default (maps to ITU-R 601)
 Quantization      : Default (maps to Full Range)
 Flags             : 

Camera Controls

                     group_hold 0x009a2003 (bool)   : default=0 value=0 flags=execute-on-write
                    sensor_mode 0x009a2008 (int64)  : min=0 max=0 step=0 default=0 value=0 flags=slider
                           gain 0x009a2009 (int64)  : min=0 max=0 step=0 default=0 value=16 flags=slider
                       exposure 0x009a200a (int64)  : min=0 max=0 step=0 default=0 value=13 flags=slider
                     frame_rate 0x009a200b (int64)  : min=0 max=0 step=0 default=0 value=2000000 flags=slider
                    bypass_mode 0x009a2064 (intmenu): min=0 max=1 default=0 value=0
                override_enable 0x009a2065 (intmenu): min=0 max=1 default=0 value=0
                   height_align 0x009a2066 (int)    : min=1 max=16 step=1 default=1 value=1
                     size_align 0x009a2067 (intmenu): min=0 max=2 default=0 value=0
               write_isp_format 0x009a2068 (bool)   : default=0 value=0
       sensor_signal_properties 0x009a2069 (u32)    : min=0 max=0 step=0 default=0 flags=read-only, has-payload
        sensor_image_properties 0x009a206a (u32)    : min=0 max=0 step=0 default=0 flags=read-only, has-payload
      sensor_control_properties 0x009a206b (u32)    : min=0 max=0 step=0 default=0 flags=read-only, has-payload
              sensor_dv_timings 0x009a206c (u32)    : min=0 max=0 step=0 default=0 flags=read-only, has-payload
               low_latency_mode 0x009a206d (bool)   : default=0 value=0
                   sensor_modes 0x009a2082 (int)    : min=0 max=30 step=1 default=30 value=5 flags=read-only

カメラ生きてるっぽいよね。

----------------------------------------


--------- 追追記 ----------------------------------------

Logicool HD c270なら動きました。


これの無地のやつ。
メモリ使い切って死ぬ寸でしたが・・・
スワップ作っといてよかった。

$ ./darknet detector demo cfg/coco.data cfg/yolov3.cfg yolov3.weights


terminalの方見るとわかりますが、2FPSとかです。
実用には耐えません^^

----------------------------------------


--------- 追追追記 ----------------------------------------

tiny yolo v3なら、15FPS位出てラズパイで初めてLチカしたときくらいの満足感が得られました。

$ wget https://pjreddie.com/media/files/yolov3-tiny.weights
$ ./darknet detector demo cfg/coco.data cfg/yolov3-tiny.cfg yolov3-tiny.weights

----------------------------------------

ということで、一応 Darknet 動かすところまでできました。
そもそもこの手の情報なにもない素人レベルでしたが、動かすだけなら割と簡単にできました。

お熱があるうちに、遅ればせながら機械学習のお勉強でも始めようかな。