第四期【百度大脑新品体验】车牌识别(一)
busyboxs 发布于2019-08 浏览:2458 回复:0
0
收藏
最后编辑于2022-04

车牌识别现在已经有了许多应用,例如停车场闸机识别,高速公路收费站车牌识别等。在本文中,将介绍如何使用百度AI的接口来实现车牌识别。

车牌识别接口介绍

本段将简单介绍一下车牌识别接口,具体的内容可以参见 文档( https://ai.baidu.com/docs#/OCR-API/5116ac95 )。

接口描述

对机动车蓝牌、绿牌、单/双行黄牌的地域编号和车牌号进行识别,并能同时识别图像中的多张车牌。

请求说明

  • 请求url:https://aip.baidubce.com/rest/2.0/ocr/v1/license_plate
  • 请求参数:image, multi_detect

返回说明

  • 返回参数:log_id, Color,number,probability, vertexes_location

  • 返回实例
{'log_id': 6317054685683389581,
 'words_result': [{'color': 'blue',
                   'number': '晋A2B222',
                   'probability': [0.9048133492469788,
                                   0.9014081954956055,
                                   0.9013367891311646,
                                   0.901279628276825,
                                   0.9011501669883728,
                                   0.9012312889099121,
                                   0.9011697769165039],
                   'vertexes_location': [{'x': 69, 'y': 83},
                                         {'x': 326, 'y': 83},
                                         {'x': 326, 'y': 163},
                                         {'x': 69, 'y': 163}]}]}

Python3 调用接口实现车牌识别

如果是初次使用接口可以查看 接入指南文档 ( https://ai.baidu.com/docs#/Begin/top )了解更多相关信息。

获取 API key 和 Secret Key

1. 进入百度智能云控制台( https://console.bce.baidu.com/?fromai=1#/aip/overview ),在左侧找到“文字识别”并点击;

          

2. 点击“创建应用”,填写好相应的信息之后点击“立即创建”即可;

3.应用创建好之后就能看到对应的 API Key 和 Secret Key,这两个对应的内容需要在代码中使用。

获取 access token

Access token 获取以及Access token的相关文档可以查看 鉴权认证机制文档 ( http://ai.baidu.com/docs#/Auth/top )

下面是本文使用 python3 通过 request 库获取 access token 的代码

def get_token_key(client_id, client_secret):
    """
    get access token key.
    
    Args:
        client_id: API Key of related application
        client_secret: Secret Key of related application

    Returns:
        token_key: access token

    """
    url = f'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials' \
        f'&client_id={client_id}&client_secret={client_secret}'
    headers = {'Content-Type': 'application/json; charset=UTF-8'}
    res = requests.post(url, headers=headers)
    token_content = res.json()
    assert "error" not in token_content, f"{token_content['error_description']}"
    token_key = token_content['access_token']
    return token_key

调用车牌识别接口

根据请求参数可以实现车牌识别接口的调用,本文中将接口调用写在了一个类中,详细代码如下:

# -*- encoding: utf-8 -*-
import requests
import cv2
import numpy as np
from utils import draw_zh, get_pixel, get_edge
requests.packages.urllib3.disable_warnings()


class Plate(object):

    def __init__(self, client_id, client_secret):
        self.client_id = client_id
        self.client_secret = client_secret
        self.token_key = self.get_token_key()
        self.multi_detect = True
        self.COLOR = {'blue': "蓝色", 'green': "绿色", 'yellow': "黄色"}
        self.color = {'blue': (255, 0, 0), 'green': (0, 255, 0), 'yellow': (0, 255, 255)}

    def get_token_key(self):
        url = f'https://aip.baidubce.com/oauth/2.0/token'
        res = requests.get(url, verify=False,params={
            'grant_type': 'client_credentials',
            'client_id': self.client_id,
            'client_secret': self.client_secret})
        token_content = res.json()
        assert "error" not in token_content, f"{token_content['error_description']}"
        token_key = token_content['access_token']
        return token_key

    def get_result(self, data):
        """
        调用车牌识别接口,获取识别结果
        Args:
            data: 接口请求参数,类型为 dict

        Returns: 如果未识别到车牌,直接退出;如果识别到车牌,返回识别结果。

        """
        request_url = "https://aip.baidubce.com/rest/2.0/ocr/v1/license_plate"
        params = dict()
        params['access_token'] = self.token_key
        res = requests.post(url=request_url,
                            data=data,
                            params=params,
                            verify=False,
                            headers={'Content-Type': 'application/x-www-form-urlencoded'})
        result = res.json()
        self.multi_detect = data['multi_detect']
        if 'error_code' in result:
            print('未检测到车牌,请换图片进行检测!')
            exit()
        return result

    def get_length(self, result):
        """

        Args:
            result: 调用接口获得的识别结果,类型为 dict

        Returns: 识别到的车牌的数量

        """
        return len(result['words_result']) if self.multi_detect else 1

    def draw(self, img, result, color=(0, 255, 0), merge=False):
        """
        将识别结果绘制在原图像上,包括车牌边框、颜色及车牌号
        Args:
            img: 通过 opencv 读入的图像
            result: 调用车牌识别接口获取的识别结果
            color: 绘制所用的颜色
            merge: 是否将车牌提取出来放在原图像左上角

        Returns: 绘制好结果的图像

        """
        length = self.get_length(result)
        data = result['words_result']
        for i in range(length):
            plate_color = self.get_color(data[i])
            number = self.get_number(data[i])
            points = self.get_points(data[i])
            pts = np.array(points, np.int32).reshape((-1, 1, 2))
            cv2.polylines(img, [pts], True, self.color[plate_color], 3)
            (x, y, w, h) = cv2.boundingRect(pts)

            pixel = get_pixel(w)
            edge = get_edge(pixel)

            roi = np.zeros((edge+h, w, 3), np.uint8)
            roi.fill(255)
            clone = img.copy()
            roi[edge:, :] = clone[y:y + h, x:x + w]
            draw_zh(roi, f'{number}', 0, 0, self.color[plate_color], pixel)
            # cv2.imshow(f'roi{i}', roi)
            background = img[points[0][1] - edge:points[0][1], points[0][0]:points[0][0]+edge*8]
            background.fill(255)
            draw_zh(img, f'{number} - {self.COLOR[plate_color]}', points[0][0], points[0][1] - edge,
                    self.color[plate_color], pixel)
            if merge:
                img[:edge+h, :w] = roi
        return img

    @staticmethod
    def get_log_id(result):
        return result['log_id']

    @staticmethod
    def get_color(data):
        return data['color']

    @staticmethod
    def get_number(data):
        return data['number']

    @staticmethod
    def get_points(data):
        points = data['vertexes_location']
        locations = list()
        for point in points:
            locations.append([point['x'], point['y']])
        return locations

调用类实现识别

通过调用上面介绍的车牌识别类可以方便的执行车牌识别

以下是 python3 执行的代码

import requests
from plate import Plate
from utils import pic_base64
from pprint import pprint
import cv2
import imutils
requests.packages.urllib3.disable_warnings()

client_id = "这里填写自己的 API Key"
client_secret = "这里填写自己的 Secret Key"

img_name = "images/004.jpg"
image_base64 = pic_base64(img_name)
multi_detect = True

data = dict()
data['image'] = str(image_base64, encoding='utf-8')
data['multi_detect'] = multi_detect

plate_obj = Plate(client_id, client_secret)
result = plate_obj.get_result(data)

# pprint(result)

img = cv2.imread(img_name)
img = plate_obj.draw(img, result, merge=False)
cv2.namedWindow('pic', cv2.WINDOW_NORMAL)
cv2.imshow('pic', img)
cv2.waitKey()

车牌识别结果展示

从结果中可以看到,对于单个车牌的检测还是非常准确的。多个车牌的检测还是有一些问题。但是在实际应用中,多车牌的识别暂时还比较少。

收藏
点赞
0
个赞
TOP
切换版块