在本教程中,我们将学习如何基于Opencv和Python实现对象跟踪。 首先必须明确目标检测和目标跟踪有什么区别:1。目标检测是每一帧每一帧的检测。2。对象跟踪会逐帧跟踪,但会一次又一次地保留对象所在位置的历史记录 我们将首先讨论对象检测,然后讨论如何将对象跟踪应用于检测。1。有哪些可能的应用? 可能有不同的应用,例如,计算某个区域有多少人,检查传送带上有多少物体通过,或者计算高速公路上的车辆。 当然,看过本教程后,您会很容易地想到数以千计的想法应用于现实生活或可能应用于工业。2。我们需要什么? 在本教程中,我们将使用3个文件:highway。mp4我们将用来统计车辆数量的高速公路视频tracker。py这已经写好了,你可以简单地下载它main。py主函数 3。物体检测 首先我们需要调用highway。mp4文件并创建一个mask:capcv2。VideoCapture(highway。mp4)来自稳定相机的物体检测objectdetectorcv2。createBackgroundSubtractorMOG2()whileTrue:ret,framecap。read()1。物体检测maskobjectdetector。apply(frame) 正如您在示例代码中看到的,我们还使用了createBackgroundSubtractorMOG2函数,该函数返回背景比率(backgroundratio),然后创建mask。 mask可视化结果: 但是,如您所见,图像中有很多噪点。因此,让我们通过删除所有较小的元素来改进提取,并将我们的注意力集中在大于某个面积的对象上。,maskcv2。threshold(mask,254,255,cv2。THRESHBINARY)contours,cv2。findContours(mask,cv2。RETRTREE,cv2。CHAINAPPROXSIMPLE)forcntincontours:计算面积,去除小元素areacv2。contourArea(cnt)ifarea100:显示 使用OpenCV的cv2。drawContours函数绘制轮廓,我们得到了这个结果。 4。我们定义一个感兴趣的区域 就本教程而言,分析整个窗口并不重要。我们只对计算在某个点通过的所有车辆感兴趣,因此,我们必须定义一个感兴趣的区域ROI并仅在该区域应用mask。whileTrue:ret,framecap。read()height,width,frame。shape提取感兴趣区域roiframe〔340:720,500:800〕1。物体检测maskobjectdetector。apply(roi),maskcv2。threshold(mask,254,255,cv2。THRESHBINARY)contours,cv2。findContours(mask,cv2。RETRTREE,cv2。CHAINAPPROXSIMPLE)forcntincontours:计算面积并去除小元素areacv2。contourArea(cnt)ifarea100:cv2。drawContours(roi,〔cnt〕,1,(0,255,0),2) 结果可视化如下: 函数cv2。createBackgroundSubtractorMOG2是在开始时添加的,没有定义参数,现在让我们看看如何进一步改进我们的结果。history是第一个参数,在这种情况下,它设置为100,因为相机是固定的。varThreshold改为40,因为该值越低,误报的可能性就越大。在这种情况下,我们只对较大的对象感兴趣。来自稳定相机的物体检测objectdetectorcv2。createBackgroundSubtractorMOG2(history100,varThreshold40) 5。在对象周围画出方框 在继续处理矩形之前,我们对图像进行了进一步的清理。为此,阈值函数就派上用场了。从我们的mask开始,我们告诉它我们只想显示白色或黑色值,因此通过编写254,255,只会考虑254和255之间的值。,maskcv2。threshold(mask,254,255,cv2。THRESHBINARY) 然后我们将找到的对象的坐标插入到if条件中并绘制矩形x,y,w,hcv2。boundingRect(cnt)cv2。rectangle(roi,(x,y),(xw,yh),(0,255,0),3) 这是最终结果: 6。对象追踪 我们现在只需导入和集成跟踪功能。fromtrackerimportCreatetrackerobjecttrackerEuclideanDistTracker() 一旦创建了对象,我们必须获取边界框的每个位置并将它们插入到单个数组中。detections。append(〔x,y,w,h〕) 通过在屏幕上显示结果,您可以看到所有通过ROI的通道是如何被识别的,以及它们的位置是如何插入到特定的数组中的。显然,识别的摩托车越多,我们的数组就越大。 7。将唯一ID关联到对象 现在让我们将带有位置的数组传递给tracker。update()。我们将再次获得一个包含位置的数组,但此外,将为每个对象分配一个唯一的ID。 从代码中可以看出,我们可以使用for循环分析所有内容。此时我们只需要绘制矩形并显示车辆ID。2。目标跟踪boxesidstracker。update(detections)forboxidinboxesids:x,y,w,h,idboxidcv2。putText(roi,str(id),(x,y15),cv2。FONTHERSHEYPLAIN,2,(255,0,0),2)cv2。rectangle(roi,(x,y),(xw,yh),(0,255,0),3) 在图像中,您可以看到结果 8。完整代码tracker。pyimportmathclassEuclideanDistTracker:definit(self):存储对象的中心位置self。centerpoints{}保持id的计数每次检测到新的对象id时,计数将增加1self。idcount0defupdate(self,objectsrect):对象框和IDobjectsbbsids〔〕获取新对象的中心点forrectinobjectsrect:x,y,w,hrectcx(xxw)2cy(yyh)2查明是否已经检测到该对象sameobjectdetectedFalseforid,ptinself。centerpoints。items():计算中心点之间的欧式距离distmath。hypot(cxpt〔0〕,cypt〔1〕)如果欧氏距离小于25即表明是相同的目标ifdist25:self。centerpoints〔id〕(cx,cy)print(self。centerpoints)objectsbbsids。append(〔x,y,w,h,id〕)sameobjectdetectedTruebreak检测到新对象,我们将ID分配给该对象ifsameobjectdetectedisFalse:self。centerpoints〔self。idcount〕(cx,cy)objectsbbsids。append(〔x,y,w,h,self。idcount〕)self。idcount1按中心点清理字典以删除不再使用的IDSnewcenterpoints{}forobjbbidinobjectsbbsids:,,,,objectidobjbbidcenterself。centerpoints〔objectid〕newcenterpoints〔objectid〕center更新字典self。centerpointsnewcenterpoints。copy()returnobjectsbbsids main。pyimportcv2fromtrackerimport创建跟踪器对象trackerEuclideanDistTracker()capcv2。VideoCapture(highway。mp4)来自稳定相机的物体检测objectdetectorcv2。createBackgroundSubtractorMOG2(history100,varThreshold40)whileTrue:ret,framecap。read()height,width,frame。shape提取感兴趣区域roiframe〔340:720,500:800〕1。物体检测maskobjectdetector。apply(roi),maskcv2。threshold(mask,254,255,cv2。THRESHBINARY)contours,cv2。findContours(mask,cv2。RETRTREE,cv2。CHAINAPPROXSIMPLE)detections〔〕forcntincontours:计算面积并去除小元素areacv2。contourArea(cnt)ifarea100:cv2。drawContours(roi,〔cnt〕,1,(0,255,0),2)x,y,w,hcv2。boundingRect(cnt)detections。append(〔x,y,w,h〕)2。对象追踪boxesidstracker。update(detections)forboxidinboxesids:x,y,w,h,idboxidcv2。putText(roi,str(id),(x,y15),cv2。FONTHERSHEYPLAIN,2,(255,0,0),2)cv2。rectangle(roi,(x,y),(xw,yh),(0,255,0),3)cv2。imshow(roi,roi)cv2。imshow(Frame,frame)cv2。imshow(Mask,mask)keycv2。waitKey(30)ifkey27:breakcap。release()cv2。destroyAllWindows() 结论 从视频中也可以看到,我们已经获得了我们在本教程开始时设置的结果。 但是,您必须将其视为练习或起点,因为关于这个主题有很多话要说,而本教程的目的只是让您了解对象跟踪的原理。 如果你想将ObjectTracking集成到你的项目中,你应该使用更可靠和先进的对象检测方法,以及跟踪方法。 完整代码地址:私信333直接获取或者链接