【精选】基于OpenCV的实时视频流车牌识别(源码&教程)

这篇具有很好参考价值的文章主要介绍了【精选】基于OpenCV的实时视频流车牌识别(源码&教程)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.研究背景

近年来,智能交通系统(ITS)在我国应用日益广泛。作为ITS重要组成部分的自动车牌识别系统在交通流量检测、交通诱导控制、违章车辆监控等方面有着广泛的应用,是确保道路安全畅通的重要手段,也为统计有关资料,为管理者决策提供有效数字依据的重要途径。由于一般的识别系统单幅图像的检测时间较长,达不到实时的要求,从而限制了这种系统在某些方面的应用,比如不停车监控、收费等。而且,即使在固定的地方使用,也必须埋设地感线圈等触发装置,施工及维护都有一定的困难。因此,发展基于视频图像的快速准确的车牌识别系统,具有广阔的发展前景和巨大的经济价值。

2.支持图片识别:

【精选】基于OpenCV的实时视频流车牌识别(源码&教程),opencv,人工智能,计算机视觉

3.支持视频识别:

【精选】基于OpenCV的实时视频流车牌识别(源码&教程),opencv,人工智能,计算机视觉

4.支持实时识别:

【精选】基于OpenCV的实时视频流车牌识别(源码&教程),opencv,人工智能,计算机视觉

5.视频演示:

Python基于OpenCV的视频车牌识别(源码&教程)上半篇_哔哩哔哩_bilibili
实时视频流车牌识别(源码)下半篇_哔哩哔哩_bilibili

6.实现原理:

入口文件 demo.py(部分):

import HyperLPRLite as pr
import cv2
import numpy as np
grr = cv2.imread("images_rec/2_.jpg")
model = pr.LPR("model/cascade.xml","model/model12.h5","model/ocr_plate_all_gru.h5")
for pstr,confidence,rect in model.SimpleRecognizePlateByE2E(grr):
        if confidence>0.7:
            image = drawRectBox(grr, rect, pstr+" "+str(round(confidence,3)))
            print "plate_str:"
            print pstr
            print "plate_confidence"
            print confidence

cv2.imshow("image",image)
cv2.waitKey(0)

(1) opencv2的imread函数导入图片, 返回的是Mat类型。

(2) HyperLPRLiite.py中的LPR类构造函数导入model, 参数就是训练好的三个模型文件,名字分别是:

  • model/cascade.xml
  • model/model12.h5
  • model/ocr_plate_all_gru.h5
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)

(3)参数 model_detection 就是文件 model/cascade.xml
用到了 opencv2的CascadeClassifier()函数
cv2.CascadeClassifier()
参数输入.xml或者.yaml文件,表示加载模型
一种基于Haar特征的级联分类器用于物体检测的模型

model.SImpleRecognizePlateByE2E()函数:
for pstr,confidence,rect in model.SimpleRecognizePlateByE2E(grr):
        if confidence>0.7:
            image = drawRectBox(grr, rect, pstr+" "+str(round(confidence,3)))
            print "plate_str:"
            print pstr
            print "plate_confidence"
            print confidence

输入为一个Mat类型的图片
输出为识别的车牌字符串,以及confidence可信度,
定义在 HyperLPRLite.py:

    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

其中又用到detectPlateRough()函数

下面有详细说明detectPlateRough函数(5)是返回图像中所有车牌的边框在图片中的bbox
返回的是一个表示车牌区域坐标边框的list

for循环中,对于每个识别出来的车牌用到filemappingVertical()函数

detectPlateRough函数
    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

输入参数:
image_gray: 一个rgb图像,Mat类型
resize_h: 重新设定的图像大小
top_bottom_padding_rate: 表示要裁剪掉图片的上下部占比

