概览

  • 一、前言
  • 二、目标检测
    • 1.图像预处理
    • 2.帧间差分法
  • 三、目标跟踪
    • 1.原理
    • 2.应用
  • 四、总结

一、前言

在NVH性能开发过程中,需对整车进行振动试验,进行模态分析。在多个模态频率下,车门、天窗、轮胎或排气系统会产生共振, 形成最大的振幅。如图中排气系统在某个频率下产生了共振,在水平方向产生最大振幅。

二、目标检测

1.图像预处理

由于振动部件的颜色比较明显,振动幅度越大,红色越明显,而静止部分为蓝色。可以尝试将彩色图像RGB转换HSV空间(色差、饱和度、强度)后对蓝色背景进行过滤。

#过滤蓝色部分,将背景转换为白色
def data_prepare(image,index):imhsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)lower_blue = np.array([100,43,46])upper_blue = np.array([124,255,255])lower_white = np.array([0,0,255])upper_white = np.array([0,0,255])mask_blue = cv2.inRange(imhsv,lower_blue,upper_blue)mask_white = cv2.inRange(imhsv,lower_white,upper_white)mask=mask_blue|mask_whitemask = 255 - maskres = cv2.bitwise_and(image,image,mask=mask)#将黑色背景转换为白色背景res[(res[:,:,0]+res[:,:,1]+res[:,:,2])==0]=[255,255,255]return res

2.帧间差分法

帧间差分法是将视频流中相邻两帧或相隔几帧图像的两幅图像像素值相减,并对相减后的图像进行阈值化来提取图像中的运动区域。因此,可采用帧间差分法检测振动部件。

1)帧间差分法的优点:算法简单,不易受环境光线影响。
2)帧间差分法的缺点:无法识别静止或运动速度很慢的目标;差分时容易产生孔洞,需做处理。

若相减两帧图像的帧数分别为第 k k k帧、第 k + 1 k+1 k+1帧,其帧图像分别为 f k ( x , y ) f_k(x,y) fk​(x,y)、 f k + 1 ( x , y ) f_{k+1}(x,y) fk+1​(x,y),差分图像二值化阈值为T,差分图像用D(x, y)表示,则帧间差分法的公式如下:

D ( x , y ) = { 1 , ∣ f k + 1 ( x , y ) − f k ( x , y ) ∣ > T 0 , o t h e r w i s e D(x,y) = \left\{\begin{array}{l}1,\;\;\;\;\left|f_{k+1}(x,y)-f_k(x,y)\right|>T\\0,\;\;\;\;otherwise\end{array}\right. D(x,y)={1,∣fk+1​(x,y)−fk​(x,y)∣>T0,otherwise​

#使用帧间差分法得到运动目标
def framediff(frame_lwpCV):global backgroundgray_lwpCV = cv2.cvtColor(frame_lwpCV, cv2.COLOR_BGR2GRAY)gray_lwpCV = cv2.GaussianBlur(gray_lwpCV, (21, 21), 0)# 将第一帧设置为整个输入的背景if background is None:background = gray_lwpCVreturn# 对于每个从背景之后读取的帧都会计算其与背景之间的差异,并得到一个差分图(different map)。# 还需要应用阈值来得到一幅黑白图像,并通过下面代码来膨胀(dilate)图像,从而对孔(hole)和缺陷(imperfection)进行归一化处理diff = cv2.absdiff(background, gray_lwpCV)diff = cv2.threshold(diff, 25, 255, cv2.THRESH_BINARY)[1] # 二值化阈值处理diff = cv2.dilate(diff, es, iterations=2) # 形态学膨胀return diff

三、目标跟踪

1.原理

光流法是一种利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系,从而计算出相邻帧之间物体的运动信息的方法。基于光流法对振动部件进行跟踪并判断运动方向。

1)假设:摄像头采集到的两帧图像之间的像素灰度不变,即相邻帧之间的亮度恒定;相邻的两帧像素具有相对运动;保持空间一致性;即,同一子图像的像素点具有相同的运动。
2)角点检测:基于灰度图像的Shi-Tomasi角点检测算法(Harris角点检测算法的改进),计算灰度发生较大变化时所对应的位置,找到纹理丰富的物体边缘点。
3)角点跟踪:根据角点的灰度及周围同一子图像的像素点的灰度值进行角点的跟踪。

