空飛ぶロボットのつくりかた

ロボットをつくるために必要な技術をまとめます。ロボットの未来についても考えたりします。

PyQtのお勉強

MyEnigmaさんの以下の記事が非常にわかりやすい↓

myenigma.hatenablog.com

環境設定

sudo apt-get install python-qt4

解説内容

  1. Windowを作る
  2. ステータスバーに文字などを表示する
  3. メニューバーを作る
  4. ツールバーを作る
  5. 一行のフォームに文字や数値を表示する
  6. 複数行のテキストボックスを作る
  7. 表形式のGUIの作り方
  8. スライダーGUIを作る
  9. タブのGUIを作る
  10. プログレスバーGUIを作る
  11. メッセージボックスを作る
  12. ウィジェットをグループ化する
  13. リスト選択のGUIを作る
  14. ラジオボタンを使う

ロボットをGazebo + ROS(kinetic)上で作って、動かしてみる

Gazebo ROS Demos

GitHub - ros-simulation/gazebo_ros_demos: Example robots and code for interfacing Gazebo with ROS

Quick Start

Rviz:

roslaunch rrbot_description rrbot_rviz.launch

Gazebo:

roslaunch rrbot_gazebo rrbot_world.launch

ROS Control:

roslaunch rrbot_control rrbot_control.launch

Example of Moving Joints:

rostopic pub /rrbot/joint2_position_controller/command std_msgs/Float64 "data: -0.9"

手順通り3つとも立ち上げようとするが、ここでエラー発生

下記をインストールして解決

sudo apt-get install ros-kinetic-ros-control ros-kinetic-ros-controllers

sudo apt-get install ros-kinetic-gazebo-ros-control 

参考:ROS Kinetic + Gazebo 7.0で簡単なロボットシミュレーション - あくまで個人的メモ用ブログ

Gazebo+URDF

とてもわかり易い!↓

ROSで始めるロボティクス(3) ー 差動二輪ロボットを準備する ~ BRILLIANTSERVICE TECHNICAL BLOG

ROSで始めるロボティクス(4) ー シミュレータ上でロボットを動かしてみる ~ BRILLIANTSERVICE TECHNICAL BLOG

ROSで始めるロボティクス(5) ー GazeboでToFセンサーをシミュレーションする ~ BRILLIANTSERVICE TECHNICAL BLOG

実行結果 f:id:robonchu:20170902201100p:plain

Freeの3DCAD

DesignSpark Mechanical Download and Installation

Gazebo + ROS で自分だけのロボットをつくる 4.URDFファイルをつくる ref: http://qiita.com/RyodoTanaka/items/174e82f06b10f9885265 · GitHub

参考:

ROS練習用のロボットを作る - Qiita

Gazebo + ROS で自分だけのロボットをつくる 5. GazeboとROSの連携 - Qiita

Gazebo + ROS で自分だけのロボットをつくる 4.URDFファイルをつくる ref: http://qiita.com/RyodoTanaka/items/174e82f06b10f9885265 · GitHub

ros.youtalk.jp — URDFを使ったロボットモデルの記述

ROSによるマニピュレータの制御 - 研究紹介ページ

rosのurdfとlaunchファイルを作成して、モデルをrvizで確認する方法 : 試行錯誤な日々

ROS勉強記録: URDFファイルを作る

http://www.cst.nihon-u.ac.jp/research/gakujutu/60/pdf/E-9.pdf

ROS演習8:ロボットアーム | demura.net

ROSで始めるロボティクス(3) ー 差動二輪ロボットを準備する ~ BRILLIANTSERVICE TECHNICAL BLOG

毎日がロボット勉強会: 6.3 独自ロボットをシミュレータで試す

cir-kit.github.io

HOG+SVMで物体認識(OpenCV3)

HOG+SVM

HOG : 局所領域 (セル) の輝度の勾配方向をヒストグラム

SVM : サポートベクターマシン(SVM)

