こんにちは。
今回はクアッドコプターの姿勢制御について書いていけたらなと思います。

~姿勢制御の実験をする環境下において~

前回まではF350の機体でしたが、実験場所が室内と言う事もあり、一回り小さなF220フレームの機体に組み直しました。

image


しっかり画像処理もできている事も再確認しました…
image

image


さて本題に入りたいと思います。
まず当たり前かもしれませんが、姿勢制御を行うにあたっては機体自身の正確なロール、ピッチ、ヨーこの角を把握する必要があります。

私は今回これらの角度を求めるために9軸センサmpu9150を使用しました。

なお、今回はSPIでmpu9150を使用しました。

受信した角速度、加速度から四元数を算出し
オイラー角に変換します。
ここで求めたヨー角は時間の経過によりノイズの影響でどんどん増えて行ってしまうので、ヨー角は地磁気センサからの値から求めます。
方位を求める式は下記になります。
image

尚、
Vxyzはオフセット値
θ、φは予め求めたピッチ角とロール角です。

ここで求めたオイラー角を参照して4個のモータを制御する必要があります。
今回はとりあえずホバリングさせたいので
(0°からの偏差)*Kp+(偏差の累積値)*ki+(前回の角度と比べた変化量)*kd
=操作量
としてPID制御します。

~実験~

今回はまだ実験段階なので、無固定で飛ばすと楽しい事になるリスクが高いです。
なので今回は段ボールに紐を対になるようにクアッドコプターの脚に固定しました。

image


image

こうする事で、一本の紐で固定する時に比べて重心の偏りが軽減され、揚力同士が引き合ってくれるので割と再現性が高い固定方法なのではないかと思います。

実際に飛ばしてみた動画です

まだ多少ブレがありますが安定してきている気がします。
今後は高度制御のため張力が極力働からないように固定方法の改善を考えていきたいです。
また、モータの低周波ノイズの干渉を若干受けているようなのでセンサ自体を鉄板で覆うなどの対策を考えていきたいです。


もうすぐ応用情報処理技術者試験ですね…
皆様にとっては簡単なものかもしれませんが取れるよう精進します…


皆さんお久しぶりです。TMNT(たみねた)と申します。
今回は学校からお借り頂いた、raspi3↓
image

とエレコムのwebカメラ↓
image

