作者:@阿利同学,邮箱:1309399183@qq.com

代码:点击获取代码


特征提取


此处面对的场景是是交通摄像头下的马路场景,数据格式为视频流或者视频,所以我们要提取视频的第一帧作为背景来进行车道线的标定,运行extra.py文件即可提取第一帧背景图片。
在这里插入图片描述


车道线和斑马线


在这里插入图片描述
根据第一步提取的场景背景图片,进行道路信息的标定,并返回道路信息的相关参数。
标定的方式是运行车道线标定文件即可。
先鼠标在背景图片上从左至右依次点击红色的两边的车道线实线,然后鼠标再依次在背景图片点击斑马线绿色框的从左至右四个顶点。这样就可以将斑马线和车道线的位置信息进行提取了,项目目录下会生成如上图标记好了的输出图片如上。


车牌识别


车牌号使用车牌号的识别是从车辆出现在画面的第一帧开始,一直到车辆消失在画面中。我们并不能事先确定在哪一帧对车牌的识别效果最好。因此,我们在车辆出现的第一帧,就将它的id和车牌信息传入字典chepaixinxi保存起来。如果当前帧比之前的识别效果都好(置信度高),我们就用它替换之前的车牌信息。另一方面,为了节省计算资源,只要是该车在某一帧的车牌置信度高于0.9,我们就不再将其传入车牌识别模块,运行LPR.py即可提取车牌信息,提取效果如下图所示
在这里插入图片描述


import cv2
import numpy as np
import math

“”” 输入图像归一化 “””


def stretch(img):
max = float(img.max())
min = float(img.min())

for i in range(img.shape[0]):
for j in range(img.shape[1]):
img[i, j] = (255 / (max - min)) _ img[i, j] - (255 _ min) / (max - min)

return img


def dobinaryzation(img):
max = float(img.max())
min = float(img.min())

x = max - ((max - min) / 2)
ret, thresholdimg = cv2.threshold(img, x, 255, cv2.THRESH_BINARY)

return thresholdimg


def find_retangle(contour):
y, x = [], []

for p in contour:
y.append(p[0][0])
x.append(p[0][1])

return [min(y), min(x), max(y), max(x)]


def locate_license(img, orgimg):
img, contours, hierachy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# 找到最大的三个区域
blocks = []
for c in contours:
# 找出轮廓的左上和右下点,计算出其面积和长宽比
r = find_retangle(c)
a = (r[2] - r[0]) _ (r[3] - r[1])
s = (r[2] - r[0]) / (r[3] - r[1])

blocks.append([r, a, s])

# 选出面积最大的3个区域
blocks = sorted(blocks, key=lambda b: b[2])[-3:]

# 使用颜色识别判断出最像车牌的区域
maxweight, maxinedx = 0, -1

for i in range(len(blocks)):
b = orgimg[blocks[i][0][1]:blocks[i][0][3], blocks[i][0][0]:blocks[i][0][2]]
# RGB 转HSV
hsv = cv2.cvtColor(b, cv2.COLOR_BGR2HSV)

# 蓝色车牌范围
lower = np.array([100, 50, 50])
upper = np.array([140, 255, 255])

# 根据阈值构建掩膜
mask = cv2.inRange(hsv, lower, upper)

# 统计权值
w1 = 0
for m in mask:
w1 += m / 255

w2 = 0
for w in w1:
w2 += w

# 选出最大权值的区域
if w2 > maxweight:
maxindex = i
maxweight = w2

return blocks[maxindex][0]


def find_license(img):
‘’’预处理’’’
# 压缩图像
a = 400 _ img.shape[0] / img.shape[1]
a = int(a)
img = cv2.resize(img, (400, a))
cv2.imshow(‘img’,img)
cv2.waitKey()

# RGB转灰色
grayimg = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow(‘grayimg’, grayimg)
cv2.waitKey()

# 灰度拉伸
stretchedimg = stretch(grayimg)
cv2.imshow(‘stretchedimg’, stretchedimg)
cv2.waitKey()

# 进行开运算,用来去除噪声
r = 16
h = w = r * 2 + 1
kernel = np.zeros((h, w), dtype=np.uint8)
cv2.circle(kernel, (r, r), r, 1, -1)
openingimg = cv2.morphologyEx(stretchedimg, cv2.MORPH_OPEN, kernel)
cv2.imshow(‘openingimg’, openingimg)
cv2.waitKey()

strtimg = cv2.absdiff(stretchedimg, openingimg)
cv2.imshow(‘strtimg’, strtimg)
cv2.waitKey()

# 图像二值化
binaryimg = dobinaryzation(strtimg)
cv2.imshow(‘binaryimg’, binaryimg)
cv2.waitKey()

# Canny算子进行边缘检测
cannyimg = cv2.Canny(binaryimg, binaryimg.shape[0], binaryimg.shape[1])
cv2.imshow(‘cannyimg’, cannyimg)
cv2.waitKey()

‘’’消除小区域,连通大区域’’’
# 进行闭运算
kernel = np.ones((5, 19), np.uint8)
closingimg = cv2.morphologyEx(cannyimg, cv2.MORPH_CLOSE, kernel)
cv2.imshow(‘closingimg’, closingimg)
cv2.waitKey()

# 进行开运算
openingimg = cv2.morphologyEx(closingimg, cv2.MORPH_OPEN, kernel)
cv2.imshow(‘openingimg’, openingimg)
cv2.waitKey()

# 再次进行开运算
kernel = np.ones((11, 5), np.uint8)
openingimg = cv2.morphologyEx(openingimg, cv2.MORPH_OPEN, kernel)
cv2.imshow(‘openingimg’, openingimg)
cv2.waitKey()

# 消除小区域,定位车牌位置
rect = locate_license(openingimg, img)
return rect, img


if __name__ == ‘__main__‘:
orgimg = cv2.imread(‘car3.jpg’)
rect, img = find_license(orgimg)

cv2.rectangle(img, (rect[0], rect[1]), (rect[2], rect[3]), (0, 255, 0), 2)
cv2.imshow(‘img’, img)
cv2.waitKey()
cv2.destroyAllWindows()




车辆越实线、不礼让行人检测


我们将车辆在上一帧的检测位置保存下来。如果车辆在上一帧的位置和在这一帧的位置分别位于车道线实线的两侧,或者落在了实线上,我们就判定车辆非法越实线了。行人在斑马线上时,车辆也在斑马线上 ==>车辆不礼让行人,运行效果图:
在这里插入图片描述


# 生成感兴趣区域即Mask掩模
def region_of_interest(image, vertices):

mask = np.zeros_like(image) # 生成图像大小一致的zeros矩

# 填充顶点vertices中间区域
if len(image.shape) > 2:
channel_count = image.shape[2]
ignore_mask_color = (255,) _ channel_count
else:
ignore_mask_color = 255

# 填充函数
cv.fillPoly(mask, vertices, ignore_mask_color)
masked_image = cv.bitwise_and(image, mask)
return masked_image

# 生成Mask掩模
vertices = np.array([[(0, imshape[0]), (9 _ imshape[1] / 20, 11 _ imshape[0] / 18),
(11 _ imshape[1] / 20, 11 * imshape[0] / 18), (imshape[1], imshape[0])]], dtype=np.int32)
masked_edges = region_of_interest(edge_image, vertices)


代码:点击获取代码