2class の分類を行う

  • sample1とsample2ディレクトリに分類したい画像を同じ枚数用意
  • 予測したい画像を用意(test.png

実行方法

python hog_svm_2class.py test.png

そうすると、0 or 1 で予測された結果が返ってくる

hog_svm_2class.py

# -*- coding: utf-8 -*

import os
import glob
import sys

import cv2
import numpy as np

bin_n = 32 # need adjustment

# 画像が存在するディレクトリの代入
images_1 = glob.glob('sample1/*.*')
images_2 = glob.glob('sample2/*.*')

hist_list1 = []
hist_list2 = []

def hog(img):
    gx = cv2.Sobel(img, cv2.CV_32F, 1, 0)
    gy = cv2.Sobel(img, cv2.CV_32F, 0, 1)
    mag, ang = cv2.cartToPolar(gx, gy)
    bins = np.int32(bin_n*ang/(2*np.pi))    # quantizing binvalues in (0...16)
    hists = np.bincount(bins.ravel(), mag.ravel(), bin_n)
    return hists

for image1, image2 in zip(images_1 , images_2):
    img1 = cv2.imread(image1, 0)
    img1_roi = img1[160:320, 120:320]
    hist1 = hog(img_roi)
    hist_list1.append(hist1)

    img2 = cv2.imread(image2, 0)
    img2_roi = img2[160:320, 120:320]
    hist2 = hog(img_roi)
    hist_list2.append(hist2)

train_data1 = np.array(hist_list1, np.float32)
train_data2 = np.array(hist_list2, np.float32)
trainingDataMat = np.r_[train_data1, train_data2]

label_list = [0]*(len(images_1)+len(images_2))
label_list[len(images_1):] = [1]*len(images_2)
labelsMat = np.array([label_list], np.int32)

# Train the SVM
svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_RBF)  # RBF1が良さげ
#svm.setDegree(0.0)
svm.setGamma(5.4)
#svm.setCoef0(0.0)
svm.setC(2.7)
#svm.setNu(0.0)
#svm.setP(0.0)
#svm.setClassWeights(None)
svm.setTermCriteria((cv2.TERM_CRITERIA_COUNT, 100, 1.e-06))
svm.train(trainingDataMat, cv2.ml.ROW_SAMPLE, labelsMat)

# TEST 
test_hist_list = []
img = cv2.imread(sys.argv[1], 0)
img_roi = img[160:320, 120:320]
hist = hog(img_roi)
test_hist_list.append(hist)

test_data = np.array(test_hist_list, np.float32)
testDataMat = test_data
response = svm.predict(testDataMat)
print response[1]

参考:

画像からHOG特徴量の抽出 - Qiita

 Nobutobook: 【Python × OpenCV】 歩行者検知でやってること

 Nobutobook: 【Python × OpenCV】 はじめての歩行者検知

HOG特徴量を用いたポケモンのアイコン画像判別 - Qiita

メソッドまとめ

参考:

opencv 3.1.0 SVMのサンプルのPython版 - sieste31の日記

HOG + SVMで人物検出【OpenCV & Python】 - ysku's blog

SVMを使った手書き文字の文字認識 — OpenCV-Python Tutorials 1 documentation

OpenCV-Python Tutorials (6) ~Image Processing in OpenCV~ - 脱初心者を目指す

opencv チュートリアル チャレンジ9 OpenCVにおける輪郭(領域) - 機械学習備忘録

opencv/digits.py at master · npinto/opencv · GitHub

OpenCVでHSV変換を行い黒検出をしたいのですがなかなか上手く... - Yahoo!知恵袋

HOG特徴とSVMによる物体検出

OpenCV 備忘録: OpenCVでHOG特徴量+SVMで人物検出を行う 1

HOG特徴量とSVMを使った自動車の検出 - くーろんログ

HOGとSVMを使った人物検出 - ニートがプログラミングするブログ

dlibによるHOG特徴を用いた物体検出がすごい - kivantium活動日記

http://www.vision.cs.chubu.ac.jp/sift/PDF/pcsjimps2008_ppt.pdf

PSA(ピクセル状態分析)+Joint HOG + AdaBoost

http://www.vision.cs.chubu.ac.jp/ssii08/ssii08-yamashita.pdf

GitHub - bikz05/object-detector: Object Detection Framework using HOG as descriptor and Linear SVM as classifier.

MPRG : 機械知覚&ロボティクスグループ/中部大学

MPRG : 機械知覚&ロボティクスグループ/中部大学

