OpenCV计算机视觉实战(Python)| 14、项目实战:停车场车位识别

本文主要是介绍OpenCV计算机视觉实战(Python)| 14、项目实战:停车场车位识别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 简介
  • 总结
    • 1、项目介绍
    • 2、步骤
    • 3、程序

简介

本节为《OpenCV计算机视觉实战(Python)》版第14讲,项目实战:停车场车位识别,的总结。

总结

1、项目介绍

统计:

  1. 有多少停车位
  2. 哪些个停车位被占据,哪些个停车位没有被占据
    在这里插入图片描述

2、步骤

  1. 选取区域:人工选择停车场所在的位置,只保存停车场所在的区域图像
  2. 预处理:灰度、边缘、霍夫
  3. 微调:针对实际的项目,由于背景是没变的,当结果不正确时,可以人为给定数据对结果进行微调
  4. 分类:以簇的形式,将每一列的停车场数据保存,保存每一列矩阵的坐标点
  5. 分割:以实际项目选取合适的值,将每一列分割成一个个小块,每一个小块代表一个停车场的位置
  6. 深度训练:以空停车位做分类训练,判断停车场某个停车位上有没有车;

3、程序

Parking.py:

class Parking:def cv_show(name, image):cv2.imshow(name, image)cv2.waitKey(0)cv2.destroyAllWindows()def select_rgb_white_yellow(self, image):# 过滤掉背景lower = np.uint8([120, 120, 120])upper = np.uint8([255, 255, 255])# lower_red和高于upper_red的部分分别变成0,lower_red-upper_red之间的值变成255,相当于过滤背景white_mask = cv2.inRange(image, lower, upper)self.cv_show('white_mask', white_mask)masked = cv2.bitwise_and(image, image, mask=white_mask)self.cv_show('masked', masked)return maskeddef convert_gray_scale(self, image):return cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)def detect_edges(self, image, low_threshold=50, high_threshold=200):return cv2.Canny(image, low_threshold, high_threshold)def filter_region(self, image, vertices):"""剔除掉不需要的地方"""mask = np.zeros_like(image)if len(mask.shape)==2:cv2.fillPoly(mask, vertices, 255)self.cv_show('mask', mask)return cv2.bitwise_and(image, mask)def select_region(self, image):"""手动选择区域"""	# first, define the polygon by verticesrows, cols = image.shape[:2]pt_1 = [cols*0.05, rows * 0.90]pt_2 = [cols*0.05, rows * 0.70]pt_3 = [cols*0.30, rows * 0.55]pt_4 = [cols*0.6, rows * 0.15]pt_5 = [cols*0.90, rows * 0.15]pt_6 = [cols*0.90, rows * 0.90]vertices = np.array([[pt_1, pt_2, pt_3, pt_4, pt_5, pt_6]], dtype=np.int32)point_img = img.copy()point_img = cv2.cvtcolor(point_img, cv2.COLOR_GRAY2RGB)for point in vertices[0]:cv2.circle(point_img, (point[0], point[1]), 10, (0,0.255), 4)self.cv_show('point_img', point_img)return self.filter_region(image, vertices)def hough_lines(self, image):#阈值越大,直线越少return cv2.HoughLinesP(image, rho=0.1, theta=np.pi/10, threshold=15, minLineLength=0, maxLineGap=4)def draw_lines(self, image, lines, color=[255, 0, 0], thickness=2, make_cope=True):# 过滤霍夫变换坚持到到直线if make_copy:image = np.copy(image)cleaned = []for line in lines:for x1,y1,x2,y2 in line:if abs(y2-y1) <=1 and abs(x2-x1)>25 and abs(x2-x1)<=55:cleaned.append((x1, y1, x2, y2))cv2.line(image, (x1,y1), (x2,y2), color, thickness)print('No lines detected:', len(cleaned))return imagedef identify_blocks(self, image, lines, make_copy=TRUE):if make_copy:new_image = np.copy(image)# step1:过滤部分直线cleaned = []for line in lines:for x1, y1, x2, y2 in line:if abs(y2-y1)<=1 and abs(x2-x1)>=25 and abs(x2-x1)<=55:cleaned.append((x1,y1,x2,y2))# Step2:对直线按照x1进行排序import operatorlist1 = sorted(cleaned, key=operator.itemgetter(0,1))# Step3: 找到多个列,相当于每列是一排车clusters = {}dIndex = 0clus_dist = 10for i in range(len(list1) - 1):distance = abs(list1[i+1][0] - list1[i][0])if distance <= clus_dist:if not dIndex in clusters.keys():clusters[dIndex] = []clusters[dIndex].append(list1[i])clusters[dIndex].append(list1[i+1])else:dIndex +=1# Step4:得到坐标rects = {}i = 0for key in clusters:all_list = clusters[key]cleaned = list(set(all_list))if len(cleaned) > 5:cleaned = sorted(cleaned, key = lambda tup:tup[1])avg_y1 = cleaned[0][1]avg_y2 = cleaned[-1][1]avg_x1 = 0avg_x2 = 0for tup in cleaned:avg_x1 += tup[0]avg_x2 += tup[2]avg_x1 = avg_x1/len(cleaned)avg_x2 = avg_x2/len(cleaned)rects[i] = (avg_x1, avg_y1, avg_x2, avg_y2)i +=1print('Num parking Lanes:', len(rects))# Step5:得到坐标rects = {}i = 0for key in clusters:all_list=cluseters[kye]cleaned = list(set(all_list))if len(cleaned) > 5:cleaned = sorted(cleaned, key=lambda tup:tup[1])avg_y1 = cleaned[0][1]avg_y2 = cleaned[-1][1]avg_x1 = 0avg_x2 = 0for tup in cleaned:avg_x1 += tup[0]avg_x2 += tup[2]avg_x1 = avg_x1/len(cleaned)avg_x2 = avg_x2/len(cleaned)rects[i] = (avg_x1, avg_y1, avg_x2, avg_y2)i+=1print('Num Parking Lanes:', len(rects))# Step5: 把列矩形给画出来buff = 7for key in rects:tup_topLeft = (int(rects[key][0] - buff), int(rects[key][1]))tup_botRight = (int(rects[key][2] + buff), int(rects[key][3]))cv2.rectangle(new_image, tup_topLeft, tup_botRight, (0,255,0),3)return new_image, rectsdef draw_parking(self, image, rects, make_copy=True,, color=[255,0,0], thickness=2,save=True):if make_copy:new_image = np.copy(image)gap = 15.5spot_dict = {} # 字典:一个车位对应一个位置tot_spots = 0#微调adj_y1 = {0:20, 1:-10, 2:0, 3:-11, 4:28, 5:5, 6:-15, 7:-15, 8:-10, 9:-30, 10:9, 11:-32}adj_y2 = {0:30, 1:50, 2:15, 3:10, 4:-15, 5:15, 6:15, 7:-20, 8:15, 9:15, 10:0, 11:30}adj_x1 = {}adj_x2 = {}for key in rects:tup = rects[key]x1 = int(tup[0]+adj_x1[key])x2 = int(tup[2] + adj_x2[key])y1 = int(tup[1] + adj_y1[key])y2 = int(tup[3] + adj_y2[key])cv2.rectangle(new_image, (x1,y1), (x2, y2), (0,255,0), 2)num_splits = int(abs(y2-y1)//gap)for in in range(0, num_splits +1):y = int(y1 + i*gap)cv2.line(new_image, (x1, y), (x2, y), color, thickness)if key>0 and key<len(rects)-1:# 竖直线x = int((x1+x2)/2cv.line(new_image, (x, y1), (x,y2), color, thickness)# 计算数量if key == 0 or key == (len(rects) -1):tot_spots += num_splits +1else:tot_spots += 2*(num_splits + 1)# 字典对应好if key ==9 or key == len(rects) -1):for i in range(0, num_splits +1):cur_len = len(spot_dict)y = int(y1 + i * gap)spot_dict[(x1, y, x2, y+gap)] = cur_len + 1else:for i in range(0, num_splits +1):cur_len  = len(spot_dict)y = int(y1 + i * gap)x = int((x1 + x2)/2)spot_dict[(x1, y, x, y+gap)] = cur_len + 1spot_dict[(x, y, x2, y+gap)] = cur_len + 2print('total parking spaces:', tot_spots, cur_len)if save:filename = 'with_parking.jpg'cv2.imwrite(filename, new_image)return new_image, splt_dictdef save_images_for_cnn(self, image, spot_dict, folder_name = 'cnn_data'):for spot in spot_dict.keys():(x1, y1, x2, y2) = spot(x1, y1, x2, y2) = (int(x1), int(y1), int(x2), int(y2))#裁剪spot_img = image[y1:y2, x1:x2]spot_img = cv2.resize(spot_img, (0,0), fx=2.0, fy=2.0)spot_id = spot_dict[spot]filename = 'spot' + str(spot_id) + '.jpg'print(spot_img.shape, filename, (x1,x2, y1, y2))cv2.imwrite(os.path.join(folder_name, filename), spot_img)

