完整项目已上传至github: https://github.com/duanshengliu/End-to-end-for-chinese-plate-recognition

喜欢的话顺手点个star,谢谢支持


整体思路:1.利用u-net图像分割得到二值化图像,2.再使用cv2进行边缘检测获得车牌区域坐标,并将车牌图形矫正,3.利用卷积神经网络cnn进行车牌多标签端到端识别

实现效果:拍摄角度倾斜、强曝光或昏暗环境等都能较好地识别,甚至有些百度AI车牌识别未能识别的图片也能识别

环境:python:3.6, tensorflow:1.15.2, opencv: 4.1.0.25

1.车牌定位

首先贴一下图像分割的效果图:

我们可以通过图像分割算法对一张输入图片进行分割,分割后的图形其实是对原图中的区域进行的分类标注,例如这里我们可以将原图标注为2类,一类就是车牌区域,还有一类就是无关的背景区域。说到标注图形就不得不说labelme了,我们可以在cmd界面通过命令 pip install labelme 进行labelme库的安装,安装结束在cmd界面输入labelme即可打开lablem软件的标注界面如下:

1. 点击OpenDir ,选择我们准备好的车辆数据集(注意:一定要先把图片全都resize为训练时所需的大小,再进行标注。我们知道图片数据的范围是0-255,背景为黑色0,车牌区域为255,我们需要的是标注好的图片即img_mask中值只有{0,255}这2种,如果我们不先resize,标注完再resize会导致一个大问题,就是数据的值并不是二类,会出现{0,1,10,248,251,255}等类似的多值问题,我在之前就遇到这样的问题,不得已又重新标注了300多张图)

2. 点击左上角File—>将Save Automatically勾选上,点击Change Output Dir选择保存路径,我这里是在桌面D:/desktop/下新建了一个文件夹命名为labelme,在labelm文件夹中新建了一个json文件夹用于保存我们标注的json数据,这里我们Change Output Dir的保存路径就选它,还新建了一个data文件夹用于存放后续转换的图片数据,而待标注图片在pic文件中,存放的都是resize好的512×512的图片,命名格式最好像我这样

3. 准备好上述一切就可以开始标注了,点击软件左侧的   这是画任意多边形的按钮,鼠标左键点击进行标注,最后双击鼠标左键会锁定标注区域,出现如下图界面,第一次标注需输入名称,后续标注就自动显示了,点击ok后标注的线条变为红色,同时json文件夹也会相应保存和pic名字对应的json文件:

4. 全部标注结束后,使用如下代码将json数据提取出来并保存到train_image和train_label文件夹中,u-net部分的数据集我一共标注了1200多张,最终效果很棒,达到了定位的效果

  1. import os
  2. import cv2
  3. import numpy as np
  4. #将json文件label转换为到data文件夹
  5. n=1200#n为总共标注的图片数
  6. for i in range(n):
  7. os.system('labelme_json_to_dataset D:/desktop/labelme/json/%d.json -o D:/desktop/labelme/data/%d_json'%(i,i))
  8. #dst_w=512
  9. #dst_h=512
  10. #dst_shape=(dst_w,dst_h,3)
  11. train_image = 'D:/desktop/labelme/train_image/'
  12. if not os.path.exists(train_image):
  13. os.makedirs(train_image)
  14. train_label = 'D:/desktop/labelme/train_label/'
  15. if not os.path.exists(train_label):
  16. os.makedirs(train_label)
  17. for i in range(n):
  18. print(i)
  19. img=cv2.imread('D:/desktop/labelme/data/%d_json/img.png'%i)
  20. label=cv2.imread('D:/desktop/labelme/data/%d_json/label.png'%i)
  21. print(img.shape)
  22. label=label/np.max(label[:,:,2])*255
  23. label[:,:,0]=label[:,:,1]=label[:,:,2]
  24. print(np.max(label[:,:,2]))
  25. # cv2.imshow('l',label)
  26. # cv2.waitKey(0)
  27. print(set(label.ravel()))
  28. cv2.imwrite(train_image+'%d.png'%i,img)
  29. cv2.imwrite(train_label+'%d.png'%i,label)