考虑一个像素I(x,y,t)在第一帧的光强度(其中t代表其所在的时间维度)。它移动了 (dx,dy)的距离到下一帧,用了dt时间。因为是同一个像素点,我们认为该像素在运动前后的光强度是不变的,即 I ( x , y , t ) = I ( x + d x , y + d y , t + d t ) I(x,y,t)=I(x+dx, y+dy, t+dt) I(x,y,t)=I(x+dx,y+dy,t+dt),经过泰勒展开得到
I ( x , y , t ) = I ( x , y , t ) + ∂ I ∂ x d x + ∂ I ∂ y d y + ∂ I ∂ t d t + ε I(x,y,t)=I(x,y,t)+\frac{\partial I}{\partial x}dx+\frac{\partial I}{\partial y}dy+\frac{\partial I}{\partial t}dt+\varepsilon I(x,y,t)=I(x,y,t)+∂x∂I​dx+∂y∂I​dy+∂t∂I​dt+ε
其中,ε代表二阶无穷小项,可忽略不计,由此可得
∂ I ∂ x d x d t + ∂ I ∂ y d y d t + ∂ I ∂ t = 0 \frac{\partial I}{\partial x}\frac{dx}{dt}+\frac{\partial I}{\partial y}\frac{dy}{dt}+\frac{\partial I}{\partial t}=0 ∂x∂I​dtdx​+∂y∂I​dtdy​+∂t∂I​=0
令 I x = ∂ I ∂ x , I y = ∂ I ∂ y , I t = ∂ I ∂ t I_x=\frac{\partial I}{\partial x},I_y=\frac{\partial I}{\partial y},I_t=\frac{\partial I}{\partial t} Ix​=∂x∂I​,Iy​=∂y∂I​,It​=∂t∂I​,由于u,v分别为光流分别为沿X轴与Y轴的速度矢量,因此
I x d x d t + I y d y d t + I t = 0 I_x\frac{dx}{dt}+I_y\frac{dy}{dt}+I_t=0 Ix​dtdx​+Iy​dtdy​+It​=0
其中Ix,Iy,It均可由图像数据求得,而(u,v)即为所求光流矢量。约束方程只有一个,而方程的未知量有两个,这种情况下无法求得u和v的确切值。此时需要引入另外的约束条件,从不同的角度引入约束条件,计算出光流场。

2.应用


