# python Opencv实现停车位识别思路详解

> 作者/来源: UCloud 运营管理员
> 发布时间: 2022-12-03T08:14:00.000Z
> 分类: 其他
> 标签: AI, 存储, Python
> 原文链接: http://117.50.162.249:3000/yun/articles/2095

---

# python Opencv实现停车位识别思路详解

> 来源: https://www.ucloud.cn/yun/128392.html
> 作者: 89542767
> 发布日期: 发布于2022-12-03 16:14

小编写这篇文章的一个主要目的，主要是给大家就相关的具体内容做出一些详细解答，比如了解使用python的相关知识，主要是涉及到python Opencv的一些相关知识，比如使用python Opencv实现停车位识别，就具体的内容，下面给大家详细解答下。

**1.怎么去实现**

　　（1）第一是需要用到一个处理画框的程序，将图片中的有车和无车的停车位给画出来，并且保存坐标（如果画错了，将鼠标移至要删除的框中，右击鼠标，即可删除）；

```
　　#定义回调函数
　　def mouseClick(events,x,y,flags,params):
　　#按下鼠标左键，将点击的坐标(x,y)保存到position列表中
　　if(events&cv2.EVENT_LBUTTONDOWN==cv2.EVENT_LBUTTONDOWN):
　　position.append((x,y))
　　#按下鼠标右键时，移除选中的框
　　if(events&cv2.EVENT_RBUTTONDOWN==cv2.EVENT_RBUTTONDOWN):
　　for i,pos in enumerate(position):
　　(x1,y1)=pos
　　if(x1&lt;x&lt;x1+img_width and y1&lt;y&lt;y1+img_height):
　　position.pop(i)
```