这样一来,标注好的u-net训练图片就准备好了,分别在train_image和train_label文件夹中,一并放在unet_datasets文件夹内,如下图所示:

接下来是u-net模型搭建和训练,使用tensorflow的keras实现,贴一下我训练u-net用的代码:

  1. def unet_train():
  2. height = 512
  3. width = 512
  4. path = 'D:/desktop/unet_datasets/'
  5. input_name = os.listdir(path + 'train_image')
  6. n = len(input_name)
  7. print(n)
  8. X_train, y_train = [], []
  9. for i in range(n):
  10. print("正在读取第%d张图片" % i)
  11. img = cv2.imread(path + 'train_image/%d.png' % i)
  12. label = cv2.imread(path + 'train_label/%d.png' % i)
  13. X_train.append(img)
  14. y_train.append(label)
  15. X_train = np.array(X_train)
  16. y_train = np.array(y_train)
  17. def Conv2d_BN(x, nb_filter, kernel_size, strides=(1, 1), padding='same'):
  18. x = layers.Conv2D(nb_filter, kernel_size, strides=strides, padding=padding)(x)
  19. x = layers.BatchNormalization(axis=3)(x)
  20. x = layers.LeakyReLU(alpha=0.1)(x)
  21. return x
  22. def Conv2dT_BN(x, filters, kernel_size, strides=(2, 2), padding='same'):
  23. x = layers.Conv2DTranspose(filters, kernel_size, strides=strides, padding=padding)(x)
  24. x = layers.BatchNormalization(axis=3)(x)
  25. x = layers.LeakyReLU(alpha=0.1)(x)
  26. return x
  27. inpt = layers.Input(shape=(height, width, 3))
  28. conv1 = Conv2d_BN(inpt, 8, (3, 3))
  29. conv1 = Conv2d_BN(conv1, 8, (3, 3))
  30. pool1 = layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same')(conv1)
  31. conv2 = Conv2d_BN(pool1, 16, (3, 3))
  32. conv2 = Conv2d_BN(conv2, 16, (3, 3))
  33. pool2 = layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same')(conv2)
  34. conv3 = Conv2d_BN(pool2, 32, (3, 3))
  35. conv3 = Conv2d_BN(conv3, 32, (3, 3))
  36. pool3 = layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same')(conv3)
  37. conv4 = Conv2d_BN(pool3, 64, (3, 3))
  38. conv4 = Conv2d_BN(conv4, 64, (3, 3))
  39. pool4 = layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2), padding='same')(conv4)
  40. conv5 = Conv2d_BN(pool4, 128, (3, 3))
  41. conv5 = layers.Dropout(0.5)(conv5)
  42. conv5 = Conv2d_BN(conv5, 128, (3, 3))
  43. conv5 = layers.Dropout(0.5)(conv5)
  44. convt1 = Conv2dT_BN(conv5, 64, (3, 3))
  45. concat1 = layers.concatenate([conv4, convt1], axis=3)
  46. concat1 = layers.Dropout(0.5)(concat1)
  47. conv6 = Conv2d_BN(concat1, 64, (3, 3))
  48. conv6 = Conv2d_BN(conv6, 64, (3, 3))
  49. convt2 = Conv2dT_BN(conv6, 32, (3, 3))
  50. concat2 = layers.concatenate([conv3, convt2], axis=3)
  51. concat2 = layers.Dropout(0.5)(concat2)
  52. conv7 = Conv2d_BN(concat2, 32, (3, 3))
  53. conv7 = Conv2d_BN(conv7, 32, (3, 3))
  54. convt3 = Conv2dT_BN(conv7, 16, (3, 3))
  55. concat3 = layers.concatenate([conv2, convt3], axis=3)
  56. concat3 = layers.Dropout(0.5)(concat3)
  57. conv8 = Conv2d_BN(concat3, 16, (3, 3))
  58. conv8 = Conv2d_BN(conv8, 16, (3, 3))
  59. convt4 = Conv2dT_BN(conv8, 8, (3, 3))
  60. concat4 = layers.concatenate([conv1, convt4], axis=3)
  61. concat4 = layers.Dropout(0.5)(concat4)
  62. conv9 = Conv2d_BN(concat4, 8, (3, 3))
  63. conv9 = Conv2d_BN(conv9, 8, (3, 3))
  64. conv9 = layers.Dropout(0.5)(conv9)
  65. outpt = layers.Conv2D(filters=3, kernel_size=(1, 1), strides=(1, 1), padding='same', activation='relu')(conv9)
  66. model = models.Model(inpt, outpt)
  67. model.compile(optimizer='adam',
  68. loss='mean_squared_error',
  69. metrics=['accuracy'])
  70. model.summary()
  71. print(np.max(X_train))
  72. print(np.max(y_train))
  73. print(X_train.shape)
  74. model.fit(X_train, y_train, epochs=100, batch_size=15)#epochs和batch_size看个人情况调整,batch_size不要过大,否则内存容易溢出
  75. #我11G显存也只能设置15-20左右,我训练最终loss降低至250左右,acc约95%左右
  76. model.save('unet.h5')
  77. print('unet.h5保存成功!!!')