http://www.vision.cs.chubu.ac.jp/joint_hog/pdf/HOG+Boosting_LN.pdf

openCVで物体認識 by traincascade - Qiita

http://www.mi.t.u-tokyo.ac.jp/harada/lectures/IIT/internal/09_object_detection_20160713.pdf

CVPR 2017 速報 - SSSSLIDE

↓この子すごい。要チェック。

輪郭検出でマスクを自動生成する | OpenCV画像解析入門

画像の明るさを正規化する | OpenCV画像解析入門

Hough変換で直線、円検出をやってみる

import cv2
import numpy as np

img = cv2.imread('dave.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)

lines = cv2.HoughLines(edges,1,np.pi/180,200)
for rho,theta in lines[0]:
    a = np.cos(theta)
    b = np.sin(theta)
    x0 = a*rho
    y0 = b*rho
    x1 = int(x0 + 1000*(-b))
    y1 = int(y0 + 1000*(a))
    x2 = int(x0 - 1000*(-b))
    y2 = int(y0 - 1000*(a))

    cv2.line(img,(x1,y1),(x2,y2),(0,0,255),2)

cv2.imwrite('houghlines3.jpg',img)
  1. 第1引数は入力画像であり,2値画像でなければなりません.あらかじめ2値化やエッジ検出をした画像を使うと良いでしょう

  2. 第2,3引数にはそれぞれ \rho と \theta の精度を指定します.

  3. 第4引数は,直線とみなされるのに必要な最低限の投票数を意味するしきい値

確率的ハフ変換による直線検出

f:id:robonchu:20170821152747j:plain

import cv2
import numpy as np

img = cv2.imread('dave.jpg')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray,50,150,apertureSize = 3)
minLineLength = 100
maxLineGap = 10
lines = cv2.HoughLinesP(edges,1,np.pi/180,10,minLineLength,maxLineGap)
for x1,y1,x2,y2 in lines[0]:
    cv2.line(img,(x1,y1),(x2,y2),(0,255,0),2)

cv2.imwrite('houghlines.jpg',img)

f:id:robonchu:20170821152839j:plain

参考:ハフ変換による直線検出 — OpenCV-Python Tutorials 1 documentation

特徴検出 — opencv 2.2 documentation

円検出

f:id:robonchu:20170821162945j:plain

circles = cv2.HoughCircles(image, cv2.HOUGH_GRADIENT, dp=2, minDist=20, param1=20, param2=20, minRadius=6, maxRadius=20 )

パラメータ

dp ・・・ 処理するときに元画像の解像度の倍率.1だとそのままの画質で処理

minDist ・・・ 検出される円と円の最小距離

param1 ・・・ 低いほどいろんなエッジを検出

param2 ・・・ 低いほど円じゃないものも検出

minRadius ・・・ 最小半径

maxRadius ・・・ 最大半径

動作確認用雑なコード↓

import cv2
import numpy as np

cap = cv2.VideoCapture(0)

while(1):
    # Take each frame
    _, frame = cap.read()

    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    lower_light_pink = np.array([168, 50, 50])
    upper_light_pink = np.array([188, 255, 255])
    mask = cv2.inRange(hsv, lower_light_pink, upper_light_pink)

    circles = cv2.HoughCircles(mask,cv2.HOUGH_GRADIENT,1,20,
                                param1=50,param2=20,minRadius=0,maxRadius=0)

    if circles is None:
        cv2.imshow('frame',frame)
        k = cv2.waitKey(5) & 0xFF
        if k == 27:
            break
        pass
    else:
        circles = np.uint16(np.around(circles))

        circle = []
        x = []
        y = []

        for i in circles[0,:]:
            x.append(i[0])
            y.append(i[1])
            circle.append(i[2])

        idx = circle.index(max(circle))
        cv2.circle(frame,(x[idx],y[idx]),circle[idx],(0,255,0),2)
        cv2.imshow('frame',frame)
        k = cv2.waitKey(5) & 0xFF
        if k == 27:
            break

cv2.destroyAllWindows()

f:id:robonchu:20170821163010j:plain

所感

円検出のパラメータ調整難しい…

参考: 円の検出 - TB-code