这个函数实现的处理:
1.resize图像大小,cv2.resize函数,按照原来图像比例
2.裁剪图片,根据输入的top_bottom_padding_rate如果是0.1,那么上面裁剪掉0.1height,下面也裁剪掉0.1height
3.将图像从rgb转化为灰度 cv2.cvtColor函数,cv2.COLOR_RGB2GRAY
4.根据前面的cv2.CascadeClassifier()物体检测模型(3),输入image_gray灰度图像,边框可识别的最小size,最大size,输出得到车牌在图像中的offset,也就是边框左上角坐标( x, y )以及边框高度( h )和宽度( w )
5.对得到的车牌边框的bbox进行扩大,也就是宽度左右各扩大0.14倍,高度上下各扩大0.15倍。
6.返回图片中所有识别出来的车牌边框bbox,这个list作为返回结果。

filemappingVertical函数
    def finemappingVertical(self,image,rect):
        resized = cv2.resize(image,(66,16))
        resized = resized.astype(np.float)/255
        res_raw= (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

输入参数:
裁剪的车牌区域图像(Mat类型),rect也是裁剪的车牌部分的图像(Mat类型)

实现处理:
1.将原来车牌图像resize大小:66163
2.将原来灰度图颜色通道[0, 255]转化为float类型[0,1]
3.将输入66*16(float),输入进模型进行测试self.modelFineMapping.predict

modelFineMapping模型
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)
model_finemapping()函数
    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

keras网络模型:对车牌的左右边界进行回归
通过modelFineMapping.loadweights()函数加载模型文件
通过modelFineMapping.predict输出网络结果

输入:16663 tensor
输出:长度为2的tensor

recognizeOne函数

对于每个车牌区域的for循环中,经过fineMappingVertical处理后输入到recognizeOne函数,进行识别

        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])
recognizeOne()
    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)

1.将前面的(136, 36)图像resize成(164, 48)
2.将图像转置,输入

model_sec_rec函数
    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

model_path为模型weights文件路径
ocr部分的网络模型(keras模型)
输入层:164483的tensor
输出层:长度为7 的tensor,类别有len(chars)+1种
chars:

chars = [u"京", u"沪", u"津", u"渝", u"冀", u"晋", u"蒙", u"辽", u"吉", u"黑", u"苏", u"浙", u"皖", u"闽", u"赣", u"鲁", u"豫", u"鄂", u"湘", u"粤", u"桂",
             u"琼", u"川", u"贵", u"云", u"藏", u"陕", u"甘", u"青", u"宁", u"新", u"0", u"1", u"2", u"3", u"4", u"5", u"6", u"7", u"8", u"9", u"A",
             u"B", u"C", u"D", u"E", u"F", u"G", u"H", u"J", u"K", u"L", u"M", u"N", u"P", u"Q", u"R", u"S", u"T", u"U", u"V", u"W", u"X",
             u"Y", u"Z",u"港",u"学",u"使",u"警",u"澳",u"挂",u"军",u"北",u"南",u"广",u"沈",u"兰",u"成",u"济",u"海",u"民",u"航",u"空"
             ]

网络结构是三层卷积神经网络(CNN),以及四层内控循环单元(GRU)组成

7.标注好的车牌数据集(文末链接提供下载):

【精选】基于OpenCV的实时视频流车牌识别(源码&教程),opencv,人工智能,计算机视觉

【精选】基于OpenCV的实时视频流车牌识别(源码&教程),opencv,人工智能,计算机视觉

8.系统整合:

下图源码&环境部署视频教程&数据集&自定义UI界面
【精选】基于OpenCV的实时视频流车牌识别(源码&教程),opencv,人工智能,计算机视觉
参考博客《Python基于OpenCV的实时视频流车牌识别(源码&教程)》文章来源地址https://www.toymoban.com/news/detail-819285.html

