1.研究背景与意义
项目参考AAAI Association for the Advancement of Artificial Intelligence
研究背景与意义
近年来,随着人工智能技术的迅速发展,深度学习在图像识别和模式识别领域取得了显著的成果。在交通安全和人员安全方面,车牌识别、火灾检测和人员跌倒检测是非常重要的问题。传统的方法往往依赖于手工设计的特征和规则,但这些方法在复杂场景下往往表现不佳。因此,基于深度学习的车牌、火灾和人员跌倒检测系统成为了研究的热点。
首先,车牌识别系统在交通管理和安全监控中起着重要的作用。传统的车牌识别方法需要手动提取车牌的特征,但由于车牌的形状、颜色和光照条件的变化,这些方法往往难以适应不同场景下的车牌识别需求。基于深度学习的车牌识别系统可以通过训练大量的车牌图像来自动学习车牌的特征,从而提高车牌识别的准确性和鲁棒性。
其次,火灾检测是保障人们生命财产安全的重要任务。传统的火灾检测方法主要依赖于烟雾和温度传感器,但这些方法往往需要大量的硬件设备和人工干预。基于深度学习的火灾检测系统可以通过训练大量的火灾图像来学习火灾的特征,从而实现对火灾的自动检测和报警。这种系统不仅可以提高火灾检测的准确性,还可以减少对人力资源的依赖。
最后,人员跌倒检测在老年人护理和安防监控中具有重要意义。传统的人员跌倒检测方法主要依赖于压力传感器和摄像头,但这些方法往往需要大量的硬件设备和人工干预。基于深度学习的人员跌倒检测系统可以通过训练大量的跌倒图像来学习跌倒的特征,从而实现对人员跌倒的自动检测和报警。这种系统不仅可以提高人员跌倒检测的准确性,还可以及时发现跌倒事件并采取相应的救助措施。
综上所述,基于深度学习的车牌、火灾和人员跌倒检测系统具有重要的研究意义和应用价值。这些系统可以提高交通安全和人员安全的水平,减少事故和灾害的发生,保护人们的生命财产安全。此外,这些系统还可以减少对人力资源的依赖,提高监控和救援的效率。因此,深入研究和开发基于深度学习的车牌、火灾和人员跌倒检测系统对于推动人工智能技术在安全领域的应用具有重要意义。
2.图片演示
3.视频演示
基于深度学习的车牌&火灾&人员跌倒检测系统_哔哩哔哩_bilibili
4.车牌识别
1.车牌检测:第一步是从汽车上检测车牌所在位置。我们将使用OpenCV中矩形的轮廓检测来寻找车牌。如果我们知道车牌的确切尺寸,颜色和大致位置,则可以提高准确性。通常,也会将根据摄像机的位置和该特定国家/地区所使用的车牌类型来训练检测算法。但是图像可能并没有汽车的存在,在这种情况下我们将先进行汽车的,然后是车牌。
2.字符分割:检测到车牌后,我们必须将其裁剪并保存为新图像。同样,这可以使用OpenCV来完成。
3. 字符识别:现在,我们在上一步中获得的新图像肯定可以写上一些字符(数字/字母)。因此,我们可以对其执行OCR(光学字符识别)以检测数字。
车牌检测
让我们以汽车的样本图像为例,首先检测该汽车上的车牌。然后,我们还将使用相同的图像进行字符分割和字符识别。如果您想直接进入代码而无需解释,则可以向下滚动至此页面的底部,提供完整的代码,或访问以下链接。
第1步: 将图像调整为所需大小,然后将其灰度。相同的代码如下
img = cv2.resize(img, (620,480) )
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #convert to grey scale
调整大小后,可以避免使用较大分辨率的图像而出现的以下问题,但是我们要确保在调整大小后,车号牌仍保留在框架中。在处理图像时如果不再需要处理颜色细节,那么灰度变化就必不可少,这加快了其他后续处理的速度。完成此步骤后,图像将像这样被转换
步骤2:每张图片都会包含有用和无用的信息,在这种情况下,对于我们来说,只有牌照是有用的信息,其余的对于我们的程序几乎是无用的。这种无用的信息称为噪声。通常,使用双边滤波(模糊)会从图像中删除不需要的细节。
gray = cv2.bilateralFilter(gray, 13, 15, 15)
语法为 destination_image = cv2.bilateralFilter(source_image, diameter of pixel, sigmaColor, sigmaSpace)。我们也可以将sigma颜色和sigma空间从15增加到更高的值,以模糊掉更多的背景信息,但请注意不要使有用的部分模糊。输出图像如下所示可以看到该图像中的背景细节(树木和建筑物)模糊了。这样,我们可以避免程序处理这些区域。
步骤3:下一步是我们执行边缘检测的有趣步骤。有很多方法可以做到,最简单和流行的方法是使用OpenCV中的canny edge方法。执行相同操作的行如下所示
edged = cv2.Canny(gray, 30, 200) #Perform Edge detection
语法为destination_image = cv2.Canny(source_image,thresholdValue 1,thresholdValue 2)。阈值谷1和阈值2是最小和最大阈值。仅显示强度梯度大于最小阈值且小于最大阈值的边缘。结果图像如下所示
步骤4:现在我们可以开始在图像上寻找轮廓
contours=cv2.findContours(edged.copy(),cv2.RETR_TREE,
cv2.CHAIN_APPROX_SIMPLE)
contours = imutils.grab_contours(contours)
contours = sorted(contours,key=cv2.contourArea, reverse = True)[:10]
screenCnt = None
一旦检测到计数器,我们就将它们从大到小进行排序,并只考虑前10个结果而忽略其他结果。在我们的图像中,计数器可以是具有闭合表面的任何事物,但是在所有获得的结果中,牌照号码也将存在,因为它也是闭合表面。
为了过滤获得的结果中的车牌图像,我们将遍历所有结果,并检查其具有四个侧面和闭合图形的矩形轮廓。由于车牌肯定是四边形的矩形。
for c in cnts:
# approximate the contour
peri = cv2.arcLength(c, True)
approx = cv2.approxPolyDP(c, 0.018 * peri, True)
# if our approximated contour has four points, then
# we can assume that we have found our screen
if len(approx) == 4:
screenCnt = approx
break
找到正确的计数器后,我们将其保存在名为screenCnt的变量中,然后在其周围绘制一个矩形框,以确保我们已正确检测到车牌。
步骤5:现在我们知道车牌在哪里,剩下的信息对我们来说几乎没有用。因此,我们可以对整个图片进行遮罩,除了车牌所在的地方。相同的代码如下所示
# Masking the part other than the number plate
mask = np.zeros(gray.shape,np.uint8)
new_image = cv2.drawContours(mask,[screenCnt],0,255,-1,)
new_image = cv2.bitwise_and(img,img,mask=mask)
被遮罩的新图像将如下所示
字符分割
车牌识别的下一步是通过裁剪车牌并将其保存为新图像,将车牌从图像中分割出来。然后,我们可以使用此图像来检测其中的字符。下面显示了从主图像裁剪出ROI(感兴趣区域)图像的代码
# Now crop
(x, y) = np.where(mask == 255)
(topx, topy) = (np.min(x), np.min(y))
(bottomx, bottomy) = (np.max(x), np.max(y))
Cropped = gray[topx:bottomx+1, topy:bottomy+1]
结果图像如下所示。通常添加到裁剪图像中,如果需要,我们还可以对其进行灰色处理和边缘化。这样做是为了改善下一步的字符识别。但是我发现即使使用原始图像也可以正常工作。
5.核心代码讲解
5.1 dark.py
class ImageProcessor:
def __init__(self, folder):
self.folder = folder
def process_images(self):
img_files = [f for f in os.listdir(self.folder) if f.endswith('.jpg') or f.endswith('.png')]
for img_file in img_files:
img_path = os.path.join(self.folder, img_file)
img = Image.open(img_path)
img_05 = img.point(lambda x: x * 0.5)
img_05_path = os.path.join(self.folder, '05_' + img_file)
img_05.save(img_05_path)
img_2 = img.point(lambda x: x * 2)
img_2_path = os.path.join(self.folder, '2_' + img_file)
img_2.save(img_2_path)
......
上述代码将原来的逐文件处理的过程封装为一个名为ImageProcessor
的类,其中__init__
方法用于初始化文件夹路径,process_images
方法用于处理图片。可以通过创建ImageProcessor
对象并调用process_images
方法来处理图片。
这个程序文件名为dark.py,主要功能是对指定文件夹中的图片进行亮度调整,并保存调整后的图片。
程序首先导入了PIL库中的Image模块和os模块。
接下来,程序通过os模块的listdir函数获取指定文件夹(‘src’文件夹)中所有的图片文件名,并将这些文件名存储在img_files列表中。这里使用了列表推导式来筛选出以’.jpg’或’.png’结尾的文件。
然后,程序使用一个循环逐一处理每张图片。在循环中,首先通过os模块的join函数构建图片的完整路径,并使用Image模块的open函数打开图片。
接下来,程序通过使用Image模块的point方法和lambda函数来调整图片的亮度。具体地,通过lambda函数将每个像素的亮度值乘以0.5,得到亮度为0.5倍的图片img_05。然后,使用os模块的join函数构建调整后图片的保存路径,并使用Image模块的save方法保存图片。
类似地,程序还对原始图片进行了亮度为2倍的调整,并保存调整后的图片。
总结起来,这个程序的功能是对指定文件夹中的图片进行亮度调整,并保存调整后的图片。具体地,它将每张图片的亮度调整为0.5倍和2倍,并分别保存为新的文件。
5.2 demo.py
class CarNumberRecognition:
def __init__(self):
reload(sys)
self.fontC = ImageFont.truetype("./Font/platech.ttf", 14, 0)
self.model = pr.LPR("model/cascade.xml", "model/model12.h5", "model/ocr_plate_all_gru.h5")
def speed_test(self, image_path):
grr = cv2.imread(image_path)
self.model.SimpleRecognizePlateByE2E(grr)
t0 = time.time()
for x in range(20):
self.model.SimpleRecognizePlateByE2E(grr)
t = (time.time() - t0) / 20.0
print("Image size :" + str(grr.shape[1]) + "x" + str(grr.shape[0]) + " need " + str(round(t * 1000, 2)) + "ms")
def draw_rect_box(self, image, rect, add_text):
cv2.rectangle(image, (int(rect[0]), int(rect[1])), (int(rect[0] + rect[2]), int(rect[1] + rect[3])), (0, 0, 255), 2, cv2.LINE_AA)
cv2.rectangle(image, (int(rect[0] - 1), int(rect[1]) - 16), (int(rect[0] + 115), int(rect[1])), (0, 0, 255), -1, cv2.LINE_AA)
img = Image.fromarray(image)
draw = ImageDraw.Draw(img)
draw.text((int(rect[0] + 1), int(rect[1] - 16)), add_text, (255, 255, 255), font=self.fontC)
imagex = np.array(img)
return imagex
def carnum_rec(self, grr):
for pstr, confidence, rect in self.model.SimpleRecognizePlateByE2E(grr):
if confidence > 0.7:
image = self.draw_rect_box(grr, rect, pstr + " " + str(round(confidence, 3)))
print("plate_str:")
print(pstr)
print("plate_confidence")
print(confidence)
cv2.imshow("enhanced", image)
def video_capture(self):
capture = cv2.VideoCapture("src/carnum.avi")
i = 1
while (True):
ref, frame = capture.read()
if ref:
cv2.imshow("enhanced", frame)
i = i + 1
if i % 10 == 0:
i = 0
self.carnum_rec(frame)
c = cv2.waitKey(30) & 0xff
if c == 27:
capture.release()
break
else:
break
这个程序文件名为demo.py,主要功能是通过摄像头实时识别车牌号码。程序首先导入了一些必要的库,然后定义了一个SpeedTest函数,用于测试识别车牌号码的速度。接下来定义了一个drawRectBox函数,用于在图像上绘制车牌框和车牌号码。然后定义了一个carnum_rec函数,用于识别车牌号码并在图像上显示。最后定义了一个video_capture函数,用于从摄像头获取图像并进行车牌识别。最后,在主函数中调用了video_capture函数来实现实时车牌识别。
5.3 HyperLPRLite.py
class LPR():
def __init__(self,model_detection,model_finemapping,model_seq_rec):
self.watch_cascade = cv2.CascadeClassifier(model_detection)
self.modelFineMapping = self.model_finemapping()
self.modelFineMapping.load_weights(model_finemapping)
self.modelSeqRec = self.model_seq_rec(model_seq_rec)
def computeSafeRegion(self,shape,bounding_rect):
top = bounding_rect[1] # y
bottom = bounding_rect[1] + bounding_rect[3] # y + h
left = bounding_rect[0] # x
right = bounding_rect[0] + bounding_rect[2] # x + w
min_top = 0
max_bottom = shape[0]
min_left = 0
max_right = shape[1]
if top < min_top:
top = min_top
if left < min_left:
left = min_left
if bottom > max_bottom:
bottom = max_bottom
if right > max_right:
right = max_right
return [left,top,right-left,bottom-top]
def cropImage(self,image,rect):
x, y, w, h = self.computeSafeRegion(image.shape,rect)
return image[y:y+h,x:x+w]
def detectPlateRough(self,image_gray,resize_h = 720,en_scale =1.08 ,top_bottom_padding_rate = 0.05):
if top_bottom_padding_rate>0.2:
print("error:top_bottom_padding_rate > 0.2:",top_bottom_padding_rate)
exit(1)
height = image_gray.shape[0]
padding = int(height*top_bottom_padding_rate)
scale = image_gray.shape[1]/float(image_gray.shape[0])
image = cv2.resize(image_gray, (int(scale*resize_h), resize_h))
image_color_cropped = image[padding:resize_h-padding,0:image_gray.shape[1]]
image_gray = cv2.cvtColor(image_color_cropped,cv2.COLOR_RGB2GRAY)
watches = self.watch_cascade.detectMultiScale(image_gray, en_scale, 2, minSize=(36, 9),maxSize=(36*40, 9*40))
cropped_images = []
for (x, y, w, h) in watches:
x -= w * 0.14
w += w * 0.28
y -= h * 0.15
h += h * 0.3
cropped = self.cropImage(image_color_cropped, (int(x), int(y), int(w), int(h)))
cropped_images.append([cropped,[x, y+padding, w, h]])
return cropped_images
def fastdecode(self,y_pred):
results = ""
confidence = 0.0
table_pred = y_pred.reshape(-1, len(chars)+1)
res = table_pred.argmax(axis=1)
for i,one in enumerate(res):
if one<len(chars) and (i==0 or (one!=res[i-1])):
results+= chars[one]
confidence+=table_pred[i][one]
confidence/= len(results)
return results,confidence
def model_seq_rec(self,model_path):
width, height, n_len, n_class = 164, 48, 7, len(chars)+ 1
rnn_size = 256
input_tensor = Input((164, 48, 3))
x = input_tensor
base_conv = 32
for i in range(3):
x = Conv2D(base_conv * (2 ** (i)), (3, 3))(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
conv_shape = x.get_shape()
x = Reshape(target_shape=(int(conv_shape[1]), int(conv_shape[2] * conv_shape[3])))(x)
x = Dense(32)(x)
x = BatchNormalization()(x)
x = Activation('relu')(x)
gru_1 = GRU(rnn_size, return_sequences=True, kernel_initializer='he_normal', name='gru1')(x)
gru_1b = GRU(rnn_size, return_sequences=True, go_backwards=True, kernel_initializer='he_normal', name='gru1_b')(x)
gru1_merged = add([gru_1, gru_1b])
gru_2 = GRU(rnn_size, return_sequences=True, kernel_initializer='he_normal', name='gru2')(gru1_merged)
gru_2b = GRU(rnn_size, return_sequences=True, go_backwards=True, kernel_initializer='he_normal', name='gru2_b')(gru1_merged)
x = concatenate([gru_2, gru_2b])
x = Dropout(0.25)(x)
x = Dense(n_class, kernel_initializer='he_normal', activation='softmax')(x)
base_model = Model(inputs=input_tensor, outputs=x)
base_model.load_weights(model_path)
return base_model
def model_finemapping(self):
input = Input(shape=[16, 66, 3]) # change this shape to [None,None,3] to enable arbitraty shape input
x = Conv2D(10, (3, 3), strides=1, padding='valid', name='conv1')(input)
x = Activation("relu", name='relu1')(x)
x = MaxPool2D(pool_size=2)(x)
x = Conv2D(16, (3, 3), strides=1, padding='valid', name='conv2')(x)
x = Activation("relu", name='relu2')(x)
x = Conv2D(32, (3, 3), strides=1, padding='valid', name='conv3')(x)
x = Activation("relu", name='relu3')(x)
x = Flatten()(x)
output = Dense(2,name = "dense")(x)
output = Activation("relu", name='relu4')(output)
model = Model([input], [output])
return model
def finemappingVertical(self,image,rect):
resized = cv2.resize(image,(66,16))
resized = resized.astype(np.float)/255
res_raw= self.modelFineMapping.predict(np.array([resized]))[0]
res =res_raw*image.shape[1]
res = res.astype(np.int)
H,T = res
H-=3
if H<0:
H=0
T+=2;
if T>= image.shape[1]-1:
T= image.shape[1]-1
rect[2] -= rect[2]*(1-res_raw[1] + res_raw[0])
rect[0]+=res[0]
image = image[:,H:T+2]
image = cv2.resize(image, (int(136), int(36)))
return image,rect
def recognizeOne(self,src):
x_tempx = src
x_temp = cv2.resize(x_tempx,( 164,48))
x_temp = x_temp.transpose(1, 0, 2)
y_pred = self.modelSeqRec.predict(np.array([x_temp]))
y_pred = y_pred[:,2:,:]
return self.fastdecode(y_pred)
def SimpleRecognizePlateByE2E(self,image):
images = self.detectPlateRough(image,image.shape[0],top_bottom_padding_rate=0.1)
res_set = []
for j,plate in enumerate(images):
plate, rect = plate
image_rgb,rect_refine = self.finemappingVertical(plate,rect)
res,confidence = self.recognizeOne(image_rgb)
res_set.append([res,confidence,rect_refine])
return res_set
这个程序文件是一个车牌识别系统的代码。它包含了一个LPR类,其中包括了车牌检测、车牌粗定位、车牌精定位、字符识别等功能。
程序首先导入了需要的库,包括cv2、numpy和keras。然后定义了一个字符列表,包含了车牌上可能出现的字符。
接下来是LPR类的定义,它有三个参数:model_detection、model_finemapping和model_seq_rec,分别表示车牌检测模型、车牌精定位模型和字符识别模型。在初始化函数中,加载了这三个模型。
LPR类中定义了一系列函数,包括computeSafeRegion、cropImage、detectPlateRough、fastdecode、model_seq_rec、model_finemapping、finemappingVertical和recognizeOne。
detectPlateRough函数用于粗定位车牌,它首先将输入的灰度图像进行预处理,然后使用级联分类器检测车牌位置,最后返回检测到的车牌图像和位置信息。
fastdecode函数用于将字符识别模型的输出转换为车牌号码和置信度。
model_seq_rec函数定义了字符识别模型的结构,并加载了预训练的权重。
model_finemapping函数定义了车牌精定位模型的结构。
finemappingVertical函数用于垂直方向的精定位,它将车牌图像缩放到固定大小,并使用车牌精定位模型对车牌进行精确定位。
recognizeOne函数用于对单个车牌图像进行字符识别。
SimpleRecognizePlateByE2E函数是整个车牌识别系统的入口函数,它调用了其他函数来完成车牌的检测、定位和字符识别,并返回识别结果和置信度。
总的来说,这个程序文件实现了一个简单的车牌识别系统,可以对输入的图像进行车牌检测和字符识别。
5.4 hyper_test.py
class CarNumberRecognition:
def __init__(self, video_path):
self.video_path = video_path
def process_frame(self, frame):
result = HyperLPR_plate_recognition(frame)
for i in result:
p1, p2 = (i[2][0], i[2][1]), (i[2][2], i[2][3])
cv2.rectangle(frame, p1, p2, [0, 0, 255], thickness=3, lineType=cv2.LINE_AA)
cv2.putText(frame, str(i[0]), (i[2][0], i[2][1] - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 0, 255), 2)
cv2.imshow('result', frame)
cv2.waitKey(1)
def process_video(self):
capture = cv.VideoCapture(self.video_path)
j = 1
while True:
ref, frame = capture.read()
if ref:
j = j + 1
if j % 5 == 0:
j = 0
self.process_frame(frame)
c = cv.waitKey(5) & 0xff
if c == 27:
capture.release()
break
else:
break
def process_image(self, image_path):
image = cv.imread(image_path)
result = HyperLPR_plate_recognition(image)
print(result)
这个程序文件名为hyper_test.py,主要功能是使用HyperLPR库对视频中的车牌进行识别。程序首先导入了需要的包,包括hyperlpr和OpenCV库。然后定义了两个函数,video_demo()和carnum_rec()。
video_demo()函数使用cv.VideoCapture()打开一个视频文件,然后进入一个循环,不断读取视频的帧。在每一帧中,程序使用HyperLPR_plate_recognition()函数对帧中的车牌进行识别,并将识别结果打印出来。然后,程序使用cv2.rectangle()和cv2.putText()函数在帧中标记出识别到的车牌,并显示出来。最后,程序等待30ms显示图像,如果期间按下"Esc"键,则退出循环。
carnum_rec()函数读入一张图片,然后使用HyperLPR_plate_recognition()函数对图片中的车牌进行识别,并将识别结果打印出来。
在主程序中,首先调用video_demo()函数进行视频中车牌的识别,然后调用cv.destroyAllWindows()关闭所有显示的窗口。
5.5 ui.py
class LicensePlateDetector:
def __init__(self, model_path):
self.model_path = model_path
self.model = None
self.stride = None
self.names = None
self.pt = None
self.jit = None
self.onnx = None
self.engine = None
def load_model(self):
FILE = Path(__file__).resolve()
ROOT = FILE.parents[0] # YOLOv5 root directory
if str(ROOT) not in sys.path:
sys.path.append(str(ROOT)) # add ROOT to PATH
ROOT = Path(os.path.relpath(ROOT, Path.cwd())) # relative
from models.common import DetectMultiBackend
from utils.augmentations import letterbox
from utils.general import (LOGGER, check_file, check_img_size, check_imshow, check_requirements, colorstr,
increment_path, non_max_suppression, print_args, scale_coords, strip_optimizer, xyxy2xywh)
from utils.torch_utils import select_device, time_sync
device = select_device('')
model = DetectMultiBackend(self.model_path, device=device)
stride, names, pt, jit, onnx, engine = model.stride, model.names, model.pt, model.jit, model.onnx, model.engine
self.model = model
self.stride = stride
self.names = names
self.pt = pt
self.jit = jit
self.onnx = onnx
self.engine = engine
def detect_license_plate(self, image):
result = HyperLPR_plate_recognition(image)
return result
def draw_box_string(self, img, box, string):
x,y,x1,y1 = box
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
img = Image.fromarray(img)
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("simhei.ttf", 60, encoding="utf-8")
draw.text((x, y), string, (0, 255, 0), font=font)
img = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
return img
这个程序文件名为ui.py,主要功能是使用PyQt5创建一个用户界面,并通过调用其他库实现车牌识别和目标检测的功能。
程序首先导入了一些必要的库,包括os、sys、pathlib、cv2、numpy、PyQt5等。然后定义了一些函数,包括load_model、run、draw_box_string等。load_model函数用于加载模型,run函数用于运行目标检测模型并返回检测结果,draw_box_string函数用于在图像上绘制框和文字。
程序还定义了一个det函数,用于实时检测摄像头的图像,并在图像上绘制检测结果。最后,程序定义了一个detimg函数,用于检测指定图像文件的图像,并在图像上绘制检测结果。
整个程序的核心功能是使用目标检测模型和车牌识别模型对图像进行检测和识别,并在图像上绘制检测结果。
6.系统整体结构
整体功能和构架概述:
该项目是一个基于深度学习的车牌识别和目标检测系统。它包含了多个程序文件,其中dark.py用于调整图片亮度,demo.py实现了通过摄像头实时识别车牌号码,HyperLPRLite.py是一个车牌识别系统的代码,hyper_test.py用于对视频中的车牌进行识别,test.py用于对单张图片进行车牌识别,ui.py使用PyQt5创建了一个用户界面,models文件夹包含了一些模型相关的代码,utils文件夹包含了一些工具函数和辅助功能的代码。
下面是每个文件的功能整理:
文件路径 | 功能 |
---|---|
dark.py | 调整图片亮度 |
demo.py | 通过摄像头实时识别车牌号码 |
HyperLPRLite.py | 车牌识别系统的代码 |
hyper_test.py | 对视频中的车牌进行识别 |
test.py | 对单张图片进行车牌识别 |
ui.py | 使用PyQt5创建用户界面 |
models\common.py | 包含一些通用的模型函数和类 |
models\experimental.py | 包含一些实验性的模型函数和类 |
models\tf.py | 包含一些TensorFlow模型函数和类 |
models\yolo.py | 包含YOLO模型函数和类 |
models_init_.py | 模型文件夹的初始化文件 |
utils\activations.py | 包含一些激活函数 |
utils\augmentations.py | 包含一些数据增强函数 |
utils\autoanchor.py | 包含自动锚框生成函数 |
utils\autobatch.py | 包含自动批处理函数 |
utils\callbacks.py | 包含一些回调函数 |
utils\datasets.py | 包含一些数据集处理函数 |
utils\downloads.py | 包含一些下载函数 |
utils\general.py | 包含一些通用的辅助函数 |
utils\loss.py | 包含一些损失函数 |
utils\metrics.py | 包含一些评估指标函数 |
utils\plots.py | 包含一些绘图函数 |
utils\torch_utils.py | 包含一些PyTorch相关的辅助函数 |
utils_init_.py | 工具文件夹的初始化文件 |
utils\aws\resume.py | 包含AWS相关的恢复函数 |
utils\aws_init_.py | AWS文件夹的初始化文件 |
utils\flask_rest_api\example_request.py | 包含示例请求函数 |
utils\flask_rest_api\restapi.py | 包含REST API函数 |
utils\loggers_init_.py | 日志记录器文件夹的初始化文件 |
utils\loggers\wandb\log_dataset.py | 包含WandB日志记录器的数据集日志函数 |
utils\loggers\wandb\sweep.py | 包含WandB日志记录器的超参数搜索函数 |
utils\loggers\wandb\wandb_utils.py | 包含WandB日志记录器的辅助函数 |
utils\loggers\wandb_init_.py | WandB日志记录器文件夹的初始化文件 |
以上是对每个文件的功能进行了简要的整理和概述。
7.基于改进 YOLO v5 的烟火检测
Mosaic数据增强
一个高效、精确的神经网络,通常需要进行大量的数据支撑训练。然而,获取新的数据往往是费时或费力的,所以增加数据量的有效方法是采用数据增强方式。例如,缩放、平移、旋转、翻转和变换色彩是广泛使用和相对常见的数据增强的方法。这将增加用于训练的样本数量,产生一个普适性更强的模型。
YOLOv5数据增强算法分为图像增强和 Mosaic数据增强。采用图像增强能使算法从同一目标的不同形状、不同尺寸提取出该目标的相关信息,以减少算法过拟合。Mosaic数据增强通过对图像数据进行随机缩放、随机裁剪和随机排列,使四张图像合成为一张图像,实现丰富数据集目标的同时,增加了小目标样本,提升网络训练速度。为了减少各张图片亮度不均的影响,在图像增强模块中对直方图进行平滑处理。在进行归一化操作时,一次性将四张图片同时输入进行归一化操作。
本文采用的 Mosaic9数据增强模块,是 Mosaic数据增强的增强版,多达九幅图像可以被随机缩放、随机裁剪和随机排列,使九张图像合并成一个图像。Mosaic9数据增强使得增强后的图片能够拥有9张图片的信息,相当于变相的提高了单次训练批次的数量。同时,Mosaic9数据增强相对于Mosaic数据增强在小目标检测效果上有一定的提高。Mosaic9数据增强流程如下图4-1所示,数据集中随机取出一个批次的图像数据,在该批次图像数据中随机取出9张图片,图片经过随机缩放、裁剪、排列组合后拼接成为一张图片,拼接完成后对同一批次中的剩余图片进行相同处理直至批次中图像数据均被遍历,被处理后的图片将被用于输入神经网络。在 Mosaic9数据增强的拼接处理细节如图4-2所示。图所示经Mosaic9数据增强后的图片示例。
性能测试
为了进一步验证改进算法的目标检测效果,分别使用为 YOLO v5算法的权重yolov5s.pt进行训练后得到的最佳权重文件与改进YOLO v5算法训练得到的最佳权重文件对不同尺寸类型目标进行目标检测测试,结果如图,图左为原YOLO v5目标检测算法检测效果,图右为改进YOLO v5目标检测算法检测效果,图中检测框所标识区域为目标检测算法所预测火焰目标区域,预测框左上角数字标识为该区域预测为火焰区域的概率值大小。从图(a)中可以看出,在对于中、大型火焰目标检测时,改进后的YOLO v5算法检测对于同样的火焰区域预测概率相较于原YOLO v5算法有一定程度的提升。还是对于小型目标,改进后的 YOLO v5算法检测效果相较于原算法均有一定程度的提高。从图 (b)中可以看出,在对于小目标区域火焰检测时,改进后的 YOLO v5算法在某些区域也存在检测预测概率不如原 YOLO v5算法的情况,但从总体上来说,并未出现误检的情况,且多个目标整体检测精度要优于原 YOLO v5算法检测精度。
改进YOLO v5模型的Precision、Recall 及mAP值如图所示。从图中可以看出改进YOLO v5模型在经过200次迭代后基本趋于最优,准确率 Precision最终趋于0.8左右,召回率 Recall很快趋近于1,表明图像数据中的火焰区域基本能够被预测到。mAP@0.5表示在IoU取0.5时的mAP值,mAP@0.5:0.95表示在ToU在范围为(0.5:0.95:0.05)时的mAP值,图中显示mAP@0.5趋近于1,mAP@0.5:0.95在0.7左右。若是以IoU取0.5作为判别标准,按表数据可得检测准确率为97.2%,林火目标检测准确率达到设计指标。
8.改进 YOLOv5 的人员跌倒检测算法
YOLOv5算法与之前的YOLO算法相比改进之处就是增加了自适应锚框、特征切片,YOLOv5算法的这些改进提高了目标检测的速度。使模型变得更加灵活,收敛速度也变得更快。YOLOv5网络结构包括YOLOv5s、YOLOv5m、YOLOv51和YOLOv5x。它们的网络深度和宽度依次加深,检测精度也逐步提高,但是模型的训练速度和复杂度也逐渐增加。为了使YOLOv5网络模型在保持参数较少、模型复杂度较低的情况下仍然保持较高的准确率,本节对YOLOv5s的网络结构进行改进。下面以YOLOv5s网络模型为例,对其网络结构进行分析并改进。
如图所示,YOLOv5s 算法将输入大小为604×604的图片划分为19×19个单元格,当目标的中心坐标落在某个单元格内时,那么这个单元格就用来检测目标,每个需要预测3×3个边界框,边界框坐标值预测还是与之前的YOLO算法做法一致。
Aphapose算法关键点补全
Alphapose 算法是一种自上而下的姿态估计算法。本节首先对Alphapose算法进行了介绍,然后对Alphapose算法中关键点缺失的情况进行关键点补齐。最后进行了关键点补齐实验。
Alphapose算法流程
Alphapose算法总体网络结图所示。首先通过人体目标检测网络得到人体的目标框,然后送入空间变换网络(Spatial transformation network,STN),进行2D仿射变换,对于不准确的输入,得到准确的人体边框,可以获取高质量的候选区域。接着利用单人姿态估计网络(Single person pose estimate,SPPE)得到估计的姿态,为了将人体姿态显示在图像中,需要再经过空间逆变换网络(Spatialde-transformer network,SDTN)将估计的姿态映射回原始的图像坐标。最后,对于同一个目标,会产生多个估计的姿态,为了消除多余的姿态,进行姿态非极大值抑制((Pose-Non-maximum suppression,P-NMS),即可得到人体的关键点特征。
9.系统整合
10.参考文献
[1]姜禹,陈思卿,孙雯.基于射频指纹的LoRa网络安全方案研究[J].物联网学报.2021,5(4).DOI:10.11959/j.issn.2096−3750.2021.00228 .
[2]李倩,岳亮.吸气式感烟火灾探测器设计改进研究[J].消防科学与技术.2021,40(11).DOI:10.3969/j.issn.1009-0029.2021.11.018 .
[3]陈鸿坤,罗会兰.多尺度语义信息融合的目标检测[J].电子与信息学报.2021,(7).DOI:10.11999/JEIT200147 .
[4]郭开诚,吴承刚,张伟丰,等.面向细粒度FPGA管理的CNN异构加速框架[J].计算机学报.2021,44(12).DOI:10.11897/SP.J.1016.2021.02529 .
[5]张萌,张经纬,李国庆,等.面向深度神经网络加速芯片的高效硬件优化策略[J].电子与信息学报.2021,(6).DOI:10.11999/JEIT210002 .
[6]戴源,白雨鑫,张伟,等.基于Vivado HLS的硬件设计效能评估[J].电脑知识与技术.2021,(19).
[7]卞永明,高飞,李梦如,等.结合Kmeans++聚类和颜色几何特征的火焰检测方法[J].中国工程机械学报.2020,(1).
[8]高黎锋.火灾事故调查视频资料的取证与审查[J].消防科学与技术.2020,(11).
[9]林景栋,吴欣怡,柴毅,等.卷积神经网络结构优化综述[J].自动化学报.2020,(1).DOI:10.16383/j.aas.c180275 .
[10]于晓明,李思颖,史胜楠.混合高斯融合三帧差的运动目标检测改进算法[J].红外技术.2019,(3).