を用いてちょっとした画像処理をしてみました。
ライブラリはOpencv3.0以降のもので
開発言語はpython2.0です。
正直、pythonもまだまだ初心者なので色々と手こずりました。
(インデントとか… 間違えてセミコロン打っちゃったりとか…
で、今回は人を検出し通過人数をカウントしてくるソフトを開発したいなぁと思いました。


・人を検出する方法。
人を検出すると言っても色々な検出方法があって
haar-like特徴を用いた顔検出、上半身検出
、下半身検出や…
HOG + SVMを用いた人物検出(人型検出)
などと色々あります。

普通に考えれば今回はカメラの前を通り過ぎる人達を検出出来ればいいのでHOGを使うのが最善と思われるかもしれません。ですがこれにはいくつかのデメリットがあります。
それは、

・遠距離(人がフレーム内に収まる距離)でないと検出されない。

・割と処理が重い。

・検出フレームが余分に大き過ぎる事がある。

以上の3つのデメリットです。

後程、追跡処理についても述べますがあまり検出フレームが余分に大きすぎると人以外の部分も生成されるヒストグラム特徴量に大きな影響を与えてしまい、結果として追跡精度が落ちてしまいます。

一方、haar-like特徴を用いた顔検出の場合は

・正面顔が検出出来れば近距離、遠距離でもok

・処理が軽い

・検出精度が高い

という利点があります。
以上の観点から今回はhaar-like特徴による顔検出を利用します。

しかしこのままでは常に正面顔が写るとは限りませんし、また断続的に検出する場合が多いのでカウント済みの顔のフレーム座標を把握できなくなり、精度低下に繋がりかねません。

このような不具合が発生しないためには、これに合わせて物体追跡処理を加えてやる事が必要です。

今回利用したものはMeanshift法です。

これにより、一度でも顔検出が成功すれば理論上フレーム内での追尾が可能になります。


以下に今回作成したプログラムを置いておきます…

※インデントが消えてしまっているので早いうちになんとかします!

import numpy as np
import cv2
track_window=[None]*10
roi_hist=[None]*10
count=0
check=0
xg_t=[0]*10
yg_t=[0]*10
ch=[0]*10

def detect(img,cascade,minsize):
rects = cascade.detectMultiScale(img, scaleFactor=1.3, minNeighbors=4, minSize=minsize,flags=cv2.CASCADE_SCALE_IMAGE)
if len(rects) == 0:
return []
rects[:,2:] += rects[:,:2]
return rects
def draw_rects(img, rects, color):
for x1, y1, x2, y2 in rects:
cv2.rectangle(img, (x1, y1), (x2, y2), color, 2)

if __name__ == '__main__':
import sys, getopt
print(__doc__)

args, video_src = getopt.getopt(sys.argv[1:], '', ['cascade=', 'nested-cascade='])
try:
video_src = video_src[0]
except:
video_src = 0
args = dict(args)
cascade_fn = args.get('--cascade', "haarcascades/haarcascade_frontalface_alt.xml")
cascade = cv2.CascadeClassifier(cascade_fn)

cap = cv2.VideoCapture(0)
term_crit = ( cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1 )
while(True):
ret, frame = cap.read()


if ret == True:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
gray = cv2.equalizeHist(gray)
rects = detect(gray, cascade,(50,50))
vis = frame.copy()
draw_rects(vis, rects, (0, 255, 0))
for x1, y1, x2, y2 in rects:
xg=(x1+x2)/2
yg=(y1+y2)/2


flag=0
if ((30x2)and(450>y2)and (30 for j in xrange(0,10):
if track_window[j]:
(x,y,w,h)=track_window[j]
if((xx+w)and(450>y+h)and (30 flag=1
track_window[j] = (x1, y1, x2-x1, y2-y1)

roi = frame[y1:y2, x1:x2]

hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)

img_mask = cv2.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))

roi_hist[j] = cv2.calcHist([hsv_roi], [0], img_mask, [180], [0,180])

cv2.normalize(roi_hist[j], roi_hist[j], 0, 255, cv2.NORM_MINMAX)
break

if flag!=1:
check+=1
print (check)
for count in xrange(0,10):
if track_window[count]==None:
track_window[count] = (x1, y1, x2-x1, y2-y1)
ch[count]=str(check)+"_HUMAN"
roi = frame[y1:y2, x1:x2]
hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV)

img_mask = cv2.inRange(hsv_roi, np.array((0., 60.,32.)), np.array((180.,255.,255.)))

roi_hist[count] = cv2.calcHist([hsv_roi], [0], img_mask, [180], [0,180])

cv2.normalize(roi_hist[count], roi_hist[count], 0, 255, cv2.NORM_MINMAX)
break
for i in xrange(0, 10):
if track_window[i]:
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

dst = cv2.calcBackProject([hsv],[0],roi_hist[i],[0,180], 1)


ret, track_window[i] = cv2.meanShift(dst, track_window[i], term_crit)

x,y,w,h = track_window[i]
xg_t[i]=(x+x+w)/2
yg_t[i]=(y+y+h)/2
if not ((30x+w)and(450>y+h)and (30 track_window[i]=None

for i2 in xrange(0,10):
if track_window[i2]:
(xl,yl,wl,hl) = track_window[i2]
if(xl track_window[i2]=None

if track_window[i]:
x,y,w,h = track_window[i]
cv2.rectangle(vis, (x,y), (w+x, h+y), 255, 2)
cv2.putText(vis,ch[i],(x,y),cv2.FONT_HERSHEY_SIMPLEX,0.8,(0,0,255))
cv2.imshow('SHOW MEANSHIFT IMAGE', vis)


k = cv2.waitKey(1)
if k == ord('q'):
break
else:
break





以下のように動きました。

image


緑枠がhaar-like特徴で顔検出したフレームで
青枠がmeanshift法により計算された追跡フレームです。

このように顔検出がされない時でも、、

image


しっかり追跡してくれていますね。

動画も載せて置きます…
https://youtu.be/mNlxeC30llo

問題点は横顔が検出出来ない事です。
公開されているカスケード分類器の中には横顔や上半身、下半身のものもありますが、残念ながらどれも精度がイマイチです…

時間があったら横顔のカスケード分類器作ってみようかなと思います。

皆さん。明けましておめでとうございます❗


今回は前回のカメラモジュール(ov7670)の続きで、、取得した画像データから画像解析をしてみました。

ただ単に画像解析をすると言っても意味が曖昧なので今回は簡単な目標を立てました。
それは、




1. 取得した画像から特定の物体のみを検出し追跡に必要なデータ(主に重心、面積)を生成する







2. なるべく処理時間は短縮させる








、、、、、、と言ったところです。





まず、1. の『特定の物体を検出する』ということですが簡単に言えば特定の色だけを取得した画像から抜き出すということです。
つまり………まず最初に特定の色を検出し2値化データを生成する事が必要です。




では、取得した画像から特定の色を検出するためにはどうすればいいのでしょうか?
方法としては、



シンプルにRGBそれぞれの値から判断する方法
と、


RGBからHSVを生成し判断する方法があります。



前者はプログラム的には非常にシンプルですが
閾値の調整等が非常に大変で地味になかなか苦労します。



後者はプログラム的には少し面倒な変換式を書く必要がありますがH(色相),S(彩度),V(明度)なので閾値の調整が簡単で直感的に扱う事ができます。



なので今回はHSVを用いて色検出をしました。



そしてこちらが取得した画像(下)から色検出をした後の2値化画像(上)です。
(今回は緑を検出対象にしました)

image





検出はできていますがこれではノイズ(ごま塩ノイズ)が多く、これから処理をしていく過程において大きなハンデを伴います。なので、
オープンニングとクロージングをしてノイズを除去します。



そしてこちらがノイズ除去後(上)です

image








これで色検出はバッチリです。しかし実は、物体検出という意味ではこれではまだ不十分です。

何故なら検出した色全てのものをひとまとまりの物体と捉えてしまっているからです。
つまり、白の連続した画素同士で区別をつける必要があります。
その方法がラベリングというものです。

ラベリングは連続した白(high)に同じ数値(ラベル)を割り当てるので物体同士で区別をつける事ができるようになります。


種類は8近傍と4近傍がありますが今回は8方近傍でラベリングをしました。



そしてこちらが2値化画像(下)からラベリングをした後の画像(上)です。
image




ラベリングが出来れば重心(つまり面積)は簡単に求める事ができます。(上)

image




速度的にはこのような感じです(https://youtu.be/cLSvlq4CYpM)


これぐらいのフレームレートなら支障なさそうですね、
ラベリングは実に優秀で円形度を求める事もでき円検出も可能のようです。
それはまた、暇があればやっていきたいと思います
プログラムは要望があればmbedにて公開します。





……………………と画像解析はここらへんまでにして次回は遂にクアッドコプター(半)自律制御のミソである姿勢制御の準備等について書いていけたらなと思います()






ではまた、、



↑このページのトップヘ