|
多旋翼直升机(四轴飞行器)之开源整合平台
八、研究探讨单元
主题一:光流(Optical Flow)应用于四轴的悬停及避开障碍。
一、应用范例:
应用例一:透过OPENCV中的函式库将前后画面的特征点,标示移动方向及速度。
原始资料:http://ai.stanford.edu/~dstavens/cs223b/
(原文件名:RESEARCH_OF_01.JPG)
应用例二: AR.drone 两个相机都在特征点上, 做速度以及方向的标记(在左上角的画面是往下看的镜头画面)
视讯地址: http://www.youtube.com/watch?v=V4r2HXGA8jw
(原文件名:RESEARCH_OF_02.png)
AR.drone 悬停时的画面
(原文件名:RESEARCH_OF_03.png)
二、透过上面的二个应用例子,可以总结出几点:
1. 因为是透过影像中的特征点来处理, 所以摄影机的解析度不是很重要,也不需要彩色, 黑白即可。因为要测速所以60fps比30fps好 。
2. 透过例一分享的资料看来,影像处理的方法是:
(a)先找出第一个画面的特征点,可以用OPENCV的GoodFeaturesToTrack()函式取得。
(b)再用CalcOpticalFlowPyrLK()函式,将第二个画面中和画面一里相同的特征点,全部找出其位置。
(c)由第一画面与第二画面中, 同一特征点的位移差值,可以估算出方向及速度。
3. 透过例二知道所有特征点位移的平均值, 可当做是机体移动的对应值。
三、测试实作
程式测试一:
1.硬体:电脑+摄影机+USB影像撷取器。
2.软体:PYTHON V2.6(先不用C语言,否则容易卡在新旧版的参数设定上,冷门资料可没人跟你解说)+OPENCV V2.2。
3.程式范例:OF_001.PY 点击此处下载 ourdev_619571YHE36Y.zip(文件大小:1K) (原文件名:OF_001.zip)
4.萤幕截图:
照向地面, 蓝圈加红箭头标示着[特征点]的方向及速度。中间绿(Y)+黄(X)标示整体的X,Y分量,紫色标出机体位移方向及速度。
(原文件名:RESEARCH_OF_04.JPG)
(原文件名:RESEARCH_OF_05.JPG)
(原文件名:RESEARCH_OF_06.JPG)
机体转动的画面
(原文件名:RESEARCH_OF_07.JPG)
============================
OF_001.PY
============================
import math
import cv
import time
pram1 = 0.04
pram2 = 1.0
cv.NamedWindow("camera", 1)
#cv.NamedWindow("feature", 1)
capture = cv.CaptureFromCAM(0)
color1 = cv.CV_RGB(0,180,200)
color2 = cv.CV_RGB(180,180,0)
color1 = cv.CV_RGB(0,0,250)
color2 = cv.CV_RGB(250,0,0)
while True:
frame = cv.QueryFrame(capture)
size = cv.GetSize(frame)
frame_1 = cv.CreateImage(size, cv.IPL_DEPTH_8U, 1)
frame_2 = cv.CreateImage(size, cv.IPL_DEPTH_8U, 1)
pyramid_1 = cv.CreateImage(size, cv.IPL_DEPTH_8U, 1)
pyramid_2 = cv.CreateImage(size, cv.IPL_DEPTH_8U, 1)
cv.CvtColor(frame, frame_1, cv.CV_BGR2GRAY)
frame = cv.QueryFrame(capture)
cv.CvtColor(frame, frame_2, cv.CV_BGR2GRAY)
# print "size", size
eig_image = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
temp_image = cv.CreateImage(size, cv.IPL_DEPTH_32F, 1)
# for (x,y) in cv.GoodFeaturesToTrack(grayscale, eig_image, temp_image, 400, 0.04, 1.0, useHarris = True):
GFTT_frame_1 = cv.GoodFeaturesToTrack(frame_1, eig_image, temp_image, 100, 0.01, 0.01, useHarris = False)
# for (x,y) in GFTT_frame_1:
# print "good feature at", x,y
# cv.Circle(frame, (int(x), int(y)), 6, color, 1, cv.CV_AA, 0)
criteria = (cv.CV_TERMCRIT_ITER | cv.CV_TERMCRIT_EPS, 20, 0.3)
flags = 0
win_size = 12
COFP_frame_2, status, track_error = cv.CalcOpticalFlowPyrLK(frame_1, frame_2, pyramid_1, pyramid_2, GFTT_frame_1,(win_size ,win_size ), 4, criteria, flags)
# for (x1,y1) in features:
# cv.Circle(frame, (int(x), int(y)), 6, color1, 1, cv.CV_AA, 0)
hypotenuse_total = 0.0
x_total = 0.0
y_total = 0.0
f2_len = len(COFP_frame_2)
for i in range(1,f2_len):
# print "x=%f,y=%f " % (features[0],features[1])
p_x = GFTT_frame_1[0]
p_y = GFTT_frame_1[1]
q_x = COFP_frame_2[0]
q_y = COFP_frame_2[1]
x_total = x_total + (p_x - q_x)
y_total = y_total + (p_y - q_y)
angle = math.atan2((p_y - q_y), (p_x - q_x))
hypotenuse = math.sqrt( (p_y - q_y)**2 + (p_x - q_x)**2)
hypotenuse_total = hypotenuse_total + hypotenuse
if hypotenuse > 0 :
q_x = p_x - 9 * hypotenuse * math.cos(angle)
q_y = p_y - 9 * hypotenuse * math.sin(angle)
cv.Circle(frame, (int(p_x), int(p_y)), 3, color1, 1, cv.CV_AA, 0)
cv.Line(frame, (int(p_x), int(p_y)), (int(q_x), int(q_y)), color2, 1, cv.CV_AA, 0)
p_x = q_x + 9 * math.cos(angle + math.pi / 6)
p_y = q_y + 9 * math.sin(angle + math.pi / 6)
cv.Line(frame, (int(p_x), int(p_y)), (int(q_x), int(q_y)), color2, 1, cv.CV_AA, 0)
p_x = q_x + 9 * math.cos(angle - math.pi / 6)
p_y = q_y + 9 * math.sin(angle - math.pi / 6)
cv.Line(frame, (int(p_x), int(p_y)), (int(q_x), int(q_y)), color2, 1, cv.CV_AA, 0)
# cv.Circle(frame, (int(features[0]), int(features[1])), 6, color1, 1, cv.CV_AA, 0)
if f2_len > 0 :
hypotenuse_avg = hypotenuse_total / f2_len
x_avg = int(x_total / f2_len)*-9
y_avg = int(y_total / f2_len)*-9
cv.Line(frame, (0,240),(720,240),cv.CV_RGB(128,128,128), 2, cv.CV_AA, 0)
cv.Line(frame, (360,0),(360,480),cv.CV_RGB(128,128,128), 2, cv.CV_AA, 0)
cv.Line(frame, (360,240),(x_avg+360,240),cv.CV_RGB(220,220,0), 6, cv.CV_AA, 0)
cv.Line(frame, (360,240),(360,y_avg+240),cv.CV_RGB(0,220,0), 6, cv.CV_AA, 0)
cv.Line(frame, (360,240),(x_avg+360,y_avg+240),cv.CV_RGB(250,0,250), 2, cv.CV_AA, 0)
# print hypotenuse_avg
# print x_avg,y_avg
cv.ShowImage("camera", frame)
# cv.ShowImage("feature", grayscale)
inkey = cv.WaitKey(10)
# print "key:", inkey
if inkey == 2490368:
pram2 = pram2 + 0.1
if inkey == 2621440:
pram2 = pram2 - 0.1
if inkey == 27:
break
# print "param2: ", pram2 |
阿莫论坛20周年了!感谢大家的支持与爱护!!
一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。
|