Opencvの円検出についてOpencvで円検出をするのですが、表示された画像の、... - Yahoo!知恵袋

Python cv2.HoughCircles で円検出 – LLC DigiFie Good!

c++とframe rateの高いカメラを使えばもう少し円検出の速度が挙げれるみたい。。。

マーカーを用いたカメラ位置姿勢推定(OpenCV+ArUco)

ArUcoのマーカー種類

  • SingleMarker
  • Board
  • ChessBoard
  • Diamond

Single

マーカの一辺の長さを指定。 マーカとカメラ間の位置関係を求める。

Board

マーカの一辺の長さとマーカ間の長さを指定。 ボードとカメラ間の位置関係を求める。 単一マーカより精度は良い。

Chess

四角形の一辺の長さとマーカの一辺の長さを指定。 チェッカの交点を求める。

Diamond

四角形の一辺の長さとマーカの一辺の長さを指定。 ダイアモンドとカメラ間の位置関係を求める

参考: すごくわかりやすい↓

OpenCVarucoマーカ - プログラム関連の個人的メモ

ArUcoを使った位置姿勢推定

手順

  1. cameraのキャリブレーション
  2. マーカー作成・検出
  3. 位置姿勢推定

OpenCV: Detection of ArUco Markers

OpenCV: ArUco Marker Detection

キャリブレーション

ArUcoで姿勢推定を行うにはカメラの内部パラメータと歪パラメータ(cameraMatrix,distCoeffs)が必要

OpenCVでのカメラキャリブの説明

cameraMatrix and distCoeffs are the camera calibration parameters that need to be known a priori.

To perform camera pose estimation you need to know the calibration parameters of your camera. This is the camera matrix and distortion coefficients. If you do not know how to calibrate your camera, you can take a look to the calibrateCamera() function and the Calibration tutorial of OpenCV. You can also calibrate your camera using the aruco module as it is explained in the Calibration with aruco tutorial. Note that this only need to be done once unless the camera optics are modified (for instance changing its focus).

やり方

  1. キャリブしたいカメラでチェスボードを用いて20枚くらいの写真を取る

  2. その写真を用いて以下のようなスクリプトを実行

opencv/samples/cpp at master · kipr/opencv · GitHub ←ここのsample画像を用いて試してみる

import numpy as np
import cv2
import glob

# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((6*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)

# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.

images = glob.glob('left*.jpg')

for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    # Find the chess board corners
    ret, corners = cv2.findChessboardCorners(gray, (7,6),None)

    # If found, add object points, image points (after refining them)
    if ret == True:
        objpoints.append(objp)

        corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
        imgpoints.append(corners2)

        # Draw and display the corners
        img = cv2.drawChessboardCorners(img, (7,6), corners2,ret)
        cv2.imshow('img',img)
        cv2.waitKey(500)

ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)

#cameraMatrix -> mtx , distCoeffs -> dist
print mtx, dist

cv2.destroyAllWindows()

結果:

mtx = [[ 534.07088318    0.          341.53407683]
 [   0.          534.11914504  232.94565267]
 [   0.            0.            1.        ]]

dist =  [[ -2.92971622e-01   1.07706883e-01   1.31038412e-03  -3.11032204e-05  4.34799808e-02]]

Calibrationの結果を今後も再利用したければ,Numpyの関数(np.savez, np.savetxt 等)を使ってカメラ行列とレンズ歪みパラメータを保存できる。

参考:

OpenCVのundistort(レンズ歪み補正)で端っこが欠けてしまうのをなんとかする - Qiita

カメラ校正 - Qiita

カメラキャリブレーション — OpenCV-Python Tutorials 1 documentation

OpenCV: Camera Calibration and 3D Reconstruction

マーカー作成・検出

#encoding:utf-8
import cv2
aruco = cv2.aruco

# DICT_4X4_50は4x4の格子でマーカ作成、ID50個
# drawMarker(dictionary, marker ID, marker_size[pix])
dictionary = aruco.getPredefinedDictionary(aruco.DICT_4X4_50)
marker = aruco.drawMarker(dictionary, 4, 100)

cv2.imwrite('ar_marker.png', marker)

img = cv2.imread('ar_marker.png')
img = cv2.resize(img, None, fx=0.05, fy=0.05)

