目录
一、学习视频b站
【2022年唐宇迪新全【OpenCV入门到实战】课程分享!原来学习OpenCV可以这么简单,超级通俗易懂!(附配套学习资料)-人工智能\图像处理\计算机视觉】 https://www.bilibili.com/video/BV1CZ4y1f7a2/?p=63&share_source=copy_web&vd_source=670a778bb5c4b23b3c6468afac06c621
二、项目介绍
该项目利用opencv图像处理和keras神经网络实现一段停车场视频的车位识别,训练完后可以识别每个车位是否为空车位以及车位数量。
三、代码按程序步骤学习
1.主程序
if __name__ == '__main__':
#使用列表推导式来读取指定目录下的所有.jpg格式的图片文件,对两张图片分别进行变换
test_images = [plt.imread(path) for path in glob.glob('test_images/*.jpg')]
#car1是训练完网络模型得到的模型结果,第二阶段判断车位是否被占
weights_path = 'car1.h5'
video_name = 'parking_video.mp4'
class_dictionary = {}
#模型预测返回结果,空车位/被占据车位
class_dictionary[0] = 'empty'
class_dictionary[1] = 'occupied'
#所用用到函数封装到parking的类当中
park = Parking()
park.show_images(test_images)
#处理图像,返回处理结果的字典
final_spot_dict = img_process(test_images, park)
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)
前几行是一些要用到的数据以及定义,test_images放了两张视频的截图用于训练。
接下来按代码顺序分析。
parking是在另一个py文件封装好的类,后面在用到该类的函数时,逐段分析学习。
2.show_images函数
def show_images(self, images, cmap=None):
cols = 2#每行展示两个图像
rows = (len(images) + 1) // cols#计算需要多少行展示图像,//是整除法确保结果整数
plt.figure(figsize=(15, 12))#创建新图形对象,宽15高12
for i, image in enumerate(images):
# 为每个图像创建子图,1行两列,i+1是当前图像子图编号
plt.subplot(rows, cols, i + 1)
# 如果是灰度图就将camp映射为gray,否则使用调用时提供的camp
cmap = 'gray' if len(image.shape) == 2 else cmap
plt.imshow(image, cmap=cmap)
plt.xticks([])#隐藏x轴y轴刻度
plt.yticks([])
# 自动调整子图参数,使之填充整个图像区域
plt.tight_layout(pad=0, h_pad=0, w_pad=0)#自动调整子图参数,使之填充整个图像区域
plt.show()
这个函数是用来在一个图形窗口中以网格形式展示多个图像的,可以处理彩色图像和灰度图像,并允许用户自定义颜色映射。如果图像是灰度的,它会自动应用灰度颜色映射。
执行后效果:
3.img_process函数
def img_process(test_images, park):
#使用 map 函数和 park 对象的 select_rgb_white_yellow 方法来选择图像中的白色和黄色部分,并将结果转换为列表
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(line_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
这段代码定义在主程序文件中,但是用到park类中的函数,主要执行图片预处理操作
3.1 select_rgb_white_yellow函数
def select_rgb_white_yellow(self, image):
#这些值被转换为无符号8位整数(np.uint8),用于指定颜色过滤的下限。
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 masked
我认为这段函数通俗来讲是保留图像中的浅色区域,具体来说,就是保留接近白色或黄色的区域。
执行后效果:
3.1.1cv_show
def cv_show(self, name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
一段简单的展示图片的函数
3.2 convert_gray_scale
def convert_gray_scale(self, image):
return cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
简单的彩色转灰度图像函数
执行后效果: