pythonで2リンクの逆運動学を解いて表示する
pythonで2リンク逆運動学を計算して2次元で表示します。
プログラム
・2リンク問題を逆運動学で算出してmatplotlibで表示しています
・Px,Pyが手先目標座標なので、使用するときは変更してください
・L1,L2のリンクの長さは直接指定しているので、使用するときは変更してください
・計算結果はprint文とグラフ上に表示されます
・エラー系は実装していません
import math import numpy import matplotlib.pyplot as plt fig = plt.figure() #アーム手先座標 Px = 6 Py = 7.5 #Linkの長さ L1 = 10 L2 = 10 #逆運動学計算↓ L3 = math.sqrt((Px*Px) + (Py*Py)) fai2 = math.acos(((L1*L1) + (L2*L2) - ( L3 * L3)) / (2*L1*L2)) tht2 = math.pi - fai2 fai1 = math.acos(((L1*L1) + (L3 * L3) - (L2*L2)) / (2*L1*L3)) fai0 = math.atan(Py / Px) tht1 = math.atan2(Py , Px) - fai1 #角度計算↓ #deg1 = math.degrees(tht1) #deg2 = math.degrees(tht2) #表示のために順運動学計算する #リンク1の座標算出 #数式↓ #x =L1cos(tht1) #y =L2sin(tht1) #プログラム↓ x1 = L1 * numpy.cos(tht1) y1 = L1 * numpy.sin(tht1) #リンク1の座標算出 #数式↓ #x2 =L1cos(tht1)+L2cos(tht1+th2) #y2 =L1sin(tht1)+L2sin(tht1+th2) #プログラム↓ x2 = x1 + L2 * numpy.cos((tht1+tht2)) y2 = y1 + L2 * numpy.sin((tht1+tht2)) #計算結果表示↓ print(x1) print(x2) print(y1) print(y2) #算出結果を格納 #リンクは[x,y]=[0,0]から表示するため最初の要素に0を代入 x = [0, x1, x2] y = [0, y1, y2] #表示 #リンクの座標表示↓ plt.text(x1, y1, x1, verticalalignment='bottom', horizontalalignment='right',color='green', fontsize=8) plt.text(x1, y1-0.8, y1,verticalalignment='bottom', horizontalalignment='right',color='green', fontsize=8) plt.text(x2, y2, x2,verticalalignment='bottom', horizontalalignment='right',color='green', fontsize=8) plt.text(x2, y2-0.8, y2, verticalalignment='bottom', horizontalalignment='right',color='green', fontsize=8) #線分表示↓ plt.plot(x,y,"r-") #表示実行 plt.show()
pythonで2リンク順運動学を解いて表示する
pythonで2リンク順運動学を計算して2次元で表示します。
プログラム
・2リンク問題を順運動学で算出してmatplotlibで表示しています。
・L1,L2のリンクの長さは直接指定しているので使用するときは変更してください
・deg1,deg2はリンクの角度なので使用するときは変更してください
・計算結果はprint文とグラフ上に表示されます
・エラー系は実装していません
import math import numpy import matplotlib.pyplot as plt fig = plt.figure() #Linkの長さ L1 = 10 L2 = 10 #各リンクの角度指定 deg1 = 30 deg2 = 50 #リンク1の座標算出 #数式↓ #x =L1cos(tht1) #y =L2sin(tht1) #プログラム↓ x1 = L1 * numpy.cos(math.radians(deg1)) y1 = L1 * numpy.sin(math.radians(deg1)) #リンク1の座標算出 #数式↓ #x2 =L1cos(tht1)+L2cos(tht1+th2) #y2 =L1sin(tht1)+L2sin(tht1+th2) #プログラム↓ x2 = x1 + L2 * numpy.cos(math.radians(deg1+deg2)) y2 = y1 + L2 * numpy.sin(math.radians(deg1+deg2)) #計算結果表示↓ print(x1) print(x2) print(y1) print(y2) #算出結果を格納 #リンクは[x,y]=[0,0]から表示するため最初の要素に0を代入 x = [0, x1, x2] y = [0, y1, y2] #表示 #リンクの座標表示↓ plt.text(x1, y1, x1, verticalalignment='bottom', horizontalalignment='right',color='green', fontsize=8) plt.text(x1, y1-0.8, y1,verticalalignment='bottom', horizontalalignment='right',color='green', fontsize=8) plt.text(x2, y2, x2,verticalalignment='bottom', horizontalalignment='right',color='green', fontsize=8) plt.text(x2, y2-0.8, y2, verticalalignment='bottom', horizontalalignment='right',color='green', fontsize=8) #線分表示↓ plt.plot(x,y,"r-") #表示実行 plt.show()
websocketでRaspberryPiからwindowsPCに画像を送る(Python)
Raspberypi3から webscketで画像をあげて、PC側で取得・表示までやります。
概要図↓
実行画面↓
開発環境
- win10 64bit
python3.5.2
openCV3.1.0
- Raspberrypi3
Raspbian Debian Stretch - Version:September 2017
python3.5.2
RaspberryPi側開発
構成
Raspberry Piのカメラモジュールで撮った映像をWebSocketでブラウザに送る!! - ami_GS's diary
ラズパイの方は、ほぼ上記参考HPのまま使っています。
今回は自分の環境でエラーが出たところを修正しました。
また、IP固定はあらかじめしておいてください。
ーーここ引用ーー
camera.py
RPi側でブラウザからのアクセスを受け付けるwebサーバ、及びカメラから映像を撮り、ブラウザへ送る。
index.html
WebSocketでブラウザに送られてきた画像を表示する。
ーーーーーーーー
インストール
pip3 install websocket pip3 install tornado
camera.py
import time import picamera import io import tornado import tornado.httpserver import tornado.websocket import tornado.ioloop import tornado.web import socket from threading import Thread WIDTH = 480 HEIGHT = 360 FPS = 30 class HttpHandler(tornado.web.RequestHandler): def initialize(self): pass def get(self): self.render("./index.html") #最初のHTTPアクセスを受け付け、WebSocket接続を確立させるスクリプトが入ったindex.htmlを返す class WSHandler(tornado.websocket.WebSocketHandler): def initialize(self, camera): self.camera = camera self.state = True def open(self): print(self.request.remote_ip, ": connection opened") t = Thread(target=self.loop) #撮影&送信スレッドの作成 t.setDaemon(True) t.start() def loop(self): stream = io.BytesIO() for foo in self.camera.capture_continuous(stream, "jpeg"): stream.seek(0) self.write_message(stream.read(), binary=True) stream.seek(0) stream.truncate() if not self.state: break def on_close(self): self.state = False #映像送信のループを終了させる self.close() #WebSocketセッションを閉じる print(self.request.remote_ip, ": connection closed") def piCamera(): camera = picamera.PiCamera() camera.resolution = (WIDTH, HEIGHT) camera.framerate = FPS camera.start_preview() time.sleep(2) #カメラ初期化 return camera def main(): camera = piCamera() print("complete initialization") app = tornado.web.Application([ (r"/", HttpHandler), #最初のアクセスを受け付けるHTTPハンドラ (r"/camera", WSHandler, dict(camera=camera)), #WebSocket接続を待ち受けるハンドラ ]) http_server = tornado.httpserver.HTTPServer(app) http_server.listen(8080) tornado.ioloop.IOLoop.instance().start() if __name__ == "__main__": main()
index.html
<html> <head> <title>livecamera</title> <img id="liveImg" src="" width="480" height="360"> <script type="text/javascript"> var img = document.getElementById("liveImg"); var arrayBuffer; //WebSocketでサーバに接続 var ws = new WebSocket("ws://192.168.1.201:8080/camera"); ws.binaryType = 'arraybuffer'; //受診するデータがバイナリであるので設定 ws.onopen = function(){console.log("connection was established");}; //接続が確立した時に呼ばれる ws.onmessage = function(evt){ arrayBuffer = evt.data; //受信したデータを復号しbase64でエンコード img.src = "data:image/jpeg;base64," + encode(new Uint8Array(arrayBuffer)); }; window.onbeforeunload = function(){ //ウィンドウ(タブ)を閉じたらサーバにセッションの終了を知らせる ws.close(1000); }; function encode (input) { var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; var output = ""; var chr1, chr2, chr3, enc1, enc2, enc3, enc4; var i = 0; while (i < input.length) { chr1 = input[i++]; chr2 = i < input.length ? input[i++] : Number.NaN; // Not sure if the index chr3 = i < input.length ? input[i++] : Number.NaN; // checks are needed here enc1 = chr1 >> 2; enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); enc4 = chr3 & 63; if (isNaN(chr2)) { enc3 = enc4 = 64; } else if (isNaN(chr3)) { enc4 = 64; } output += keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4); } return output; } </script> </head> </html>
*WebSocketでサーバに接続する部分のIPアドレスを自分のラズパイのIPに書き換えてください
起動
上の2つのプログラムを同じフォルダに置いて実行します。
python camera.py
ブラウザでwindowsPCからラズパイIPにアクセスするとリアルタイム画像が表示されます。
Windows側開発
構成
client.py
websocketのクライアント文とOpenCVでの画像表示になります。
インストール
pip3 install websocket-client
client.py
#-*- coding:utf-8 -*- from websocket import create_connection import sys import base64 from io import BytesIO import cv2 import numpy as np ws = create_connection("ws://192.168.1.201:8080/camera") # decode while True: arr = np.asarray(bytearray(ws.recv()), dtype=np.uint8) img = cv2.imdecode(arr, -1) # 'load it as it is' cv2.imshow('image', img) cv2.waitKey(10) cv2.destroyAllWindows() ws.close()
*create_connectionのアドレスをラズパイのアドレスに書き換えてください
起動
こっちを起動する前にラズパイの方を起動させておいてください。
ラズパイ起動確認後、以下で実行
python client.py
ウインドウが表示され、ラズパイが取得している画像が表示されます
初めてwebsocketやりました。
おわり
[参考]
Raspberry Piのカメラモジュールで撮った映像をWebSocketでブラウザに送る!! - ami_GS's diary
【技術】pythonでwebsocketを試してみた - エンジニアリングとお金の話
PicameraによるRaspberry Pi 3カメラモジュールのカメラ設定 | TomoSoft
Pythonの画像読み込み: PIL, OpenCV, scikit-image - Qiita
YoLo/darknet初期学習データで判別できる種類一覧
github等でYOLO、YOLOv2、darknetでよく用意されている学習データをそのまま適用したときに
判別できる種類の一覧は、以下の全80種類になります。
人 自転車 車 バイク 飛行機 バス 列車 トラック ボート 信号機 消火栓 一時停止標識 パーキングメーター ベンチ 鳥 ネコ 犬 馬 羊 牛 ゾウ くま シマウマ キリン バックパック 傘 ハンドバッグ ネクタイ スーツケース フリスビー スキー スノーボード スポーツボール 凧 野球用バット 野球グローブ スケートボード サーフボード テニスラケット ボトル ワイングラス カップ フォーク ナイフ スプーン ボウル バナナ 林檎 サンドイッチ オレンジ ブロッコリ にんじん ホットドッグ ピザ ドーナツ ケーキ 椅子 ソファー 鉢植え ベッド ダイニングテーブル トイレ テレビモニター ノートPC マウス リモコン キーボード 携帯電話 電子レンジ オーブン トースター シンク 冷蔵庫 本 時計 花瓶 はさみ テディベア ヘアドライヤー 歯ブラシ
元の英語では
person bicycle car motorbike aeroplane bus train truck boat traffic light fire hydrant stop sign parking meter bench bird cat dog horse sheep cow elephant bear zebra giraffe backpack umbrella handbag tie suitcase frisbee skis snowboard sports ball kite baseball bat baseball glove skateboard surfboard tennis racket bottle wine glass cup fork knife spoon bowl banana apple sandwich orange broccoli carrot hot dog pizza donut cake chair sofa pottedplant bed diningtable toilet tvmonitor laptop mouse remote keyboard cell phone microwave oven toaster sink refrigerator book clock vase scissors teddy bear hair drier toothbrush
BBoX-Label-ToolをPython3で使用する
BBoX-Label-Toolはpyhotn2.7で作成されているので3系では起動しません。
そこで今回はpython3系で起動できるようにします。
[環境]
win7 64bit
python3.5
[ソースダウンロード]
以下から本体をダウンロードします
github.com
[python3系に編集]
DL後、解凍。
main.pyを開きます。
10 from Tkinter import * 11 import tkMessageBox
の部分を削除して
try: import tkinter import tkinter.messagebox except: import Tkinter as tkinter import tkMessageBox from tkinter import *
に書き換え
あとはpython3用にprint文にカッコを追記して
python main.py
私の環境ではpythonで3系が起動します。
これで起動できたと思います。
ちなみに画像フォルダはimages/002とか作ってそこにいれても画像が読み込めない?事態がおきますので、
その場合は001に入っている初期画像を消して、自分の学習させたい画像を001に移動させます。
そしてBBoxを起動させてフォルダパスのところに"1"と数字のみ入れてloadすると読み込めるはずです。
おわり
Darknetをwindows10にインストールして物体認識・物体判別をする
今までChainerやTensorflowなどで記述された物体認識・物体判別をしてきましたが
今回はYoloV2の制作者がC言語製作したdarknetをwindowsPCにインストールして試してみました。
[環境]
windows7 64bit
python3.5.2
VisualStudio2015
OpenCV3.2
[OpenCVインストール]
OpenCV3.2をダウンロードします
*製作者はOpenCV3.0でやっていますがファイル関係のエラーでできなかったため3.2でやっています
OpenCV 3.2 - OpenCV library
ここの一番下の”Windows self-extracting archive:”からexeをダウンロードします
exeを実行し、C:\直下に定してインストール
環境設定に
[DarkerNetビルド]
https://github.com/AlexeyAB/darknet
ここにアクセスしてzipをダウンロード
ダウンロードしたファイルを解凍し、
次に”darknet.sln”を実行(VisualStudio2015)
VisualStudioが起動したら、
プラットフォームを”x64”に構成を”Release”に変更
ビルド→darknetのリビルドを実行
以下エラー除去
・include失敗、見つからない
プロジェクト→プロパティ→VC++ディレクトリ→インクルードディレクトリ右の▼→編集→C:\opencv\build\includeを追加
・opencv_world320.libが見つからない、参照できない
プロジェクト→プロパティ→VC++ディレクトリ→ライブラリディレクトリ右の▼→編集→C:\opencv\build\x64\vc14\libを追加
*1.CUDA8.0ではなくて他のバージョンをお持ちの場合は、メモ帳を使用してbuild\darknet\darknet.vcxprojを開き、
”CUDA 8.0”で2か所探して自分のCUDAバージョンに変更して、リビルドを実行してください。
*2.GPUがない人はbuild\darknet\darknet_no_gpu.slnで実行してください
*3.OpenCV2.4.13の人はパスを変更してください
・(right click on project) -> properties -> C/C++ -> General -> Additional Include Directories:
C:\opencv_2.4.13\opencv\build\include
・(right click on project) -> properties -> Linker -> General -> Additional Library Directories:
C:\opencv_2.4.13\opencv\build\x64\vc14\lib
*4.OpenCV2.4.**の人はさらにパス変更が必要なようです
\src\detector.c等を開き、”#pragma comment(lib, "opencv_core2413.lib"”などを変更
無事ビルドが終了したら”darknet-master\darknet-master\build\darknet\x64”にexeができています。
[DarkerNet実行]
コマンドプロンプトを起動して以下に移動
”darknet_voc.cmd”
以下エラー除去
・opencv_world320.libが見つからない、参照できない
C:\opencv\build\x64\vc14\bin\opencv_world320.dllをdarknet_voc.cmdを生成したexeと同じフォルダにコピー
・opencv_ffmpeg320_64.dllが見つからない、参照できない
C:\opencv\build\x64\vc14\bin\opencv_ffmpeg320_64.dllをdarknet_voc.cmdを生成したexeと同じフォルダにコピー
以下実行結果
\darknet-master\darknet-master\build\darknet\x64>darknet.exe detector test data/voc.data yolo-voc.cfg yolo-voc.weights -i 0 -thresh 0.2 layer filters size input output 0 conv 32 3 x 3 / 1 416 x 416 x 3 -> 416 x 416 x 32 1 max 2 x 2 / 2 416 x 416 x 32 -> 208 x 208 x 32 2 conv 64 3 x 3 / 1 208 x 208 x 32 -> 208 x 208 x 64 3 max 2 x 2 / 2 208 x 208 x 64 -> 104 x 104 x 64 4 conv 128 3 x 3 / 1 104 x 104 x 64 -> 104 x 104 x 128 5 conv 64 1 x 1 / 1 104 x 104 x 128 -> 104 x 104 x 64 6 conv 128 3 x 3 / 1 104 x 104 x 64 -> 104 x 104 x 128 7 max 2 x 2 / 2 104 x 104 x 128 -> 52 x 52 x 128 8 conv 256 3 x 3 / 1 52 x 52 x 128 -> 52 x 52 x 256 9 conv 128 1 x 1 / 1 52 x 52 x 256 -> 52 x 52 x 128 10 conv 256 3 x 3 / 1 52 x 52 x 128 -> 52 x 52 x 256 11 max 2 x 2 / 2 52 x 52 x 256 -> 26 x 26 x 256 12 conv 512 3 x 3 / 1 26 x 26 x 256 -> 26 x 26 x 512 13 conv 256 1 x 1 / 1 26 x 26 x 512 -> 26 x 26 x 256 14 conv 512 3 x 3 / 1 26 x 26 x 256 -> 26 x 26 x 512 15 conv 256 1 x 1 / 1 26 x 26 x 512 -> 26 x 26 x 256 16 conv 512 3 x 3 / 1 26 x 26 x 256 -> 26 x 26 x 512 17 max 2 x 2 / 2 26 x 26 x 512 -> 13 x 13 x 512 18 conv 1024 3 x 3 / 1 13 x 13 x 512 -> 13 x 13 x1024 19 conv 512 1 x 1 / 1 13 x 13 x1024 -> 13 x 13 x 512 20 conv 1024 3 x 3 / 1 13 x 13 x 512 -> 13 x 13 x1024 21 conv 512 1 x 1 / 1 13 x 13 x1024 -> 13 x 13 x 512 22 conv 1024 3 x 3 / 1 13 x 13 x 512 -> 13 x 13 x1024 23 conv 1024 3 x 3 / 1 13 x 13 x1024 -> 13 x 13 x1024 24 conv 1024 3 x 3 / 1 13 x 13 x1024 -> 13 x 13 x1024 25 route 16 26 conv 64 1 x 1 / 1 26 x 26 x 512 -> 26 x 26 x 64 27 reorg / 2 26 x 26 x 64 -> 13 x 13 x 256 28 route 27 24 29 conv 1024 3 x 3 / 1 13 x 13 x1280 -> 13 x 13 x1024 30 conv 125 1 x 1 / 1 13 x 13 x1024 -> 13 x 13 x 125 31 detection Loading weights from yolo-voc.weights...Done! Enter Image Path:
使用する画像を尋ねられるからサンプルに付属している画像のパスを入れる
Enter Image Path: ***\darknet-master\darknet-master\data\dog.jpg ***\darknet-master\darknet-master\data\dog.jpg: Predicted in 0.038000 seconds. car: 75% bicycle: 77% dog: 91% ^Cバッチ ジョブを終了しますか (Y/N)? y
Ctrl+Cを打ってyで終了する
実行結果↓
[参考HP]
「darknet」C言語で機械学習!とりあえずインストールとmake、エラーの対処をしてみた - lisz-works
DarknetをWindowsにインストールする - TadaoYamaokaの日記
YOLOv2を使って自前のデータを学習させて認識させるまで。 - 可変ブログ
OpenCV3.2インストール方法(ビルドなし) - Qiita
ChainerでYOLOv2をやってみる [訓練/学習編]
前回ChainerでYOLOv2をやったという記事にアクセスがまぁまぁあったので、
下書きのままだったYOLOv2の訓練/学習編を書いていきます。(メモ程度ですがご容赦ください)
YOLOv2の訓練手順(製作者様)↓
YOLOv2/YOLOv2_animal_train.md at master · leetenki/YOLOv2 · GitHub
[環境]
Ubuntu16.04
python3.5.2
*windows7 64bitでも可能だと思います
[インストール]
以下のものを入れてない人は入れてください
pip3 install mock
pip3 install cupy
[画像収集]
・backup
・sample_images
・items
・backgrounds
以上の4つのフォルダを新規作成してください。
次に画像を収集します
python download_images.py
itemsフォルダ内に画像がダウンロードされたか確認します。
[画像生成]
python image_generate.py
で画像がランダムに作られていきます。
ここでエラーが起こるので少し変更しました。
random_overlay_image関数の74,75行目の部分でエラーが起こります。
y = int(np.random.randint(src_h-scale_item_h)) - int(shift_item_h) x = int(np.random.randint(src_w-scale_item_w)) -int( shift_item_w)
変更した関数ごとを載せます。
def random_overlay_image(src_image, overlay_image, minimum_crop): src_h, src_w = src_image.shape[:2] overlay_h, overlay_w = overlay_image.shape[:2] shift_item_h, shift_item_w = overlay_h * (1-minimum_crop), overlay_w * (1-minimum_crop) scale_item_h, scale_item_w = overlay_h * (minimum_crop*2-1), overlay_w * (minimum_crop*2-1) a = src_h-scale_item_h b = src_w-scale_item_w if a <= 1: a = 100 if b <= 1: b = 100 c = int(np.random.randint(a) - shift_item_h) d = int(np.random.randint(b) - shift_item_w) if c < 0: c = int(np.random.randint(a)) if d < 0: d = int(np.random.randint(a)) y = (int(c)) x = (int(d)) image = overlay(src_image, overlay_image, x, y) bbox = ((np.maximum(x, 0), np.maximum(y, 0)), (np.minimum(x+overlay_w, src_w-1), np.minimum(y+overlay_h, src_h-1))) return image, bbox
はい、汚いですすみません。とにかくrandintにマイナスを入れないようにすればいいと思います。
今回は恐竜のほかにカービーを混ぜました。それに伴い、パラサウロロフスさんは消去しました。
追加したカービー↓
とてもかわいいですね。
もう一度image_generate.pyを実行して確認します。
[darknet19(画像識別器)の訓練・テスト]
今回カービーを追加したのでdata/label.tetラベルを書き換えます。
Tyrannosaurus Brachiosaurus Triceratops Riopururodon Rhino Dog Erasmosaurus Ammonite kirby Deer
*パラサウロロフスさんは消去しました。
*順番も順守
訓練
python darknet19_train.py
訓練終了後、テストします。
python darknet19_predict.py items/kirby.png
以下、結果です
[darknet19_448の訓練・重み切り出し]
訓練する
python darknet19_448_train.py
backupフォルダにdarknet19_448_final.modelが保存されたか確認
つぎに重み切り出し
python partial_weights.py
backupフォルダにpartial.modelが保存されたか確認
[YOLOv2の訓練・テスト]
python yolov2_train.py
ここで私のPCではメモリ不足になってしまったので
88行目のloss.backward()の下に
loss.unchain_backward()
を追加します。
*これでメモリが解放されますが学習にどう響くかは不明です。。。
ちなみに3日~1週間の間、学習処理をしました。
無事、訓練が終わったらテストです。
しかし、テストするまえに
yolov2_predict.pyの12行目を変更を出力したモデルの名前に書き換えます
12 weight_file = "./backup/yolov2_final_cpu.model" ↓ 12 weight_file = "./backup/yolov2_final.model"
認識テスト実行
python yolov2_predict.py test.jpg
テスト画像↓
結果
以上、終わりです。
[参考]
Chainer2.0がリリース【今後の安定版】とりあえず抑えておきたい変更点 - HELLO CYBERNETICS
chainer-object-detection/model/yolov2 at master · dsanno/chainer-object-detection · GitHub