2.车牌矫正

接着训练u-net得到unet.h5。我们可以先利用百度API进行车牌标注,那部分可以见我上一篇博客:https://blog.csdn.net/qq_32194791/article/details/106526217,那里讲述了如何高效的将整张图片标注好,标注好再利用u-net进行图像分割就可以轻松高效地获得标注好的车牌图片了,贴一下u-net分割和cv2矫正的代码

  1. import os
  2. import cv2
  3. import numpy as np
  4. from tensorflow import keras
  5. def unet_predict(unet,img_src_path):
  6. img_src= cv2.imdecode(np.fromfile(img_src_path, dtype=np.uint8), -1)#从中文路径读取时用
  7. # img_src=cv2.imread(img_src_path)
  8. if img_src.shape!=(512,512,3):
  9. img_src=cv2.resize(img_src,dsize=(512,512))[:,:,:3]#dsize=(宽度,高度),[:,:,:3]是防止图片为4通道图片,后续无法reshape
  10. img_src=img_src.reshape(1,512,512,3)#预测图片shape为(1,512,512,3)
  11. img_mask=unet.predict(img_src)#归一化除以255后进行预测
  12. img_src=img_src.reshape(512,512,3)#将原图reshape为3维
  13. img_mask=img_mask.reshape(512,512,3)#将预测后图片reshape为3维
  14. img_mask=img_mask/np.max(img_mask)*255#归一化后乘以255
  15. img_mask[:,:,2]=img_mask[:,:,1]=img_mask[:,:,0]#三个通道保持相同
  16. img_mask=img_mask.astype(np.uint8)#将img_mask类型转为int型
  17. return img_src,img_mask
  18. def locate(img_src,img_mask,name):
  19. """
  20. 该函数通过cv2对img_mask进行边缘检测,获取车牌区域的边缘坐标(存储在contours中)和最小外接矩形4个端点坐标,
  21. 再从车牌的边缘坐标中计算出和最小外接矩形4个端点最近的点即为平行四边形车牌的四个端点,从而实现车牌的定位和矫正
  22. :param img_src: 原始图片
  23. :param img_mask: 通过u_net预测得到的二值化图片,车牌区域呈现白色,背景区域为黑色
  24. :return: 定位且矫正后的车牌
  25. """
  26. contours, hierarchy = cv2.findContours(img_mask[:, :, 0], cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  27. if not len(contours):#contours1长度为0说明未检测到车牌
  28. print("未检测到车牌")
  29. else:
  30. flag=0#默认flag为0,因为不一定有车牌区域
  31. for ii,cont in enumerate(contours):
  32. x, y, w, h = cv2.boundingRect(cont)#获取最小外接矩形
  33. img_cut_mask=img_mask[y:y+h,x:x+w]#将标签车牌区域截取出来
  34. if np.mean(img_cut_mask)>=75 and w>15 and h>15:
  35. rect = cv2.minAreaRect(cont)#针对坐标点获取带方向角的最小外接矩形,中心点坐标,宽高,旋转角度
  36. box = cv2.boxPoints(rect).astype(np.int32)#获取最小外接矩形四个顶点坐标
  37. cv2.drawContours(img_mask, contours, -1, (0, 0, 255), 2)
  38. cv2.drawContours(img_mask, [box], 0, (0, 255, 0), 2)
  39. cont=cont.reshape(-1,2).tolist()
  40. #由于转换矩阵的两组坐标位置需要一一对应,因此需要将最小外接矩形的坐标进行排序,最终排序为[左上,左下,右上,右下]
  41. box=sorted(box,key=lambda xy:xy[0])#先按照左右进行排序,分为左侧的坐标和右侧的坐标
  42. box_left,box_right=box[:2],box[2:]#此时box的前2个是左侧的坐标,后2个是右侧的坐标
  43. box_left=sorted(box_left,key=lambda x:x[1])#再按照上下即y进行排序,此时box_left中为左上和左下两个端点坐标
  44. box_right=sorted(box_right,key=lambda x:x[1])#此时box_right中为右上和右下两个端点坐标
  45. box=np.array(box_left+box_right)#[左上,左下,右上,右下]
  46. x0,y0=box[0][0],box[0][1]#这里的4个坐标即为最小外接矩形的四个坐标,接下来需获取平行(或不规则)四边形的坐标
  47. x1,y1=box[1][0],box[1][1]
  48. x2,y2=box[2][0],box[2][1]
  49. x3,y3=box[3][0],box[3][1]
  50. def point_to_line_distance(X,Y):
  51. if x2-x0:
  52. k_up=(y2-y0)/(x2-x0)#斜率不为无穷大
  53. d_up=abs(k_up*X-Y+y2-k_up*x2)/(k_up**2+1)**0.5
  54. else:#斜率无穷大
  55. d_up=abs(X-x2)
  56. if x1-x3:
  57. k_down=(y1-y3)/(x1-x3)#斜率不为无穷大
  58. d_down=abs(k_down*X-Y+y1-k_down*x1)/(k_down**2+1)**0.5
  59. else:#斜率无穷大
  60. d_down=abs(X-x1)
  61. return d_up,d_down
  62. d0,d1,d2,d3=np.inf,np.inf,np.inf,np.inf
  63. l0,l1,l2,l3=(x0,y0),(x1,y1),(x2,y2),(x3,y3)
  64. for each in cont: #计算cont中的坐标与矩形四个坐标的距离以及到上下两条直线的距离,对距离和进行权重的添加,成功选出四边形的4个顶点坐标
  65. x,y=each[0],each[1]
  66. dis0=(x-x0)**2+(y-y0)**2
  67. dis1=(x-x1)**2+(y-y1)**2
  68. dis2=(x-x2)**2+(y-y2)**2
  69. dis3=(x-x3)**2+(y-y3)**2
  70. d_up,d_down=point_to_line_distance(x,y)
  71. weight=0.975
  72. if weight*d_up+(1-weight)*dis0<d0:
  73. d0=weight*d_up+(1-weight)*dis0
  74. l0=(x,y)
  75. if weight*d_down+(1-weight)*dis1<d1:
  76. d1=weight*d_down+(1-weight)*dis1
  77. l1=(x,y)
  78. if weight*d_up+(1-weight)*dis2<d2:
  79. d2=weight*d_up+(1-weight)*dis2
  80. l2=(x,y)
  81. if weight*d_down+(1-weight)*dis3<d3:
  82. d3=weight*d_down+(1-weight)*dis3
  83. l3=(x,y)
  84. p0 = np.float32([l0,l1,l2,l3])#左上角,左下角,右上角,右下角,形成的新box顺序需和原box中的顺序对应,以进行转换矩阵的形成
  85. p1= np.float32([(0,0),(0,80),(240,0),(240,80)])
  86. transform_mat=cv2.getPerspectiveTransform(p0,p1)#构成转换矩阵
  87. lic=cv2.warpPerspective(img_src,transform_mat,(240,80))#进行车牌矫正
  88. if len(contours)==1:#只有一个区域可以认为是车牌区域
  89. flag+=1
  90. print('saving ',save_path+name[0:7]+'.png')
  91. # cv2.imshow('lic',lic)
  92. # cv2.waitKey(0)
  93. cv2.imencode('.png',lic)[1].tofile(save_path+name[0:7]+'.png')
  94. if not flag:
  95. print("未检测到车牌区域或车牌区域过小")
  96. if __name__ == '__main__':
  97. test_path='D:/Desktop/baidu/'#利用百度API标注或手动标注好的图片
  98. save_path='D:/desktop/license/'#车牌图片保存路径
  99. unet_path = 'unet.h5'
  100. listdir=os.listdir(test_path)
  101. unet=keras.models.load_model(unet_path)
  102. # print(listdir)
  103. for name in listdir:
  104. print(name)
  105. img_src_path=test_path+name
  106. img_src,img_mask=unet_predict(unet,img_src_path)
  107. locate(img_src,img_mask,name)

上述代码关键部分是要获取车牌四边形的四个顶点,一开始只使用cont中坐标到外接矩形四个端点的距离,发现对于倾斜度很高的车牌效果可能不佳,见下图,可以观察到,计算得到的4个黄色坐标中,左右有2个黄色点并不处在四边形的顶点位置,这样矫正效果大打折扣,同时也会影响后续的识别效果

发现上述问题后,我又想了个方法就是加入了上述的point_to_line_distance函数,即还计算坐标点到上下两条边的距离,并添加了权重,经过调整权重设置为0.975倍的点线距离,0.025点到端点距离时整体效果较佳,最终矫正效果如下图:

矫正效果大大改善后,识别率也将大大提高。

最终运行后上述代码后,提取的license文件夹中的车牌图如下:

由于某些省份的车牌图片网上比较少,且有些图片清晰度不佳,为了防止数据不均衡,因此我又对数据集进行了数据增强,总共标注了3万3千多张车牌图片

最终统计的频数图如下:

但是数据增强所增加的信息还是有限,某些省份如 藏,青,贵等由于训练图片少,或是图片不清晰,因此可能存在识别错误的情况,但是整体识别准确率还是很高的

3.车牌识别

我们的输入图片就是上述的宽240,高80的车牌图片,要实现车牌的端到端识别,显然是多标签分类问题,每张输入图片有7个标签,模型输出前的结构都是可以共享的,只需将输出修改为7个即可,7个输出对应了7个loss,总loss就是7个loss的和,使用keras可以很方便地实现,训练cnn的代码如下:

  1. def cnn_train():
  2. char_dict = {"京": 0, "沪": 1, "津": 2, "渝": 3, "冀": 4, "晋": 5, "蒙": 6, "辽": 7, "吉": 8, "黑": 9, "苏": 10,
  3. "浙": 11, "皖": 12, "闽": 13, "赣": 14, "鲁": 15, "豫": 16, "鄂": 17, "湘": 18, "粤": 19, "桂": 20,
  4. "琼": 21, "川": 22, "贵": 23, "云": 24, "藏": 25, "陕": 26, "甘": 27, "青": 28, "宁": 29, "新": 30,
  5. "0": 31, "1": 32, "2": 33, "3": 34, "4": 35, "5": 36, "6": 37, "7": 38, "8": 39, "9": 40,
  6. "A": 41, "B": 42, "C": 43, "D": 44, "E": 45, "F": 46, "G": 47, "H": 48, "J": 49, "K": 50,
  7. "L": 51, "M": 52, "N": 53, "P": 54, "Q": 55, "R": 56, "S": 57, "T": 58, "U": 59, "V": 60,
  8. "W": 61, "X": 62, "Y": 63, "Z": 64}
  9. # 读取数据集
  10. path = 'home/cnn_datasets/' # 车牌号数据集路径(车牌图片宽240,高80)
  11. pic_name = sorted(os.listdir(path))
  12. n = len(pic_name)
  13. X_train, y_train = [], []
  14. for i in range(n):
  15. print("正在读取第%d张图片" % i)
  16. img = cv2.imdecode(np.fromfile(path + pic_name[i], dtype=np.uint8), -1) # cv2.imshow无法读取中文路径图片,改用此方式
  17. label = [char_dict[name] for name in pic_name[i][0:7]] # 图片名前7位为车牌标签
  18. X_train.append(img)
  19. y_train.append(label)
  20. X_train = np.array(X_train)
  21. y_train = [np.array(y_train)[:, i] for i in range(7)] # y_train是长度为7的列表,其中每个都是shape为(n,)的ndarray,分别对应n张图片的第一个字符,第二个字符....第七个字符
  22. # cnn模型
  23. Input = layers.Input((80, 240, 3)) # 车牌图片shape(80,240,3)
  24. x = Input
  25. x = layers.Conv2D(filters=16, kernel_size=(3, 3), strides=1, padding='same', activation='relu')(x)
  26. x = layers.MaxPool2D(pool_size=(2, 2), padding='same', strides=2)(x)
  27. for i in range(3):
  28. x = layers.Conv2D(filters=32 * 2 ** i, kernel_size=(3, 3), padding='valid', activation='relu')(x)
  29. x = layers.Conv2D(filters=32 * 2 ** i, kernel_size=(3, 3), padding='valid', activation='relu')(x)
  30. x = layers.MaxPool2D(pool_size=(2, 2), padding='same', strides=2)(x)
  31. x = layers.Dropout(0.5)(x)
  32. x = layers.Flatten()(x)
  33. x = layers.Dropout(0.3)(x)
  34. Output = [layers.Dense(65, activation='softmax', name='c%d' % (i + 1))(x) for i in range(7)] # 7个输出分别对应车牌7个字符,每个输出都为65个类别类概率
  35. model = models.Model(inputs=Input, outputs=Output)
  36. model.summary()
  37. model.compile(optimizer='adam',
  38. loss='sparse_categorical_crossentropy', # y_train未进行one-hot编码,所以loss选择sparse_categorical_crossentropy
  39. metrics=['accuracy'])
  40. # 模型训练
  41. print("开始训练cnn")
  42. model.fit(X_train, y_train, epochs=35) # 总loss为7个loss的和
  43. model.save('cnn.h5')
  44. print('cnn.h5保存成功!!!')

最终,训练集上准确率acc1(即车牌省份字符)为97%,其余字符均为99%左右,本地测试集准确率为97%,识别效果较佳。

最后放一下整体的效果图:

全部代码以及训练好的模型都在github:https://github.com/duanshengliu/End-to-end-for-chinese-plate-recognition

整个项目花了我很多心血和时间,所以喜欢的话顺手点个star吧,谢谢支持,有意见或者建议欢迎评论,转载请注明出处,谢谢

关于keras实现unet,cnn模型还可以参考博客,我从中也受益良多:

https://blog.csdn.net/shi2xian2wei2/article/details/84345025

https://cloud.tencent.com/developer/article/1005199

转载自:https://blog.csdn.net/qq_32194791/article/details/106748685

CSDN车牌识别项目相关推荐

  1. 开源车牌识别项目,OpenALPR

    今天在github上看到了一个开源的车牌识别项目,OpenALPR.github链接 我以前自己在MATLAB上编写了一个简单的车牌识别的程序,使用的是传统模板匹配法.只是有了初步的效果,还有很多需要 ...

  2. (2023最新)基于 Grounded-SAM 的车牌识别项目

    背景介绍 曾经在大二的图像处理课程中完成了一个基础的车牌识别项目,当时主要采用的是普通的图像处理技术,并且没有结合前沿的OCR方法导致字符识别准确率堪忧. 现如今已经涌现出诸如Grounded-SAM ...

  3. 数字图像处理:基于MATLAB的车牌识别项目

    学过了数字图像处理,就进行一个综合性强的小项目来巩固一下知识吧.前阵子编写调试了一套基于MATLAB的车牌识别的项目的代码.今天又重新改进了一下代码,识别的效果好一点了,也精简了一些代码.这里没有使用 ...

  4. python车牌识别使用训练集_基于Python 实现的车牌识别项目

    车牌识别在高速公路中有着广泛的应用,比如我们常见的电子收费(ETC)系统和交通违章车辆的检测,除此之外像小区或地下车库门禁也会用到,基本上凡是需要对车辆进行身份检测的地方都会用到. 简介 车牌识别系统 ...

  5. 车牌识别项目全过程——opencv知识自学(1)

    目录 什么是opencv? 图像数字化基础知识 图像获取 图像变换 改变大小 车牌识别内容分析 定位车牌 图像降噪 形态学处理 阈值分割+边缘检测 什么是opencv? OpenCV(Open Sou ...

  6. 模式识别之车牌识别---一个开源车牌识别项目easypr

    http://doc.okbase.net/subconscious/archive/105312.html https://github.com/liuruoze http://www.cnblog ...

  7. OpenCV(项目)车牌识别1 -- 车牌提取(形态学)

    目录 一.形态学车牌提取(简单:单情景) 1.读取图片,转灰度图 2.提取轮廓(Sobel算子提取y方向边缘) 3.自适应二值化 4.闭运算处理,把图像闭合.揉团,使图像区域化 5.腐蚀/膨胀去噪得到 ...

  8. 【项目三、车牌检测+识别项目】四、使用LPRNet进行车牌识别

    目录 前言 一.数据集 二.训练 三.验证 四.测试结果 五.推理代码 Reference 前言 马上要找工作了,想总结下自己做过的几个小项目. 之前已经总结过了我做的第一个项目:xxx病虫害检测项目 ...

  9. 【项目三、车牌检测+识别项目】一、CCPD车牌数据集转为YOLOv5格式和LPRNet格式

    目录 前言 一.CCPD数据集介绍 二.CCPD数据集下载 三.划分训练集.验证集和测试集 四.车牌检测数据集制作 五.车牌识别数据集制作 六.我的车牌检测+识别数据集 Reference 前言 马上 ...

最新文章

  1. FLINK源代码调试方式
  2. 星期和工作日计算,你会了吗?
  3. windows下配置apache虚拟主机
  4. ZOJ 2540 Form a Square
  5. Django day17 博客项目(一)
  6. 蓝桥杯 ADV-127 算法提高 日期计算
  7. linux 安装Centos源
  8. 开放大学计算机应用基础第三次,江苏开放大学-计算机应用基础第三次.doc
  9. 这是一个没有现金的国家——丹麦
  10. matlab相关性分析
  11. 【白嫖系列-怕违规】告别BDWP龟速下载,体验飞一般的感觉
  12. 电脑常用快捷键及组合键
  13. OpenGL FBO学习
  14. BUG记录——解析程序包出现错误
  15. 高纯度钨酸铜粉末/钨酸铁粉末/钨酸亚铁粉末/硫化铋粉末/铬酸铋粉末/氧化锆粉末/铬酸钡粉末
  16. 苹果WWDC将于6月8日夏季发布会苹果WWDC发布会直播地址
  17. EMUI10开启公测!华为P30系列率先尝鲜,详细升级教程奉上
  18. 正态分布(用python画出相应的图)
  19. python中文朗读_用python实现的文字朗读
  20. 断言信息与元素等待_Sinno_Song_新浪博客

热门文章

  1. 【爬虫】 静态网页抓取
  2. 80核处理器_Intel i9-10980XE处理器首发评测:售价“良心”的18核性能旗舰
  3. 拨开国产 COS 系统的重重迷雾
  4. 镜头与相机法兰距匹配
  5. 蓝牙4.0 BLE 广播包解析
  6. scite php配置 下载,SciTE的基本配置文件
  7. 计算机专业黑话,互联网行业黑话大全
  8. Day059 爬虫(三)
  9. SAP-ABAP-SQL语句中CAST字段类型转换示例,CONCAT连接示例,SUBSTRING截断示例
  10. 与某流氓网站的血泪交战史