到了这里,关于【精选】基于OpenCV的实时视频流车牌识别(源码&教程)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 视频流识别---python

    在Python中实现预处理,需要用到一些常见的图像处理库,如OpenCV、PIL等。 首先,需要加载视频并读取视频帧。可以使用OpenCV库中的cv2.VideoCapture()函数读取视频,然后使用cv2.read()函数读取视频的每一帧。读取到的每一帧是一个numpy数组,可以对其进行各种图像处理操作。 以下

    2024年01月17日
    浏览(52)
  • 设计一个像ESPN一样的实时视频流系统

    功能需求 •直播事件与流之间的最大延迟不超过1分钟•系统应能够适应大量用户(异构交付)•系统应能将视频转换为不同的分辨率和编解码器•系统应具备容错性 视频转换和接收 由于我们正在实时直播整个事件,因此我们不能等待整个视频结束后再开始将其转换为不同的

    2024年02月07日
    浏览(36)
  • 安防监控项目---mjpeg-streamer视频图像显示(实时视频流实现)

    书接上期,我们已经实现了许多功能了,但是对于视频流的实时上传还未实现,本期主要分享的就是如何具体实现网页实时显示摄像头采集到的视频,从而实现安防中监控的功能,这个功能完成后呢,就只剩下一个功能需求了,那就是GPRS模块,能够实现危险报警的功能,也能

    2024年02月06日
    浏览(48)
  • FFmpeg+SDL实时解码和渲染H264视频流

    之前实现了Android手机摄像头数据的TCP实时传输,今天接着聊聊,如何在PC端把接收到的H264视频流实时解码并渲染出来。这次使用的语言是C++,框架有FFmpeg和SDL2。 解码部分使用FFmpeg,首先,需要初始化H264解码器: 然后,使用创建TCP连接到我们的Android端,读取数据包: 再把每

    2024年02月13日
    浏览(47)
  • Qt推流程序自动生成网页远程查看实时视频流(视频文件/视频流/摄像头/桌面转成流媒体rtmp+hls+webrtc)

    推流程序将视频流推送到流媒体服务器后,此时就等待验证拉流播放,一般可以选择ffplay命令行播放或者vlc等播放器打开播放,也可以选择网页直接打开拉流地址播放,一般主流的浏览器都支持网页直接播放hls/m3u8/webrtc类型的视频流,而且推流的主要目的可能就是为了能够在

    2024年02月05日
    浏览(80)
  • [chatGPT] 如何通过JNI在Android上显示实时视频流

    相机拍摄的画面通过local socket 获取,所以C++的代码可以轻易的获取到每一帧视频数据,需要通过JNI 让 Android显示出来,方法有两种,一种是在Android内创建回调函数使用Bitmap 和ImageView 进行赋值显示,另一种也就是ChatGPT完成的,Android将surface 传递到JNI层内,C++来完成赋值和渲

    2023年04月26日
    浏览(84)
  • QT实现OpenCV播放rtsp视频流

    使用OpenCV(图像处理)、FastDeploy(飞桨部署)库; 监控相机传输数据用的是码流,高清网络摄像机产品编码器都会产生两个编码格式,称为 主码流 和 子码流 。这就叫双码流技术。 目的是用于解决监控录像的本地存储和网络传输的图像的质量问题。双码流能实现本地和远程

    2024年02月03日
    浏览(69)
  • Opencv保存ESP32-CAM视频流

    Opencv保存ESP32-CAM视频流 esp32cam是一个很便宜的视频模组,可以用作监控等功能。此时就需要保存esp32的视频流,方便查看等操作,python代码如下 前置条件:视频流正常,已安装opencv

    2024年02月08日
    浏览(67)
  • VUE3 播放RTSP实时、回放(NVR录像机)视频流(使用WebRTC)

    1、下载webrtc-streamer,下载的最新window版本 Releases · mpromonet/webrtc-streamer · GitHub  2、解压下载包  3、webrtc-streamer.exe启动服务 (注意:这里可以通过当前文件夹下用cmd命令webrtc-streamer.exe -o这样占用cpu会很少,直接双击exe文件会占用cpu) cmd  webrtc-streamer.exe -o 启动如下图所示,

    2024年04月12日
    浏览(63)
  • opencv基本操作二(读取视频流与保存视频、读取摄像头并保存视频)

    opencv常用 读视频函数 cv2.VideoCapture 、 cv2.VideoCapture.get 等,可以参考这里 opencv常用 写视频函数 cv2.VideoWriter 等可以参考这里 ,其中视频格式可以参考这里 videoCapture.read() 是按帧读取视频, ret,frame 是获 .read() 方法的两个返回值。其中 ret 是布尔值,如果读取帧是正确的则返回

    2023年04月08日
    浏览(100)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包