#基于SIFT光流法的速度识别与位移检测
首先 还是先科普一下SIFT吧
很简单的说,因为不喜欢讲太多blabala没用的话
首先 数字图像是什么?
A good Question。数字图像不过是数字矩阵,常用的有HSV、HSI、UAV、RGB以及灰度等。这些,统统不重要,他们不过是三维/二维矩阵而已。640*480的图像,共有那么多的像素点。每一个点用什么代表?灰度就是0-255的一维表示。RGB/HSV则是三个值去表征。这个矩阵,就是图像处理的原材料。
其次 数字图像如何处理?
显然,对数字图像处理和数学息息相关。一说数学,肯定就是那一套。
一方面是改变图像,比如去噪声(窗口滤波),基于统计特征(直方图)渲染什么的,。
高通低通滤波,傅里叶变换、小波分析等。这是对于滤波而言。
数字图像处理稍微有基础的,应该也都知道形态学滤波,中值、高斯平滑什么的。
二方面是提取有用的特征,比如HOugh检测直线、cannny算子、Laplace算子、fast算法检测边缘什么的。
用于训练学习的LBP特征,SIFT\ORB\SURF提取的特征点等。
我们把第一方面称为图像的前处理,把第二方面称为图像特征提取。
这些特征是什么?
比如某一个窗口的直方图,是一个特征,LBP特征的原理类似,通过直方图使用概率的方法匹配的好处是快速,准确性一般。
比如边缘是监测变化率(灰度),简单的说d r(灰度值)/d(x) 变化率大的即是边缘。
这里用到了什么特征点?
这里是fast算法角点检测的特征点,有关FAST的数学公式看书即可,该特征点即在x,y两个维度上的变化率大于阈值即设为特征点,不然没有特征有什么用呢。SIFT/SURF/ORB都用的是这个。
特征点如何标记?
这里用到的是链码特征。什么是链码特征呢,就是对于一个假设3*3的窗口,已知9个点的像素值,那么中间的在8个方向上的变化率,按照大小排列就构成了链码特征。
要这个有什么用?识别啊。
#正文开始
1、速度识别和位移检测的原理
速度识别很简单,已知匹配到的特征点,当镜头发生移动,特征点随之发生移动。根据运动学规律,It’s So easy to understand。
位移检测同理,对速度积分。(不太准确,只能定性不能定量分析)
2、SIFT又是什么?
如果监测所有的特征点和链码再实时匹配,那算不过来。那么怎么办呢,这里就引入了人SIFT算法。
SIFT 的详细介绍参考:
http://blog.csdn.net/abcjennifer/article/details/7639681/
当两幅图像的SIFT特征向量生成后,下一步我们采用关键点特征向量的欧式距离来作为两幅图像中关键点的相似性判定度量。取图像1中的某个关键点,并找出其与图像2中欧式距离最近的前两个关键点,在这两个关键点中,如果最近的距离除以次近的距离少于某个比例阈值,则接受这一对匹配点。降低这个比例阈值,SIFT匹配点数目会减少,但更加稳定。
3、速度识别和位移检测的代码实现
这里我给出Python代码,Python-openCV较容易上手。
解决的工程问题有:
1、匹配点的好坏,对匹配的点的相似度排序
2、点丢失怎么办,当点小于阈值时,意味着环境场景发生了变化,这里重新寻找特征点。
#coding=UTF-8
import numpy as np
import cv2
import time
def juedui(num):
if num>0 or num==0:
return num
else:
return 0-num
def ceshi(num):
t=0
cap=cv2.VideoCapture(0)
feature_params=dict(maxCorners=100,qualityLevel=0.4,minDistance=7,blockSize=7)
lk_params=dict(winSize=(15,15),maxLevel=2,criteria=(cv2.TERM_CRITERIA_EPS|cv2.TERM_CRITERIA_COUNT,10,0.03))
color=np.random.randint(0,255,(100,3))
ret,old=cap.read()
old_gray=cv2.cvtColor(old,cv2.COLOR_BGR2GRAY)
p0=cv2.goodFeaturesToTrack(old_gray,mask=None,**feature_params)
if num==1:
while(1):
l1=[]
l2=[]
d1=0
d2=0
ret,frame=cap.read()
frame_gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
p1,st,err=cv2.calcOpticalFlowPyrLK(old_gray,frame_gray,p0,None,**lk_params)
good_new=p1[st==1]
good_old=p0[st==1]
#print good_new
#print good_old
rows1 = frame.shape[0]
cols1 = frame.shape[1]
out = np.zeros((rows1,cols1,3), dtype='uint8')
out[:rows1,:cols1] = np.dstack([frame_gray, frame_gray, frame_gray])
lenth=len(good_new)
for i ,(new,old) in enumerate(zip(good_new,good_old)):
a,b=new.ravel()
c,d=old.ravel()
res1=juedui(a-c)
res2=juedui(b-d)
#print res1,res2
l1.append(res1)
l2.append(res2)
# print (int(a),int(b)),(int(c),int(d))
cv2.line(out,(int(a),int(b)),(int(c),int(d)),color[i].tolist(),2)
cv2.circle(out,(int(a),int(b)),5,(255,0,0),-1)
cv2.circle(out,(int(c),int(d)),5,(255,222,173),-1)
# frame=cv2.circle(frame,(int(a),int(b)),5,color[i].tolist(),-1)
cv2.imshow('frame.jpg',out)
k=cv2.waitKey(2)&0xff
if k==27:
break
d1=sum(l1)/lenth
d2=sum(l2)/lenth
#print l1,l2
if -15<d1<15 and -15<d2<15:
print"OK",d1,d2
else :
print"不稳定",d1,d2
#except:
# time.sleep(0.3)
# print "错误"
elif num==2:
while(1):
try:
l1=[]
l2=[]
d1=0
d2=0
ret,frame=cap.read()
frame_gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
p1,st,err=cv2.calcOpticalFlowPyrLK(old_gray,frame_gray,p0,None,**lk_params)
good_new=p1[st==1]
good_old=p0[st==1]
#print good_new
#print good_old
rows1 = frame.shape[0]
cols1 = frame.shape[1]
out = np.zeros((rows1,cols1,3), dtype='uint8')
out[:rows1,:cols1] = np.dstack([frame_gray, frame_gray, frame_gray])
lenth=len(good_new)
for i ,(new,old) in enumerate(zip(good_new,good_old)):
a,b=new.ravel()
c,d=old.ravel()
res1=a-c
res2=b-d
l1.append(res1)
l2.append(res2)
# print (int(a),int(b)),(int(c),int(d))
cv2.line(out,(int(a),int(b)),(int(c),int(d)),color[i].tolist(),2)
cv2.circle(out,(int(a),int(b)),5,color[i].tolist(),-1)
# frame=cv2.circle(frame,(int(a),int(b)),5,color[i].tolist(),-1)
d1=sum(l1)/lenth
d2=sum(l2)/lenth
cv2.imshow('frame.jpg',out)
print "X",d1,"Y",d2
k=cv2.waitKey(2)&0xff
if k==27:
break
old_gray=frame_gray.copy()
p0=good_new.reshape(-1,1,2)
t=t+1
if len(good_new)<10:
feature_params=dict(maxCorners=100,qualityLevel=0.3,minDistance=7,blockSize=7)
lk_params=dict(winSize=(15,15),maxLevel=2,criteria=(cv2.TERM_CRITERIA_EPS|cv2.TERM_CRITERIA_COUNT,10,0.03))
color=np.random.randint(0,255,(100,3))
ret,old=cap.read()
old_gray=cv2.cvtColor(old,cv2.COLOR_BGR2GRAY)
p0=cv2.goodFeaturesToTrack(old_gray,mask=None,**feature_params)
t=0
except:
time.sleep(0.01)
print "静止"
cv2.destroyAllWindows()
cap.release()
#1为位移检测模式,2为测速模式
ceshi(2)