作者|Hitesh Valecha
编译|VK
起源|Towards Data Science
在本教程中,咱们将学习如何应用计算机视觉和图像处理来检测汽车是否在路上变道。
你肯定据说过应用Opencv haar cascade能够检测人脸、眼睛或汽车、公共汽车等物体?这次让咱们用这个简略的检测办法来构建一些很酷的货色。
1.数据集
在本教程中,路线上汽车的视频文件被用作数据集。此外,咱们能够应用图像数据集检测图像中的车辆,但在这里,当车辆变道时,咱们会用弹出窗口收回警报,因而对于这些动静信息,视频输出更为可行。
2.输出
咱们应用OpenCV的haar cascade来检测汽车的坐标,输出是路线上汽车的视频文件
cascade_src = 'cascade/cars.xml'video_src = 'dataset/cars.mp4'cap = cv2.VideoCapture(video_src)car_cascade = cv2.CascadeClassifier(cascade_src)
cv2.VideoCapture()办法用于捕捉输出的视频,一个视频通常是每秒25帧图像(fps)。在捕捉到输出后,循环提取帧,并利用haar cascade检测,在循环中围绕汽车绘制一个矩形,以取得一致性,同时对捕捉的帧执行其余操作。
while(1): # 获取每一帧 _, frame = cap.read() cars = car_cascade.detectMultiScale(frame, 1.1, 1) for (x,y,w,h) in cars: roi = cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255),2) #感兴趣区域
在OpenCV中应用BGR而不是RGB,因而(0,0,255)将在汽车上绘制一个红色矩形,而不是蓝色。
3.图像处理
咱们应用帧,然而如果帧的分辨率十分高,它将减慢执行的操作,此外,帧蕴含噪声,能够应用含糊来缩小,这里应用高斯含糊。
当初,让咱们看看一些图像处理的概念
3.1 HSV框架
在这篇文章中,咱们应用从cv2.VideoCapture()捕捉的帧中获取HSV帧,仅突出显示车辆转弯的点,并遮住残余的路线和在路线上直线行驶的车辆。设置下限和上限以定义HSV中的色彩范畴,以查看汽车变道的点,并用作帧的掩码。上面是用于获取此信息的代码片段-
# 应用含糊打消视频帧中的噪声frame = cv2.GaussianBlur(frame,(21,21),0)# 转换BGR到HSVhsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)# 在HSV中定义色彩范畴,以查看车辆扭转角度的点lower_limit = np.array([0,150,150])upper_limit = np.array([10,255,255])# HSV图像限度阈值mask = cv2.inRange(hsv, lower_limit, upper_limit)
3.2侵蚀和收缩
侵蚀和收缩是用于图像处理的两种根本形态学操作。侵蚀算子对核函数的区域有部分最小值的影响,核函数是模板或掩码。侵蚀是用来缩小图像中的斑点噪声。收缩是图像与核的卷积,它具备部分最大算子的作用。当像素被增加到图像中平滑物体的边界时,利用收缩来复原一些失落的区域。
从HSV帧的第一步生成的掩码当初用根本的形态学操作(侵蚀和扩张)来解决。生成的帧是通过将帧和掩码之间的按位与运算失去ROI(感兴趣区域)。
kernel = np.ones((3,3),np.uint8)kernel_lg = np.ones((15,15),np.uint8)# 被称为侵蚀的图像处理技术用于降噪mask = cv2.erode(mask,kernel,iterations = 1)# 称为收缩的图像处理技术,用来复原失去的局部区域mask = cv2.dilate(mask,kernel_lg,iterations = 1)# 除了感兴趣的区域,其余中央都变成彩色result = cv2.bitwise_and(frame,frame, mask= mask)
3.3车道检测
利用canny边缘检测算子联合Hough线变换进行车道检测。
#车道检测def canny(frame): gray=cv2.cvtColor(frame,cv2.COLOR_RGB2GRAY) blur=cv2.GaussianBlur(gray,(5,5),0) canny=cv2.Canny(blur,50,150) return canny def region_of_interest(frame): height=frame.shape[0] polygons=np.array([ [(0,height),(500,0),(800,0),(1300,550),(1100,height)] ]) mask=np.zeros_like(frame) cv2.fillPoly(mask,polygons,255) masked_image=cv2.bitwise_and(frame,mask) return masked_image def display_lines(frame,lines): line_image=np.zeros_like(frame) if lines is not None: for line in lines: x1,y1,x2,y2=line.reshape(4) cv2.line(line_image, (x1, y1), (x2, y2), (0, 255, 0), 3) return line_imagelane_image=np.copy(frame)canny=canny(lane_image)cropped_image=region_of_interest(canny)lines=cv2.HoughLinesP(cropped_image,2,np.pi/180,100,np.array([]),minLineLength=5,maxLineGap=300)line_image=display_lines(lane_image,lines)frame=cv2.addWeighted(lane_image,0.8,line_image,1,1)cv2.imshow('video', frame)
4.等高线
canny边缘检测器等算法用于查找边缘像素图像中的边缘分界,但它并没有通知咱们如何找到对象或实体不能联合的点和边,这里咱们能够应用OpenCV实现的cv2.findContours()作为轮廓的概念。
定义-“轮廓示意图像中曲线的点的列表。”
轮廓由序列示意,每个序列都对下一个点的地位信息进行编码。咱们在roi中屡次运行cv2.findConteurs()来获取实体,而后应用cv2.drawContours()绘制轮廓区域。轮廓能够是点、边、多边形等,所以在绘制等高线时,咱们做多边形近似,求出边的长度和区域的面积。
函数cv2.drawContours()的工作原理是从根节点开始绘制一棵树(数据结构),而后连贯后续点、边界框和Freeman链码。
thresh = maskcontours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)# 定义轮廓的最小面积(疏忽min以下的所有值)min_area = 1000cont_filtered = []# 过滤掉最小面积以下的所有轮廓线for cont in contours: if cv2.contourArea(cont) > min_area: cont_filtered.append(cont) cnt = cont_filtered[0]# 围绕轮廓画出矩形rect = cv2.minAreaRect(cnt)box = cv2.boxPoints(rect)box = np.int0(box)cv2.drawContours(frame,[box],0,(0,0,255),2)rows,cols = thresh.shape[:2][vx,vy,x,y] = cv2.fitLine(cnt, cv2.DIST_L2,0,0.01,0.01)lefty = int((-x*vy/vx) + y)righty = int(((cols-x)*vy/vx)+y)cv2.line(frame,(cols-1,righty),(0,lefty),(0,255,0),2)
找到轮廓后的另一个重要工作是匹配它们。匹配轮廓意味着咱们有两个独立的计算轮廓来互相比拟,或者有一个轮廓与一个形象模板进行比拟。
5.特色矩
咱们能够通过计算轮廓矩来比拟两个轮廓。“特色矩是轮廓的总特色,通过将轮廓的所有像素相加来计算。”
力矩类型
空间特色矩:m00, m10, m01, m20, m11, m02, m30, m21, m12, m03.
核心特色矩:mu20, mu11, mu02, mu30, mu21, mu12, mu03.
Hu特色矩:有七个Hu特色矩(h0-h6)或(h1-h7),这两个符号都应用。
咱们应用cv2.fitEllipse()计算特色矩并在点上拟合椭圆。从轮廓线和特色矩中找到角度,因为扭转车道须要45度旋转,这被视为汽车转弯角度的阈值。
M = cv2.moments(cnt)cx = int(M['m10']/M['m00'])cy = int(M['m01']/M['m00'])(x,y),(MA,ma),angle = cv2.fitEllipse(cnt)print('x= ', cx, ' y= ', cy, ' angle = ', round(rect[2],2))if(round(rect[2],2))<-45: # print('Lane change detected') popupmsg('Lane change detected')
当初,咱们能够应用Tkinter来创立一个简略的弹出窗口来正告变动,而不仅仅是打印变动的检测后果。
if(round(rect[2],2))<-45: popupmsg('Lane change detected')def popupmsg(msg): popup = tk.Tk() popup.wm_title("Message") label = ttk.Label(popup, text=msg, font=NORM_FONT) label.pack(side="top", fill="x", pady=10) B1 = ttk.Button(popup, text="Okay", command = popup.destroy) B1.pack() popup.mainloop()
在车架上画矩形,用绿线测量角度
6.总结和将来
在本教程中,将应用车道变化检测办法摸索智能汽车导航的一个小演示。
计算机视觉正在迅速倒退,它的利用不仅在汽车的部分导航,而且在火星上的导航和产品检测畛域也在提高,甚至在医学利用中也在开发和用于晚期在X射线图像中检测癌症和肿瘤。
单击此处获取GitHub帐户的源代码:https://github.com/Hitesh-Val...
参考文献
- Bradski, Gary and Kaehler, Adrian, Learning OpenCV: Computer Vision in C++ with the OpenCV Library, O’Reilly Media, Inc., 2nd edition, 2013, @10.5555/2523356, ISBN — 1449314651.
- Laganiere, Robert, OpenCV Computer Vision Application Programming Cookbook, Packt Publishing, 2nd edition, 2014, @10.5555/2692691, ISBN — 1782161481.
原文链接:https://towardsdatascience.co...
欢送关注磐创AI博客站:
http://panchuang.net/
sklearn机器学习中文官网文档:
http://sklearn123.com/
欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/