点击上方
“
小白学视觉
”,选择加"
星标
"或“
置顶
”
重磅干货,第一时间送达
该项目基于图像处理来检测停车场中的空间。
该项目将使用 openCV 和 CVzone 库来执行图像处理任务。
如何运行
结合这两个步骤并将它们应用于视频以检查可用的可用空间
过程
1. 安装和导入依赖项
openCV 将允许我们导入图像和视频,然后我们可以对它们应用转换,CVzone作为基于 openCV 的库,它还允许我们使用与 openCV 相比所需语法更少的转换,“Pickel”用于存储在图片上绘制的方框的位置,“numpy”用于应用简单的转换。
import cv2import pickleimport cvzoneimport numpy as np
我们将处理使用 parkingspacepicker.py 绘制框并存储位置,并通过 pickel 在我们的 main.py 中使用这些位置
2. 绘制方框
在此图像中,我们可以看到空间分布不均,并且间隔各不相同。
我们稍后将使用的视频的相机处于静态状态,因此我们可以通过在框上手动绘制框来接近它。
为此,我们需要知道单个框的高度和宽度,然后我们将不得不尝试不同的值以获得完美形状的框
import cv2import pickleimport cvzoneimport numpy as np img = cv2.imread('carParkImg.png' )while True : cv2.rectangle(img,(50 ,1920 ),(157 ,240 ),(255 ,0 ,255 ),2 ) cv2.imshow("image" , img) cv2.waitKey(1 )
在此之后,我们得到 width 和 height = 107, 48 你也可以尝试不同的值。
我们启动一个列表来存储这些值并编写一个函数来检测鼠标点击操作,你可以在下一个片段中看到
img = cv2.imread('carParkImg.png' ) width, height = 107 , 48 def mouse_click (events, x, y, flags, params) : if events == cv2.EVENT_LBUTTONDOWN: posList.append((x, y))#and to see what we are drwaing on the screen while True : for pos in posList: cv2.rectangle(img, pos, (pos[0 ] + width, pos[1 ] + height), (255 , 0 , 255 ), 2 ) cv2.imshow("Image" , img) cv2.setMouseCallback("Image" , mouse_click) cv2.waitKey(1 )
在 mouse_click 函数中,我们将events, x, y, flags, params作为参数传递,如果events == cv2.EVENT_LBUTTONDOWN,则将值 (x, y) 附加到 posList 并查看我们在屏幕上绘制的内容,我们将在我们的 posList 值上编写一个 for 循环。
我在这里遇到了两个问题:
加载图像后只生成一帧,因此对该图像的任何修改都不会显示
对于第 1 个问题的解决方案,我修改了mouse_click函数,将右键单击按钮作为一个事件,然后我们将检查我们的单击点是否位于其中一个位置之间,我们将删除它。
def mouse_click (events, x, y, flags, params) : if events == cv2.EVENT_LBUTTONDOWN: posList.append((x, y)) if events == cv2.EVENT_RBUTTONDOWN: for i, pos in enumerate(posList): x1, y1 = pos if x1 and y1 posList.pop(i)
我们将检查当前的x是否在x1
对于问题2-因为我们的图像只被导入一次,所以无论在其上绘制什么都将保持不变,我们在网络摄像头或相机中不会遇到此问题,并且我们正在处理的是静态图像,因此我们必须在循环中导入它以获得删除框。
在绘制所有框后,现在我们必须将它们存储为pickle对象并以一种方式存储它们,以便我们不必每次都进行制作,并且我们可以使用先前的对象或修改现有的对象。
img = cv2.imread('carParkImg.png' ) width, height = 107 , 48 try : with open('CarParkPos' , 'rb' ) as f: posList = pickle.load(f)except : posList = []def mouse_click (events, x, y, flags, params) : if events == cv2.EVENT_LBUTTONDOWN: posList.append((x, y)) if events == cv2.EVENT_RBUTTONDOWN: for i, pos in enumerate(posList): x1, y1 = pos if x1 and y1 posList.pop(i) with open('CarParkPos' , 'wb' ) as f: pickle.dump(posList, f)while True : img = cv2.imread('carParkImg.png' ) for pos in posList: cv2.rectangle(img, pos, (pos[0 ] + width, pos[1 ] + height), (255 , 0 , 255 ), 2 ) cv2.imshow("Image" , img) cv2.setMouseCallback("Image" , mouse_click) cv2.waitKey(1 )
这将创建一个对象 CarParkPos 并检查该对象是否已经存在
图像处理(main.py)
加载视频馈送并循环进行循环,我们将对帧进行计数,当帧到达时,我们将重置它,以便获得连续的视频
import cv2import pickleimport cvzoneimport numpy as np# video feed cap = cv2.VideoCapture('carPark.mp4' )while True : if cap.get(cv2.CAP_PROP_POS_FRAMES) == cap.get(cv2.CAP_PROP_FRAME_COUNT): cap.set(cv2.CAP_PROP_POS_FRAMES, 0 ) success, img = cap.read() cv2.imshow("Image" , img) cv2.waitKey(10 )
将框位置加载到我们将使用 pickle 对象的视频上,并定义我们之前找到的宽度和高度
with open('CarParkPos' , 'rb' ) as f: posList = pickle.load(f) width, height = 107 , 48
我们需要裁剪这些位置以供以后转换,为此我们将编写一个函数
def checkParkingSpace (imgPro) : for pos in posList: x, y = pos imgCrop = imgPro[y:y + height, x:x + width] cv2.imshow(str(x * y), imgCrop)while True : if cap.get(cv2.CAP_PROP_POS_FRAMES) == cap.get(cv2.CAP_PROP_FRAME_COUNT): cap.set(cv2.CAP_PROP_POS_FRAMES, 0 ) for pos in posList: cv2.rectangle(img, pos, (pos[0 ] + width, pos[1 ] + height), (255 , 0 , 255 ), 2 ) success, img = cap.read() cv2.imshow("Image" , img) cv2.waitKey(10 )
裁剪后绘制出方框,这将为裁剪区域提供完美的视角,现在我们需要找出其中哪个区域有汽车。
我们可以通过查看像素计数来做到这一点,在图像处理中,我们可以使用边缘和角点检测算法来将图像转换为二进制形式,并计算出图像中的边缘和角点数量。在二值化后的图像中,黑色像素表示背景,白色像素表示前景。通过分析这些二值化后的图像中的边缘和角点数目,我们可以了解到关于该图像的一些信息,如图像是否具有结构性、复杂度等信息,来确定图像的特点。在此基础上,我们可以继续下一步的分析或处理。
为了确定该区域是否包含汽车,我们必须首先使用 OpenCV 和 CVzone 进行一些阈值处理,我们将图像转换为灰度并应用高斯模糊,然后我们将其转换为二值图像,我们将使用自适应阈值和去除椒盐噪声,我们使用“medianBlur”和主动内核来去除噪声,有时这些像素非常小,为了更好地区分,我们将使用膨胀操作。
应用所有滤镜后的图像
if cap.get(cv2.CAP_PROP_POS_FRAMES) == cap.get(cv2.CAP_PROP_FRAME_COUNT): cap.set(cv2.CAP_PROP_POS_FRAMES, 0 ) success, img = cap.read() imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) imgBlur = cv2.GaussianBlur(imgGray, (3 , 3 ), 1 ) imgThreshold = cv2.adaptiveThreshold(imgBlur, 255 , cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 25 , 16 ) imgMedian = cv2.medianBlur(imgThreshold, 5 ) kernel = np.ones((3 , 3 ), np.uint8) imgDilate = cv2.dilate(imgMedian, kernel, iterations=1 ) checkParkingSpace(imgDilate) cv2.imshow("Image" , img) # cv2.imshow("ImageBlur", imgBlur) # cv2.imshow("ImageThres", imgMedian) cv2.waitKey(10 )
所有的值都作为参数传递,通过尝试不同的值来获得,现在我们将这个处理过的图像传递给我们的裁剪函数
def checkParkingSpace (imgPro) : spaceCounter = 0 for pos in posList: x, y = pos imgCrop = imgPro[y:y + height, x:x + width] # cv2.imshow(str(x * y), imgCrop) count = cv2.countNonZero(imgCrop) if count 900: color = (0 , 255 , 0 ) thickness = 5 spaceCounter += 1 else