train.py:(神经网络训练文件,此处略去)

import numpy as np
...

main.py:(主程序)

from __future__ import division
import matplotlib.pyplot as plt
import cv2
import os,glob
import numpy as np
from PIL import Image
from keras.applications.imagenet_utils import preprocess_input
from keras.models import image
from keras.preprocessing import image
from Parking import Parking
import picklecwd = os.getcwd()def img_process(test_images, park):white_yellow_images = list(map(park.select_rgb_white_yellow, test_images))park.show_images(white_yellow_images)gray_images = list(map(park.convert_gray_scale, white_yellow_images))park.show_images(gray_images)edge_images = list(map(lambda image:park.detect_edges(image), gray_images))park.show_images(edge_images)roi_images = list(map(park.select_region, edge_images))park.show_images(roi_images)list_of_lines = list(map(park.hough_lines, roi_images))line_images = []for image, lines in zip(test_images, list_of_lines):line_images.append(park.draw_lines(image, lines))park.show_images(lien_images)rect_images = []rect_coords = []for image, lines in zip(test_images, list_of_lines):new_image, rects = park.identify_blocks(image, lines)rect_images.append(new_image)rect_coords.append(rects)park.show_images(rect_images)delineated = []spot_pos = []for image, rects in zip(test_images, rect_coords):new_image, spot_dict = park.draw_parking(image, rects)delineated.append(new_image)spot_pos.append(spot_dict)park.show_images(delineated)final_spot_dict = spot_pos[1]print(len(final_spot_dict)with open('spot_dict.pickle', 'wb') as handle:pickle.dump(final_spot_dict, handle, protocol=pickle.HIGHEST_PROTOCOL)park.save_images_for_cnn(test_images[0], final_spot_dict)return final_spot_dict
def keras_model(weights_path):model = load_model(weights_path)return model
def img_test(test_images, final_spot_dict, model, class_dictionary):for i in range(len(test_images)):predicted_images = park.predict_on_image(test_images[i], final_spot_dict, class_dictionary)if __name__ == '__main__':test_images = [plt.imread(path) for path in glob.glob('test_images/*.jpg')]weights_path = 'car1.h5'video_name = 'parking_video.mp4'class_dictionary[0] = 'empty'class_dictionary[1] = 'occupied'park = Parking()park.show_images(test_images)final_spot_dict = img_process(test_images, park)# 本文所附录出的程序代码仅到img_process处,往下的这些代码没有给出,感兴趣的可以自行看课程model = keras_model(weights_path)img_test(test_images, final_spot_dict, model, class_dictionary)video_test(video_name, final_spot_dict, model, class_dictionary)

这篇关于OpenCV计算机视觉实战(Python)| 14、项目实战:停车场车位识别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/760977

相关文章

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

Python正则表达式匹配和替换的操作指南

《Python正则表达式匹配和替换的操作指南》正则表达式是处理文本的强大工具,Python通过re模块提供了完整的正则表达式功能,本文将通过代码示例详细介绍Python中的正则匹配和替换操作,需要的朋... 目录基础语法导入re模块基本元字符常用匹配方法1. re.match() - 从字符串开头匹配2.

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

通过Docker容器部署Python环境的全流程

《通过Docker容器部署Python环境的全流程》在现代化开发流程中,Docker因其轻量化、环境隔离和跨平台一致性的特性,已成为部署Python应用的标准工具,本文将详细演示如何通过Docker容... 目录引言一、docker与python的协同优势二、核心步骤详解三、进阶配置技巧四、生产环境最佳实践

Python一次性将指定版本所有包上传PyPI镜像解决方案

《Python一次性将指定版本所有包上传PyPI镜像解决方案》本文主要介绍了一个安全、完整、可离线部署的解决方案,用于一次性准备指定Python版本的所有包,然后导出到内网环境,感兴趣的小伙伴可以跟随... 目录为什么需要这个方案完整解决方案1. 项目目录结构2. 创建智能下载脚本3. 创建包清单生成脚本4

MyBatis分页查询实战案例完整流程

《MyBatis分页查询实战案例完整流程》MyBatis是一个强大的Java持久层框架,支持自定义SQL和高级映射,本案例以员工工资信息管理为例,详细讲解如何在IDEA中使用MyBatis结合Page... 目录1. MyBATis框架简介2. 分页查询原理与应用场景2.1 分页查询的基本原理2.1.1 分

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结