corners, ids, rejectedImgPoints = aruco.detectMarkers(img, dictionary)

aruco.drawDetectedMarkers(img, corners, ids, (0,255,0))
cv2.imwrite('DetectedMarkers.png', img)

位置姿勢推定(TODO:pytho化)

参考になるコード

// if at least one marker is detected
if (ids.size() > 0){
  // single marker
  if (markerType == ARUCO_SingleMarker){
    // draw id
    cv::aruco::drawDetectedMarkers(undistImage, corners, ids);

    // pose estimation
    rvecsSingle.clear(); tvecsSingle.clear();
    cv::aruco::estimatePoseSingleMarkers(corners, markerSingleSize,
      intrinsic, distortion, rvecsSingle, tvecsSinge);

    // draw axis
    for (int ii = 0; ii < ids.size(); ii++)
      cv::aruco::drawAxis(undistImage, intrinsic, distortion,
        rvecsSingle[ii], tvecsSingle[ii], 0.1);    
  }
  // board
  else if (markerType == ARUCO_Board){
    cv::aruco::drawDetectedMarkers(undistImage, corners, ids);
    int valid = cv::aruco::estimatePoseBoard(corners, ids, 
      markerBoard, intrinsic, distortion, rvecBoard, tvecBoad);

    // if at least one board marker detected
    if (valid > 0)
      cv::aruco::drawAxis(undistImage, intrinsic, distortion,
        rvecBoard, tvecBoard, 0.1);
  }

Single

cv::aruco::estimatePoseSingleMarkers

マーカの位置推定を行う。 rvecs, tvecsにそれぞれのマーカとの位置関係が入っている。

rが回転成分、tが直進成分。回転成分に関してはrodrigues。 http://opencv.jp/opencv-2svn/cpp/camera_calibratio…

Board

cv::aruco::estimatePoseBoard

見つけたマーカ全部の情報を使ってボードの位置推定を行う。 マーカがある程度隠れていてもOKで精度も良い。

参考:

OpenCVarucoマーカ - プログラム関連の個人的メモ

全体参考

ArUco マーカーの検出 - Qiita

arucoモジュール を試す - 機械学習備忘録

OpenCV: ArUco Marker Detection

arucoモジュールでマーカーを検出する · atinfinity/lab Wiki · GitHub

開発メモ その59 OpenCV 3.2 with ContribモジュールでArUcoを使用する - A certain engineer "COMPLEX"

OpenCVarucoマーカ - プログラム関連の個人的メモ

物体追跡をやってみる(ピンクのボールを追いかける)

やりたいこと:ピンクボールの追跡

f:id:robonchu:20170819115402j:plain

OpenCV-Python tutorial

OpenCV-Pythonチュートリアル — OpenCV-Python Tutorials 1 documentation

OpenCVでのHSVの扱い

OpenCVでのHSV色空間lower,upperの取り扱い - Qiita

ピンクの色相の検出

lightsalmon : 255,160,167

lower_pink = np.array([168, 100, 100])

upper_pink = np.array([188, 255, 255])

import numpy as np
import cv2

cap = cv2.VideoCapture(0)

while(1):
    _, frame = cap.read()
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    lower_light_pink = np.array([168, 100, 100])
    upper_light_pink = np.array([188, 255, 255])
    mask = cv2.inRange(hsv, lower_light_pink, upper_light_pink)

    res = cv2.bitwise_and(frame,frame, mask= mask)

    cv2.imshow('frame',frame)
    cv2.imshow('mask',mask)
    cv2.imshow('res',res)
    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cv2.destroyAllWindows()

参考:色名称付色見本[赤、ピンク、茶系] – コピペで出来る!簡単ホームページ作成入門

【Python/OpenCV】カラートラッキング(色追跡)で移動物体の検出

最大矩形を追跡

作成したmaskの中で、一番大きいものだけを追跡する(矩形で囲む)

ROI:Region Of Interest

以下を上記のスクリプトに追加↑

    image, contours, hierarchy  = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    rects = []
    for contour in contours:
        approx = cv2.convexHull(contour)
        rect = cv2.boundingRect(approx)
        rects.append(np.array(rect))

    if len(rects) > 0:
      rect = max(rects, key=(lambda x: x[2] * x[3]))
      cv2.rectangle(frame, tuple(rect[0:2]), tuple(rect[0:2] + rect[2:4]), (0, 0, 255), thickness=2)

参考: pythonで赤い物体を認識しよう - Qiita

camshiftで追跡

ヒストグラムとは

ヒストグラムとは画像中の画素値の全体的な分布を知るためのグラフやプロットとみなせます.

ヒストグラム その1: 計算して,プロットして,解析する !!! — OpenCV-Python Tutorials 1 documentation

ヒストグラム逆投影法

各画素が対象物体に属している確率を表す.入力画像と同じサイズで単相の画像を作成します.

ヒストグラム その4: ヒストグラムの逆投影法 — OpenCV-Python Tutorials 1 documentation

パラメータ

  • cv2.TERM_CRITERIA_EPS - 指定された精度(epsilon)に到達したら繰り返し計算を終了する.

  • cv2.TERM_CRITERIA_MAX_ITER - 指定された繰り返し回数(max_iter)に到達したら繰り返し計算を終了する.

かなり適当なコード(TODO:リファクタ、マウスでクリックした箇所のHSV値の利用)

import numpy as np
import cv2

cap = cv2.VideoCapture(0)

print raw_input("please set the tracking object and input key")

# Need adjustment
lower_light_pink = np.array([168, 100, 100])
upper_light_pink = np.array([188, 255, 255])

_LOWER_COLOR = lower_light_pink
_UPPER_COLOR = upper_light_pink

print _LOWER_COLOR[0]

def find_rect_of_target_color(image):
  hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

  # Threshold the HSV image to get only pink colors
  mask = cv2.inRange(hsv, _LOWER_COLOR, _UPPER_COLOR)
  image, contours, hierarchy  = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

  rects = []
  for contour in contours:
    approx = cv2.convexHull(contour)
    rect = cv2.boundingRect(approx)
    rects.append(np.array(rect))
  return rects

def get_max_rect(rects):
    if len(rects) > 0:
      rect = max(rects, key=(lambda x: x[2] * x[3]))
      return rect
    else:
      return None

def get_track_info(rect):
    # setup initial location of window
    r, h, c, w = rect[1], rect[3], rect[0], rect[2]
    track_window = (c,r,w,h)

    # set up the ROI for tracking
    roi = frame[r:r+h, c:c+w]
    hsv_roi =  cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)
    mask = cv2.inRange(hsv_roi, _LOWER_COLOR, _UPPER_COLOR)
    
    # Need adjustment
    roi_hist = cv2.calcHist([hsv_roi],[0],mask,[int(_UPPER_COLOR[0])],[0,int(_UPPER_COLOR[0])])
    cv2.normalize(roi_hist,roi_hist,0,255,cv2.NORM_MINMAX)

    # Setup the termination criteria, either 10 iteration or move by atleast 1 pt
    term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 )
    return roi_hist, track_window, term_crit