#使用光流法寻找特征点的轨迹
def tracking(image,listnum):global tracksglobal tracksflagglobal prev_graytrack_len = 10frame_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)#转化为灰度图vis = image.copy()#赋值frame的值,不覆盖frame本身if tracksflag[listnum] > 0:#检测到角点后进行光流跟踪 img0, img1 = prev_gray, frame_grayp0 = np.float32([tr[-1] for tr in tracks]).reshape(-1, 1, 2)#对np数组进行重塑#前一帧的角点和当前帧的图像作为输入来得到角点在当前帧的位置p1, st, err = cv2.calcOpticalFlowPyrLK(img0, img1, p0, None, **lk_params)#当前帧跟踪到的角点及图像和前一帧的图像作为输入来找到前一帧的角点位置p0r, st, err = cv2.calcOpticalFlowPyrLK(img1, img0, p1, None, **lk_params) d = abs(p0-p0r).reshape(-1, 2).max(-1)#得到角点回溯与前一帧实际角点的位置变化关系good = d < 1#判断d内的值是否小于1,大于1跟踪被认为是错误的跟踪点new_tracks = []#将跟踪正确的点列入成功跟踪点for tr, (x, y), good_flag in zip(tracks, p1.reshape(-1, 2), good):if not good_flag:continuetr.append((x, y))if len(tr) > track_len:del tr[0]new_tracks.append(tr)
#            cv2.circle(vis, (x, y), 2, (0, 255, 0), -1)#画圆tracks = new_tracks#以上一帧角点为初始点,当前帧跟踪到的点为终点划线cv2.polylines(vis, [np.int32(tr) for tr in tracks], False, (0, 0, 0))
#        print('寻找轨迹',tracks)else:mask = np.zeros_like(frame_gray)#初始化和视频大小相同的图像mask[:] = 255#将mask赋值255也就是算全部图像的角点
#        for x, y in [np.int32(tr[-1]) for tr in tracks]:#跟踪的角点画圆
#            cv2.circle(mask, (x, y), 5, 0, -1)p = cv2.goodFeaturesToTrack(frame_gray, mask = mask, **feature_params)#角点检测if p is not None:for x, y in np.float32(p).reshape(-1, 2):tracks.append([(x, y)])#将检测到的角点放在待跟踪序列中        tracksflag[listnum]=1prev_gray = frame_gray#根据轨迹上的点可以得到运动向量,将该向量转换运动方向
def direction_judge(tracklines):classification='0'trvec=[]ang=[]for listnum in range(0,len(tracklines)):dismax=0indexmax=0trvector=[0,0]for index in range(0,len(tracklines[listnum])):#将同一个视图中同一个轨迹上最后一个轨迹点和第一个轨迹点做差得到运动向量,将同一个视图中所有特征点的运动向量累加得到整体的运动向量trackline_x=[x[0] for x in tracklines[listnum][index]]trackline_y=[y[1] for y in tracklines[listnum][index]]trackline=[trackline_x[-1]-trackline_x[0],trackline_y[-1]-trackline_y[0]]trvector=[a+b for a, b in zip(trvector,trackline)]
#        length=len(trackline_x)
#            trvector=[sum(trackline_x)/length,sum(trackline_y)/length]
#        trvector=trackline[-1][0]-trackline[0][0],trackline[-1][1]-trackline[0][1]trvector=np.array(trvector)        unitvector=np.array([1,0])#计算运动向量与x轴正方向的角度interangel=np.arccos(trvector.dot(unitvector)/np.sqrt(trvector.dot(trvector)))*180/np.piif trvector[1] < 0:angel=interangel+180else:angel=interangeltrvec.append(trvector)ang.append(angel)#特殊点挑选->lateralif ang[0] < 20:classification='2'#主视图和俯视图运动部件向右/左水平移运动->lateralelif (((ang[2] < 40) or ((ang[2] > 150) and (ang[2] < 220)) or (ang[2] > 350)) and ((ang[3] < 10) or ((ang[3] > 150) and (ang[3] < 220)) or (ang[3] > 350))):classification='2'#主视图和俯视图运动部件运动方向相反或者右视图运动部件向上/下运动->bounceelif (abs(ang[2]-ang[3]) > 110 ) and (abs(ang[2]-ang[3]) < 190 ) or (((ang[1] > 70) and (ang[1] < 110)) or ((ang[1] > 230) and (ang[1] < 310))):classification='1'else:classification='3'for case in switch(classification):if case('1'):print('It is bounce')breakif case('2'):print('It is lateral')breakif case('3'):print('It is front-after')breakif case():print('There is no classification')print(ang)

四、总结

本文基于整车振动时振动部件的四个视角,通过帧间差分法对振动部件进行检测,并且采用光流法对振动部件进行跟踪,对振动方向予以准确的判断。

参考文献
[1]背景提取算法
[2]光流法简单介绍
[3]计算机视觉–光流法(optical flow)简介
[4]总结:光流–LK光流–基于金字塔分层的LK光流–中值流

