开发者

利用Python+Opencv实现车牌自动识别完整代码

目录
  • 1 导入相关模块
  • 2 相关功能函数定义
    • 2.1 彩色图片显示函数(plt_show0)
    • 2.2 灰度图片显示函数(plt_show)
    • 2.3 图像去噪函数(gray_guss)
  • 2 图像预处理
    • 2.1 图片读取
    • 2.2 高斯去噪
    • 2.3 边缘检测
    • 2.4 阈值化
  • 3 车牌定位
    • 3.1 区域选择
    • 3.2 形态学操作
    • 3.3 轮廓检测
  • 4 车牌字符分割
    • 4.1 高斯去噪
    • 4.2 阈值化
    • 4.3 膨胀操作
    • 4.4 车牌号排序
    • 4.5 分割效果
  • 5 模板匹配
    • 5.1 准备模板
    • 5.2 匹配结果
    • 5.3 匹配效果展示
  • 6完整代码
    • 总结 

      该篇文章将以实战形式演示利用python结合Opencv实现车牌识别,全程涉及图像预处理、车牌定位、车牌分割、通过模板匹配识别结果输出。该项目对于智能交通、车辆管理等领域具有实际应用价值。通过自动识别车牌号码,可以实现车辆追踪、违章查询、停车场管理等功能,提高交通管理的效率和准确性。可用于车牌识别技术学习。

      技术要点:

      • OpenCV:用于图像处理和计算机视觉任务。
      • Python:作为编程语言,具有简单易学、资源丰富等优点。
      • 图像处理技术:如灰度化、噪声去除、边缘检测、形态学操作、透视变换等。

      1 导入相关模块

      import cv2
      from matplotlib import pyplot as plt
      import os
      import numpy as np
      from PIL import ImageFont, ImageDraw, Image
      

      2 相关功能函数定义

      2.1 彩色图片显示函数(plt_show0)

      def plt_show0(img):
          b,g,r = cv2.split(img)
          img = cv2.merge([r, g, b])
          plt.imshow(img)
          plt.show()
      

      cv2与plt的图像通道不同:cv2为[b,g,r];plt为[r, g, b]

      2.2 灰度图片显示函数(plt_show)

      def plt_show(img):
          plt.imshow(img,cmap='gray')
          plt.show()
      

      2.3 图像去噪函数(gray_guss)

      def gray_guss(image):
          image = cv2.GaussianBlur(image, (3, 3), 0)
          gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
          return gray_image
      

      此处演示使用高斯模糊去噪。

      cv2.GaussianBlur参数说明:

      • src:输入图像,可以是任意数量的通道,这些通道可以独立处理,但深度应为 CV_8UCV_16UCV_16SCV_32F 或 CV_64F
      • ksize:高斯核的大小,必须是正奇数,例如 (3, 3)、(5, 5) 等。如果 ksize 的值为零,那么它会根据 sigmaX 和 sigmaY 的值来计算。
      • sigmaX:X 方向上的高斯核标准偏差。
      • dst:输出图像,大小和类型与 src 相同。
      • sigmaY:Y 方向上的高斯核标准偏差,如果 sigmaY 是零,那么它会与 sigmaX 的值相同。如果 sigmaY 是负数,那么它会从 ksize.width 和 ksize.height 计算得出。
      • borderType:像素外插法,有默认值。

      2 图像预处理

      2.1 图片读取

      origin_image = cv2.imread('D:/image/car3.jpg')
      

        此处演示识别车牌原图:

      利用Python+Opencv实现车牌自动识别完整代码

      2.2 高斯去噪

      origin_image = cv2.imread('D:/image/car3.jpg')
      # 复制一张图片,在复制图上进行图像操作,保留原图
      image = origin_image.copy()
      gray_image = gray_guss(image)
      

      2.3 边缘检测

      Sobel_x = cv2.Sobel(gray_image, cv2.CV_16S, 1, 0)
      absX = cv2.convertScaleAbs(Sobel_x)
      image = absX
      

      x方向上的边缘检测(增强边缘信息)

      2.4 阈值化

      # 图像阈值化操作——获得二值化图
      ret, image = cv2.threshold(image, 0, 255, cv2.THRESH_OTSU)
      # 显示灰度图像
      plt_show(image)
      

        运行结果:

      利用Python+Opencv实现车牌自动识别完整代码

      3 车牌定位

      3.1 区域选择

      kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 10))
      image = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernelX,iterations = 1)
      # 显示灰度图像
      plt_show(image)
      

      从图像中提取对表达和描绘区域形状有意义的图像分量。

        运行结果:

      利用Python+Opencv实现车牌自动识别完整代码

      3.2 形态学操作

      # 腐蚀(erode)和膨胀(dilate)
      kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 1))
      kernelY = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 20))
      #x方向进行闭操作(抑制暗细节)
      image = cv2.dilate(image, kernelX)
      image = cv2.erode(image, kernelX)
      #y方向的开操作
      image = cv2.erode(image, kernelY)
      image = cv2.dilate(image, kernelY)
      # 中值滤波(去噪)
      image = cv2.medianBlur(image, 21)
      # 显示灰度图像
      plt_show(image)
      

      使用膨胀和腐蚀操作来突出车牌区域。

         运行结果:

      利用Python+Opencv实现车牌自动识别完整代码

      3.3 轮廓python检测

      contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
      for item in contours:
          rect = cv2.boundingRect(item)
          x = rect[0]
          y = rect[1]
          weight = rect[2]
          height = rect[3]
          # 根据轮廓的形状特点,确定车牌的轮廓位置并截取图像
          if (weight > (height * 3)) and (weight < (height * 4.5)):
              image = origin_image[y:y + height, x:x + weight]
              plt_show(image)
      

      利用Python+Opencv实现车牌自动识别完整代码

      4 车牌字符分割

      4.1 高斯去噪

      # 图像去噪灰度处理
      gray_image = gray_guss(image)
      

      4.2 阈值化

      ret, image = cv2.threshold(gray_image, 0, 255, cv2.THRESH_OTSU)
      plt_show(image)
      

        运行结果:

      利用Python+Opencv实现车牌自动识别完整代码

      4.3 膨胀操作

      #膨胀操作
      kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (4, 4))
      image = cv2.dilate(image, kernel)
      plt_show(image)
      

        运行结果:

      利用Python+Opencv实现车牌自动识别完整代码

      4.4 车牌号排序

      words = sorted(words,key=lambda s:s[0],reverse=False)
      i = 0
      #word中存放轮廓的起始点和宽高
      for word in words:
          # 筛选字符的轮廓
          if (word[3] > (word[2] * 1.5)) and (word[3] < (word[2] * 5.5)) and (word[2] > 10):
              i = i+1
              if word[2] < 15:
                  splite_image = image[word[1]:word[1] + word[3], word[0]-word[2]:word[0] + word[2]*2]
              else:
                  splite_image = image[word[1]:word[1] + word[3], word[0]:word[0] + word[2]]
              word_images.append(splite_image)
              print(i)
      print(words)
      

        运行结果:

      1
      2
      3
      4
      5
      6
      7
      [[2, 0, 7, 70], [12, 6, 30, 55], [15, 7, 7, 9], [46, 6, 32, 55], [83, 30, 9, 9], [96, 7, 32, 55], [132, 8, 32, 55], [167, 8, 30, 54], [202, 62, 7, 6], [203, 7, 30, 55], [245, 7, 12, 54], [266, 0, 12, 70]]
      

      4.5 分割效果

      for i,j in enumerate(word_images):  
          plt.subplot(1,7,i+1)
          plt.imshow(word_images[i],cmap='gray')
      plt.show()
      

        运行结果:

      利用Python+Opencv实现车牌自动识别完整代码

      5 模板匹配

      5.1 准备模板

      # 准备模板(template[0-9]为数字模板;)
      template = ['0','1','2','3','4','5','6','7','8','9',
                  'A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z',
                  '藏','川','鄂','甘','赣','贵','桂','黑','沪','吉','冀','津','晋','京','辽','鲁','蒙','闽','宁',
                  '青','琼','陕','苏','皖','湘','新','渝','豫','粤','云','浙']
      
      # 读取一个文件夹下的所有图片,输入参数是文件名,返回模板文件地址列表
      def read_directory(directory_name):
          referImg_list = []
          for filename in os.listdir(directory_name):
              referImg_list.append(directory_name + "/" + filename)
          return referImg_list
      
      # 获得中文模板列表(只匹配车牌的第一个字符)
      def get_chinese_words_list():
          chinese_words_list = []
          for i in range(34,64):
              #将模板存放在字典中
              c_word = read_directory('D:/refer1/'+ template[i])
              chinese_words_list.append(c_word)
          return chinese_words_list
      chinese_words_list = get_chinese_words_list()
      
      
      # 获得英文模板列表(只匹配车牌的第二个字符)
      def get_eng_words_list():
          eng_words_list = []
          for i in range(10,34):
              e_word = read_directory('D:/refer1/'+ template[i])
              eng_words_list.append(e_word)
          return eng_words_list
      eng_words_list = get_eng_words_list()
      
      
      # 获得英文和数字模板列表(匹配车牌后面的字符)
      def get_eng_num_words_list():
          eng_num_words_list = []
          for i in range(0,34):
              word = read_directory('D:/refer1/'+ template[i])
              eng_num_words_list.append(word)
          return eng_num_words_list
      eng_num_words_list = get_eng_num_words_list()
      

      此处需提前准备各类字符模板。

      5.2 匹配结果

      # 获得英文和数字模板列表(匹配车牌后面的字符)
      def get_eng_num_words_list():
          eng_num_words_list = []
          for i in range(0,34):
              word = read_directory('D:/refer1/'+ template[i])
              eng_num_words_list.append(word)
          return eng_num_words_list
      eng_num_words_list = get_eng_num_words_list()
      
      
      # 读取一个模板地址与图片进行匹配,返回得分
      def template_score(template,image):
          #将模板进行格式转换
          template_img=cv2.imdecode(np.fromfile(template,dtype=np.uint8),1)
          template_img = cv2.cvtColor(template_img, cv2.COLOR_RGB2GRAY)
          #模板图像阈值化处理——获得黑白图
          ret, template_img = cv2.threshold(template_img, 0, 255, cv2.THRESH_OTSU)
      #     height, width = template_img.shape
      #     image_ = image.copy()
      #     image_ = cv2.resize(image_, (width, height))
          image_ = image.copy()
          #获得待检测图片的尺寸
          height, width = image_.shape
          # 将模板resize至与图像一样大小
          template_img = cv2.resize(template_img, (width, height))
          # 模板匹配,返回匹配得分
          result = cv2.matchTemplate(image_, template_img, cv2.TM_CCOEFF)
          return result[0][0]
      
      
      # 对分割得到的字符逐一匹配
      def template_matching(word_images):
          results = []
          for index,word_image in enumerate(word_images):
              if index==0:
                  best_score = []
                  for chinese_words in chinese_words_list:
                      score = []
                      for chinese_word in chinese_words:
                          result = template_score(chinese_word,word_image)
                          score.append(result)
                      best_score.append(max(score))
                  i = best_score.index(max(best_score))
                  # print(template[34+i])
                  r = template[34+i]
                  results.append(r)
                  continue
              if index==1:
                  best_score = []
                  for eng_word_list in eng_words_list:
                      score = []
                      for eng_word in eng_word_list:
                          result = template_score(eng_word,word_image)
                          score.append(result)
                      best_score.append(max(score))
                  i = best_score.index(max(best_score))
                  # print(template[10+i])
                  r = template[10+i]
                  results.append(r)
                  continue
              else:
                  best_score = []
                  for eng_num_word_list in eng_num_words_list:
                      score = []
                      for eng_num_word in eng_num_word_list:
                          result = template_score(eng_num_word,word_image)
                          score.append(result)
                      best_score.append(max(score))
                  i = best_score.index(max(best_score))
                  # print(template[i])
                  r = template[i]
                  results.append(r)
                  continue
          return results
      
      
      word_images_ = word_images.copy()
      # 调用函数获得结果
      result = template_matching(word_images_)
      print(result)
      print( "".join(result))
      

        运行结果:

      ['渝', 'B', 'F', 'U', '8', '7', '1']
      渝BFU871
      

      “”.join(result)函数将列表转换为拼接好的字符串,方便结果显示

      5.3 匹配效果展示

      height,weight = origin_image.shape[0:2]
      print(height)
      print(weight)
      
      image_1 = origin_image.copy()
      cv2.rectangle(image_1, (int(0.2*weight), int(0.75*height)), (int(weight*0.9), int(height*0.95)), (0, 255, 0), 5)
      
      #设置需要显示的字体
      fontpath = "font/simsun.ttc"
      font = ImageFont.truetype(fontpath,64)
      img_pil = Image.fromarray(image_1)
      draw = ImageDraw.Draw(img_pil)
      #绘制文字信息
      draw.text((int(0.2*weight)+25, int(0.75*height)),  "".join(result), font = font, fill = (255, 255, 0))
      bk_img = np.array(img_pil)
      print(result)
      print( "".join(result))
      plt_show0(bk_img)
      

        运行结果:

      利用Python+Opencv实现车牌自动识别完整代码

      6完整代码

      # 导入所需模块
      import cv2
      from matplotlib import pyplot as plt
      import os
      import numpy as np
      from PIL import ImageFont, ImageDraw, Image
      # plt显示彩色图片
      def plt_show0(img):
          b,g,r = cv2.split(img)
          img = cv2.merge([r, g, b])
          plt.imshow(img)
          plt.show()
          
      # plt显示灰度图片
      def plt_show(img):
          plt.imshow(img,cmap='gray')
          plt.show()
          
      # 图像去噪灰度处理
      def gray_guss(image):
          image = cv2.GaussianBlur(image, (3, 3), 0)
          gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
          return gray_image
      
      # 读取待检测图片
      origin_image = cv2.imread('D:/image/car3.jpg')
      # 复制一张图片,在复制图上进行图像操作,保留原图
      image = origin_image.copy()
      # 图像去噪灰度处理
      gray_image = gray_guss(image)
      # x方向上的边缘检测(增强边缘信息)
      Sobel_x = cv2.Sobel(gray_image, cv2.CV_16S, 1, 0)
      absX = cv2.convertScaleAbs(Sobel_x)
      image = absX
      
      # 图像阈值化操作——获得二值化图
      ret, image = cv2.threshold(image, 0, 255, cv2.THRESH_OTSU)
      # 显示灰度图像
      plt_show(image)
      # 形态学(从图像中提取对表达和描绘区域形状有意义的图像分量)——闭操作
      kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 10))
      image = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernelX,iterations = 1)
      # 显示灰度图像
      plt_show(image)
      
      
      # 腐蚀(erode)和膨胀(dilate)
      kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 1))
      kernelY = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 20))
      #x方向进行闭操作(抑制暗细节)
      image = cv2.dilate(image, kernelX)
      image = cv2.erode(image, kernelX)
      #y方向的开操作
      image = cv2.erode(image, kernelY)
      image = cv2.dilate(image, kernelY)
      # 中值滤波(去噪)
      image = cv2.medianBlur(image, 21)
      # 显示灰度图像
      plt_show(image)
      
      # 获得轮廓
      contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
      
      for item in contours:
          rect = cv2.boundingRect(item)
          x = rect[0]
          y = rect[1]
          weight = rectjavascript[2]
          height = rect[3]
          # 根据轮廓的形状特点,确定车牌的轮廓位置并截取图像
          if (weight > (height * 3)) and (weight < (height * 4.5)):
              image = origin_image[y:y + height, x:x + weight]
              plt_show(image)
      
      
      #车牌字符分割
      # 图像去噪灰度处理
      gray_image = gray_guss(image)
      
      # 图像阈值化操作——获得二值化图   
      ret, image = cv2.threshold(gray_image, 0, 255, cv2.THRESH_OTSU)
      plt_show(image)
      
      #膨胀操作
      kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (4, 4))
      image = cv2.dilate(image, kernel)
      plt_show(image)
      
      
      # 查找轮廓
      contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
      words = []
      word_images = []
      #对所有轮廓逐一操作
      for item in contours:
          word = []
          rect = cv2.boundingRect(item)
          x = rect[0]
          y = rect[1]
          weight = rect[2]
          height = rect[3]
          word.append(x)
          word.append(y)
          word.append(weight)
          word.append(height)
          words.append(word)
      # 排序,车牌号有顺序。words是一个嵌套列表
      words = sorted(words,key=lambda s:s[0],reverse=False)
      i = http://www.devze.com0
      #word中存放轮廓的起始点和宽高
      for word in words:
          # 筛选字符的轮廓
          if (word[3] > (word[2] * 1.5)) and (word[3] < (word[2] * 5.5)) and (word[2] > 10):
              i = i+1
              if word[2] < 15:
                  splite_image = image[word[1]:word[1] + word[3], word[0]-word[2]:word[0] + word[2]*2]
              else:
                  splite_image = image[word[1]:word[1] + word[3], word[0]:word[0] + word[2]]
              word_images.append(splite_image)
              prinwww.devze.comt(i)
      print(words)
      
      for i,j in enumerate(word_images):  
          plt.subplot(1,7,i+1)
          plt.imshow(word_images[i],cmap='gray')
      plt.show()
      
      #模版匹配
      # 准备模板(template[0-9]为数字模板;)
      template = ['0','1','2','3','4','5','6','7','8','9',
                  'A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z',
                  '藏','川','鄂','甘','赣','贵','桂','黑','沪','吉','冀','津','晋','京','辽','鲁','蒙','闽','宁',
                  '青','琼','陕','苏','皖','湘','新','渝','豫','粤','云','浙']
      
      # 读取一个文件夹下的所有图片,输入参数是文件名,返回模板文件地址列表
      def read_directory(directory_name):
          referImg_list = []
          for filename in os.listdir(directory_name):
              referImg_list.append(directory_name + "/" + filename)
          return referImg_list
      
      # 获得中文模板列表(只匹配车牌的第一个字符)
      def get_chinese_words_list():
          chinese_words_list = []
          for i in range(34,64):
              #将模板存放在字典中
              c_word = read_directory('D:/refer1/'+ template[i])
              chinese_words_list.append(c_word)
          return chinese_words_list
      chinese_words_list = get_chinese_words_list()
      
      
      # 获得英文模板列表(只匹配车牌的第二个字符)
      def get_eng_words_list():
          eng_words_list = []
          for i in range(10,34):
              e_word = read_directory('D:/refer1/'+ template[i])
              eng_words_list.append(e_word)
          return eng_words_list
      eng_words_list = get_eng_words_list()
      
      
      # 获得英文和数字模板列表(匹配车牌后面的字符)
      def get_eng_num_words_list():
          eng_num_words_list = []
          for i in range(0,34):
              word = read_directory('D:/refer1/'+ template[i])
              eng_num_words_list.append(word)
          return eng_num_words_list
      eng_num_words_list = get_eng_num_words_list()
      
      
      # 读取一个模板地址与图片进行匹配,返回得分
      def template_score(template,image):
          #将模板进行格式转换
          template_img=cv2.imdecode(np.fromfile(template,dtype=np.uint8),1)
          template_img = cv2.cvtColor(template_img, cv2.COLOR_RGB2GRAY)
          #模板图像阈值化处理——获得黑白图
          ret, template_img = cv2.threshold(template_img, 0, 255, cv2.THRESH_OTSU)
      #     height, width = template_img.shape
      #     image_ = iandroidmage.copy()
      #     image_ = cv2.resize(image_, (width, height))
          image_ = image.copy()
          #获得待检测图片的尺寸
          height, width = image_.shape
          # 将模板resize至与图像一样大小
          template_img = cv2.resize(template_img, (width, height))
          # 模板匹配,返回匹配得分
          result = cv2.matchTemplate(image_, template_img, cv2.TM_CCOEFF)
          return result[0][0]
      
      
      # 对分割得到的字符逐一匹配
      def template_matching(word_images):
          results = []
          for index,word_image in enumerate(word_images):
              if index==0:
                  best_score = []
                  for chinese_words in chinese_words_list:
                      score = []
                      for chinese_word in chinese_words:
                          result = template_score(chinese_word,word_image)
                          score.append(result)
                      best_score.append(max(score))
                  i = best_score.index(max(best_score))
                  # print(template[34+i])
                  r = template[34+i]
                  results.append(r)
                  continue
              if index==1:
                  best_score = []
                  for eng_word_list in eng_words_list:
                      score = []
                      for eng_word in eng_word_list:
                          result = template_score(eng_word,word_image)
                          score.append(result)
                      best_score.append(max(score))
                  i = best_score.index(max(best_score))
                  # print(template[10+i])
                  r = template[10+i]
                  results.append(r)
                  continue
              else:
                  best_score = []
                  for eng_num_word_list in eng_num_words_list:
                      score = []
                      for eng_num_word in eng_num_word_list:
                          result = template_score(eng_num_word,word_image)
                          score.append(result)
                      best_score.append(max(score))
                  i = best_score.index(max(best_score))
                  # print(template[i])
                  r = template[i]
                  results.append(r)
                  continue
          return results
      
      
      word_images_ = word_images.copy()
      # 调用函数获得结果
      result = template_matching(word_images_)
      print(result)
      # "".join(result)函数将列表转换为拼接好的字符串,方便结果显示
      print( "".join(result))
      
      
      
      height,weight = origin_image.shape[0:2]
      print(height)
      print(weight)
      
      image_1 = origin_image.copy()
      cv2.rectangle(image_1, (int(0.2*weight), int(0.75*height)), (int(weight*0.9), int(height*0.95)), (0, 255, 0), 5)
      
      #设置需要显示的字体
      fontpath = "font/simsun.ttc"
      font = ImageFont.truetype(fontpath,64)
      img_pil = Image.fromarray(image_1)
      draw = ImageDraw.Draw(img_pil)
      #绘制文字信息
      draw.text((int(0.2*weight)+25, int(0.75*height)),  "".join(result), font = font, fill = (255, 255, 0))
      bk_img = np.array(img_pil)
      print(result)
      print( "".join(result))
      plt_show0(bk_img)

      总结 

      到此这篇关于利用Python+Opencv实现车牌自动识别的文章就介绍到这了,更多相关Python+Opencv车牌自动识别内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新开发

      开发排行榜