# Set Initial Value
while(1):
  # take first frame of the video
  ret,frame = cap.read()
  rects = find_rect_of_target_color(frame)
  rect = get_max_rect(rects)
  if rect is not None:
    roi_hist, track_window, term_crit = get_track_info(rect)
    break

# Start Tracking
while(1):
    ret ,frame = cap.read()

    if ret == True:
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)        
        dst = cv2.calcBackProject([hsv],[0],roi_hist,[0,180],1)

        # apply camshift to get the new location
        # ret = ([x,y],[width,height],deg) ex: [640, 480],[10,10],30
        ret, track_window = cv2.CamShift(dst, track_window, term_crit)

        # Draw it on image
        pts = cv2.boxPoints(ret)
        pts = np.int0(pts)
        img = cv2.polylines(frame,[pts],True, 255,2)
        cv2.imshow('img',img)

        print pts
        # origin is upper left
        frame_size = frame.shape
        print "position_x_rate"
        print (pts[0][0]+pts[2][0])/2.0/frame_size[1]
        print "position_y_rate"
        print (pts[0][1]+pts[2][1])/2.0/frame_size[0]

        k = cv2.waitKey(60) & 0xff
        if k == 27:
            break
        else:
            cv2.imwrite(chr(k)+".jpg",img)
    else:
        break