算法(二):汽车振动部件目标检测与跟踪(计算机视觉)相关推荐

  1. 机器人视觉分析算法_机器视觉处理:目标检测和跟踪

    得益于人工智能,机器学习和计算机视觉等融合技术的进步,机器人每天都能看到,分析和做出更像人类的决策.开发此类视觉分析逻辑涉及实现解决方案,这些解决方案可以确定对象的方向,处理移动的对象并执行导航.为此 ...

  2. 计算机视觉算法——基于Anchor Free的目标检测网络总结

    计算机视觉算法--基于Anchor Free的目标检测网络总结 计算机视觉算法--基于Anchor Free的目标检测网络总结 1. CornerNet 1.1 关键知识点--网络结构及特点 1.2 ...

  3. 综述二 | 最全的目标检测大综述(附下载链接)

    欢迎关注" 计算机视觉研究院 " 关注并星标 从此不迷路 计算机视觉研究院 公众号ID|ComputerVisionGzq 学习群|扫码在主页获取加入方式 计算机视觉研究院专栏 作 ...

  4. 9.2.2 Python图像处理之图像数学形态学-二值形态学应用-目标检测

    9.2.2 Python图像处理之图像数学形态学-二值形态学应用-目标检测(击中与击不中) 文章目录 9.2.2 Python图像处理之图像数学形态学-二值形态学应用-目标检测(击中与击不中) 1 算 ...

  5. 2020中兴捧月算法大赛阿尔法赛道决赛总结(多目标检测与跟踪)

    赛题:多目标检测与跟踪 代码地址 初赛:排名第1 初赛思路:第一次做跟踪任务.简单的认为是检测+reid问题. 初赛: 1.首先明确题意:多目标跟踪:指标MOTA和MOTP, 后期的大量实验证明检测算 ...

  6. Complexer-YOLO:基于语义点云的实时三维目标检测与跟踪

    泡泡点云时空,带你精读点云领域顶级会议文章 标题:Complexer-YOLO: Real-Time 3D Object Detection and Tracking on Semantic Poin ...

  7. 动态视频目标检测和跟踪技术(入门)

    动态视频目标检测和跟踪技术 http://m.qingqingsk.com/ztnews/lvvozlzrztkzrqwqqlnrluqk.html 传统电视监控技术只能达到"千里眼&quo ...

  8. 分割点云数据_3D点云深度学习综述:三维形状分类、目标检测与跟踪、点云分割等...

    3D点云学习( Point Clouds)作为近年来的研究热点之一,受到了广泛关注,每年在各大会议上都有大量的相关文章发表.当前,点云上的深度学习变得越来越流行,人们提出了许多方法来解决这一领域的不同 ...

  9. Waymo 2020 | 2D/3D目标检测、跟踪和域自适应性冠军解决方案解析

    ©PaperWeekly 原创 · 作者|黄飘 学校|华中科技大学硕士 研究方向|多目标跟踪 随着最近 Waymo Open Dataset Challenges 2020 的落幕,其中关于 2D/3 ...

  10. GitHub 5.9K,目标检测、跟踪、关键点全覆盖的年度开源项目来了!

    关注公众号,发现CV技术之美 目标检测技术作为计算机视觉的基础核心,支撑了包括人脸识别.目标跟踪.关键点检测.图像搜索等等70%以上视觉任务.虽然业界YOLO.Anchor Free.Transfor ...

最新文章

  1. 验证ArrayList是线程不安全的集合
  2. 如何用python画一个小房子?
  3. Python程序练习题5.1-输出更大的田字格。
  4. 织梦wap.php绑定域名,dedecms织梦cms 手机站移动端 绑定设置独立M或wap域名的方法...
  5. 【网络与系统安全】关于SSL/TSL协议的分析
  6. Lang.String
  7. 算法随笔一(背包问题)
  8. es 删除重复数据_怎么标识并删除SPSS数据库里的“重复个案”?
  9. Linux——alias 设置别名详解
  10. 练习-用户模块-注册与登陆 190907
  11. Back to back销售订单和drop ship第三方销售订单的销售成本的问题
  12. .NET开发人员必看:提高ASP.NET Web应用性能的24种方法和技巧——转
  13. php安装libpng,安装php:configure: error: libpng.(a|so) not found解决办法
  14. Java多线程实现多用户与服务端Socket通信
  15. k8s部署-43-带你深入学习ingress-nginx(下)
  16. STM32:使用外部中断控制对射式红外传感器并计次
  17. 今天来说说白色white
  18. android阅读器里的 txt 文本处理分页功能的实现:
  19. 巴比特 | 元宇宙每日必读:用户流失,滞销频现,平台在合规和利润面前该如何平衡?...
  20. cad角度命令怎么输入_CAD阵列命令中角度阵列的使用技巧

热门文章

  1. linux uniq 第一列,linux uniq命令用法
  2. 今天天气很好,心情不错
  3. BUUCTF-Crypto-篱笆墙的影子
  4. 前端js如何展示服务端保存到本地的照片(接收客户端上传的照片)
  5. Python让文档处理变得轻松:如何快速替换Word文档中的关键字
  6. idea上传git被拒绝_IDEA上传项目到gitee被拒绝,解决方式
  7. Spring5_简介和入门案例
  8. Unity --- 场景/场景管理类 与 异步场景加载法
  9. java导入导出有版本兼容问题_Java:实现文件批量导入导出实践(兼容xls,xlsx)...
  10. OpenXLSX的安装与使用(macOS-c++)