![01.png](https://ucloud-blog.cn-bj.ufileos.com/articles/128392/images/128392_000.png)

　　（2）画好之后，关闭窗口，即可看到已经保存好坐标的文件，下次再运行程序时，不用再画框；程序会读出当前文件，将之前保存好的坐标加载出画出框。

　　#首先查看文件是否已经包含了CarParkPos文件

```
　　try:
　　with open('CarParkPos','rb')as fp:
　　position=pickle.load(fp)
　　except:
　　#存储所有停车位的坐标列表
　　position=[]
```

![02.png](https://ucloud-blog.cn-bj.ufileos.com/articles/128392/images/128392_001.png)

　　（3）主程序的思路

　　将摄像头读取的图片进行处理

　　Opencv基础知识点：

　　https://www.jb51.net/article/254006.htm

　　高斯去噪：

　　https://www.jb51.net/article/198212.htm

　　局部二值化：

　　https://www.jb51.net/article/248000.htm

　　中值滤波：

　　https://www.jb51.net/article/198212.htm

　　Opencv中获取卷积核：

　　https://www.jb51.net/article/254013.htm

　　腐蚀操作：

　　https://www.jb51.net/article/214725.htm

```
　　#转换为灰度图
　　gray=cv2.cvtColor(src=frame,code=cv2.COLOR_BGR2GRAY)
　　#高斯去噪
　　gauss=cv2.GaussianBlur(src=gray,ksize=(3,3),sigmaX=0)
　　#图像二值化处理
　　thresh=cv2.adaptiveThreshold(src=gauss,maxValue=255,adaptiveMethod=cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
　　thresholdType=cv2.THRESH_BINARY_INV,blockSize=21,C=16)
　　#中值滤波操作
　　median=cv2.medianBlur(src=thresh,ksize=3)
　　#腐蚀操作
　　dilate=cv2.dilate(src=median,kernel=kernel,iterations=1)
```

```
　　for pos in position:
　　(x,y)=pos
　　mask=dilate[y:y+img_height,x:x+img_width]
　　#cv2.imshow(str(x*y),mask)
　　#返回灰度值不为0的像素数，可用来判断图像是否全黑。
　　count=cv2.countNonZero(mask)
　　#当计算的count低于800,表示是一个空位
　　if count&lt;800:
　　countBlackCar+=1
　　color=(0,255,0)
　　thickness=3
　　else:
　　color=(0,0,255)
　　thickness=2
　　cv2.rectangle(img=frame,pt1=(pos[0],pos[1]),
　　pt2=(pos[0]+img_width,pos[1]+img_height),
　　color=color,thickness=thickness)
　　cvzone.putTextRect(img=frame,text=str(count),pos=(x+3,y+img_height-5),
　　scale=0.8,thickness=1,offset=0,colorR=color)
```

　　参考视频教程：https://www.bilibili.com/video/BV14Z4y1Q7au?t=3992.0（建议看懂视频中的思路）

**2.整体代码实战**

![03.png](https://ucloud-blog.cn-bj.ufileos.com/articles/128392/images/128392_002.png)

　（1）ParkingSpacePicker.py

```
　　import os
　　import cv2
　　import pickle
　　#首先查看文件是否已经包含了CarParkPos文件
　　try:
　　with open('CarParkPos','rb')as fp:
　　position=pickle.load(fp)
　　except:
　　#存储所有停车位的坐标列表
　　position=[]
　　#停车位的高宽
　　img_width,img_height=47,88
　　#定义回调函数
　　def mouseClick(events,x,y,flags,params):
　　#按下鼠标左键，将点击的坐标(x,y)保存到position列表中
　　if(events&cv2.EVENT_LBUTTONDOWN==cv2.EVENT_LBUTTONDOWN):
　　position.append((x,y))
　　#按下鼠标右键时，移除选中的框
　　if(events&cv2.EVENT_RBUTTONDOWN==cv2.EVENT_RBUTTONDOWN):
　　for i,pos in enumerate(position):
　　(x1,y1)=pos
　　if(x1&lt;x&lt;x1+img_width and y1&lt;y&lt;y1+img_height):
　　position.pop(i)
　　with open('CarParkPos','wb')as fp:
　　pickle.dump(position,fp)
　　while True:
　　img=cv2.imread('images/packing.png')
　　for pos in position:
　　cv2.rectangle(img=img,pt1=(pos[0],pos[1]),
　　pt2=(pos[0]+img_width,pos[1]+img_height),
　　color=(0,255,0),thickness=2)
　　cv2.imshow('Packing',img)
　　#设置鼠标事件
　　cv2.setMouseCallback('Packing',mouseClick)
　　key=cv2.waitKey(1)
　　if key==27:
　　break
　　cv2.destroyAllWindows()
　　if __name__=='__main__':
　　print('Pycharm')
```

　　（2）main.py

```
　　import os
　　import cv2
　　import pickle
　　import cvzone
　　with open('CarParkPos','rb')as fp:
　　position=pickle.load(fp)
　　#停车位的高宽
　　img_width,img_height=47,88
　　cap=cv2.VideoCapture('video/packing-3.mp4')
　　def checkParkingSpace(dilate):
　　countBlackCar=0
　　for pos in position:
　　(x,y)=pos
　　mask=dilate[y:y+img_height,x:x+img_width]
　　#cv2.imshow(str(x*y),mask)
　　#返回灰度值不为0的像素数，可用来判断图像是否全黑。
　　count=cv2.countNonZero(mask)
　　#当计算的count低于800,表示是一个空位
　　if count&lt;800:
　　countBlackCar+=1
　　color=(0,255,0)
　　thickness=3
　　else:
　　color=(0,0,255)
　　thickness=2
　　cv2.rectangle(img=frame,pt1=(pos[0],pos[1]),
　　pt2=(pos[0]+img_width,pos[1]+img_height),
　　color=color,thickness=thickness)
　　cvzone.putTextRect(img=frame,text=str(count),pos=(x+3,y+img_height-5),
　　scale=0.8,thickness=1,offset=0,colorR=color)
　　return countBlackCar
　　#获取卷积核
　　kernel=cv2.getStructuringElement(shape=cv2.MORPH_RECT,ksize=(3,3))
　　while cap.isOpened():
　　#循环播放视频文件
　　if cap.get(cv2.CAP_PROP_POS_FRAMES)==cap.get(cv2.CAP_PROP_FRAME_COUNT):
　　cap.set(cv2.CAP_PROP_POS_FRAMES,0)
　　ret,frame=cap.read()
　　#frame=cv2.resize(src=frame,dsize=(750,600))
　　height,width,channel=frame.shape
　　if not ret:
　　break
　　#转换为灰度图
　　gray=cv2.cvtColor(src=frame,code=cv2.COLOR_BGR2GRAY)
　　#高斯去噪
　　gauss=cv2.GaussianBlur(src=gray,ksize=(3,3),sigmaX=0)
　　#图像二值化处理
　　thresh=cv2.adaptiveThreshold(src=gauss,maxValue=255,adaptiveMethod=cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
　　thresholdType=cv2.THRESH_BINARY_INV,blockSize=21,C=16)
　　#中值滤波操作
　　median=cv2.medianBlur(src=thresh,ksize=3)
　　#腐蚀操作
　　dilate=cv2.dilate(src=median,kernel=kernel,iterations=1)
　　cntCar=checkParkingSpace(dilate)
　　cvzone.putTextRect(img=frame,text="BlackPosition:"+str(cntCar),
　　pos=(20,height-80),scale=1.0,thickness=2)
　　cv2.imshow('img',frame)
　　#cv2.imshow('thresh',thresh)
　　#cv2.imshow('median',median)
　　#cv2.imshow('dilate',dilate)
　　key=cv2.waitKey(30)
　　if key==27:
　　break
　　cv2.destroyAllWindows()
　　if __name__=='__main__':
　　print('Pycharm')
```

　　（3）视频效果

![04.png](https://ucloud-blog.cn-bj.ufileos.com/articles/128392/images/128392_003.png)

　　停车位识别演示

　　综上所述，这篇文章就给大家介绍到这里了，希望可以给各位读者带来一定的帮助。