cv2.destroyAllWindows()
cap.release()

参考: Meanshift と Camshift — OpenCV-Python Tutorials 1 documentation

パーティクルフィルタで追跡

import numpy as np
import cv2

# Need adjustment
lower_light_pink = np.array([168, 50, 50])
upper_light_pink = np.array([188, 255, 255])

_LOWER_COLOR = lower_light_pink
_UPPER_COLOR = upper_light_pink

def tracking():
    cap = cv2.VideoCapture(0)

    filter = ParticleFilter()
    filter.initialize()

    while True:
        ret, frame = cap.read()

        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

        # Threshold the HSV image to get only a color
        mask = cv2.inRange(hsv, _LOWER_COLOR, _UPPER_COLOR)

        # Start Tracking
        y, x = filter.filtering(mask)
        frame = cv2.circle(frame, (int(x), int(y)), 10, (255, 0, 0), -1)

        # origin is upper left
        frame_size = frame.shape
        print "position_x_rate"
        print x/frame_size[1]
        print "position_y_rate"
        print y/frame_size[0]

        for i in range(filter.SAMPLEMAX):
            frame = cv2.circle(frame, (int(filter.X[i]), int(filter.Y[i])), 2, (0, 0, 255), -1)
        cv2.imshow("frame", frame)

        if cv2.waitKey(20) & 0xFF == 27:
            break
    cap.release()
    cv2.destroyAllWindows()

class ParticleFilter:
    def __init__(self):
        self.SAMPLEMAX = 1000
        # frame.shape
        self.height, self.width = 480, 640

    def initialize(self):
        self.Y = np.random.random(self.SAMPLEMAX) * self.height
        self.X = np.random.random(self.SAMPLEMAX) * self.width

    # Need adjustment for tracking object velocity
    def modeling(self):
        self.Y += np.random.random(self.SAMPLEMAX) * 200 - 100 # 2:1
        self.X += np.random.random(self.SAMPLEMAX) * 200 - 100

    def normalize(self, weight):
        return weight / np.sum(weight)

    def resampling(self, weight):
        index = np.arange(self.SAMPLEMAX)
        sample = []

        # choice by weight 
        for i in range(self.SAMPLEMAX):
            idx = np.random.choice(index, p=weight)
            sample.append(idx)
        return sample

    def calcLikelihood(self, image):
        # white space tracking 
        mean, std = 250.0, 10.0
        intensity = []

        for i in range(self.SAMPLEMAX):
            y, x = self.Y[i], self.X[i]
            if y >= 0 and y < self.height and x >= 0 and x < self.width:
                intensity.append(image[int(y),int(x)])
            else:
                intensity.append(-1)

        # normal distribution
        weights = 1.0 / np.sqrt(2 * np.pi * std) * np.exp(-(np.array(intensity) - mean)**2 /(2 * std**2))
        weights[intensity == -1] = 0
        weights = self.normalize(weights)
        return weights

    def filtering(self, image):
        self.modeling()
        weights = self.calcLikelihood(image)
        index = self.resampling(weights)
        self.Y = self.Y[index]
        self.X = self.X[index]
        
        # return COG
        return np.sum(self.Y) / float(len(self.Y)), np.sum(self.X) / float(len(self.X))

if __name__ == '__main__':
    tracking()

参考:

パーティクルフィルタ組んでみた(Python) - コンピュータサイエンス系勉強ノート

Numpyによる乱数生成まとめ - Qiita

python + numpyで緑色の物体を追跡する (パーティクルフィルタ) - Qiita

Particle FilterでOpencvを使った物体追跡 - のんびりしているエンジニアの日記

Python版OpenCVのパーティクルフィルタで物体追跡

satomacoto: Pythonでパーティクルフィルタを実装してみる

particlefilter/particlefilter_py.py at master · AriYu/particlefilter · GitHub

pythonでパーティクルフィルタによる物体トラッキング - kohta blog

オプティカルフロー(Lucas-Kanade法)で追跡

cv2.goodFeaturesToTrack

コーナー検出器。8bitの画像とコーナーに関する設定を行うことでコーナーが検出される。

cv2.calcOpticalFlowPyrLK

8bitの画像を前後の二枚と検出したい点の集合(feature)やwinSizeを指定すると、後の画像上の特徴点が抽出される。

cv2.cornerSubPix

コーナー検出の高精度化。

Harrisコーナー検出 — OpenCV-Python Tutorials 1 documentation

cv2.dilate

膨張処理

Python OpenCV3で画素の膨張処理(dilation)と収縮処理(erosion) (ちょっと解説も) | from umentu import stupid

cv2.connectedComponentsWithStats

重心・面積・外接矩形の座標が得らる。

Harrisコーナー検出 — OpenCV-Python Tutorials 1 documentation

参考: qiita.com

OpenCVでオプティカルフローをリアルタイムに描画する(Shi-Tomasi法、Lucas-Kanade法) - Qiita

全体参考

毎日がロボット勉強会: 10.ロボットビジョン(応用編その1) 

モーション解析と物体追跡 — opencv 2.2 (r4295) documentation

人追跡

OpenCVで簡単リアルタイム物体検出 | AI coordinator

 Nobutobook: 【Python × OpenCV】 はじめての歩行者検知

機械の目が見たセカイ -コンピュータビジョンがつくるミライ (27) 動く人・物を追跡する(1) - OpenCVによるトラッキング | テクノロジー | マイナビニュース

顔追跡

【ライブラリ】pyFaceTracker:顔パーツ追跡「FaceTracker」のpythonラッパー... | DERiVE コンピュータビジョン ブログ

OpenCVで簡単リアルタイム物体検出 | AI coordinator

マーカー

Aruco-with-Python/aruco_testproject/build at master · JanezCim/Aruco-with-Python · GitHub

Opencvを用いたマーカー検出(仮 - Qiita

arucoモジュールでマーカーを検出する · atinfinity/lab Wiki · GitHub

軽量な AR ライブラリの ArUco について調査中 - Qiita

itouh2: OpenCV 画面上の四角の3次元座標をもとめる

GitHub - DebVortex/python-ar-markers: Detection of hamming markers for OpenCV written in python

ARタグの姿勢を取得

ROSでARマーカーを追跡するパッケージを使う: マイコン漬け

ROS勉強記録: ar_pose (ARToolKitのマーカー認識 in ROS)パッケージを使ってみる

ar-markers 0.4.1 : Python Package Index

機械学習のお勉強(ベイズ推定)

パラメトリックモデルの3つのステップ

  1. パラメータを含むモデル(数式)を設定する

  2. パラメータを評価する

  3. 最良の評価を与えるパラメータを決定する

ここで、2.においてパラメータを評価する基準として大きく2つある

  • 1つは誤差を定義して誤差を最小にするパラメータを決める

  • トレーニングセットが得られる確率である尤度関数を定義してこれを最大にするようにパラメータを決める

尤度関数(わかりやすい→):  【統計学】尤度って何?をグラフィカルに説明してみる。 - Qiita

ベイズ推定

これらとは異なる新しいパラメータの評価方法

ベイズの定理

考え方:ベイズの定理の基本的な解説 | 高校数学の美しい物語

使い方(大事!):10-6. ベイズの定理の使い方 | 統計学の時間 | 統計WEB

最尤推定ベイズ推定

  • 最尤推定は一意にパラメータを決める
  • ベイズ推定は求めたいパタメータの確率を決める(トレーニングデータ数が増えるほど、最尤推定のパラメータに近づく)

ベイズ推定は最尤推定の拡張と考えることができる。ベイズ推定は事前分布からの影響を受けない時は、最尤推定と同じになり、影響を受けるときは異なり、オーバーフィッティングを防ぐなどの効果がある。

藤井四段で学ぶ最尤推定、MAP推定、ベイズ推定 - Qiita

ベイズ推定の回帰分析への応用

(TBD)

共役事前分布

【ベイズ統計】共役事前分布とは?わかりやすく解説 | 全人類がわかる統計学

13-1. 二項分布 | 統計学の時間 | 統計WEB

13-3. ポアソン分布 | 統計学の時間 | 統計WEB

多項分布の意味と平均,分散,共分散などの計算 | 高校数学の美しい物語