Python は検証コードの画像認識に Baidu OCR インターフェイスを使用します

前回は、pytesseract ソフトウェアとその Python ライブラリから OCR 画像認識を開始し、画像の読み取り、形式変換、画像処理を行いました。また、検証コードの取得、ログイン検証、さまざまな画像処理の認識を含む検証コード認識実験も実施しました。効果テスト、具体的な内容は以下のリンクをクリックして読むことができます: Python は検証コード画像認識に pytesseract を使用します_Cameback_Tang のブログ-CSDN ブログ_検証コード画像認識

今回は、Baidu の OCR 認識インターフェースを使用し、ソフトウェアとそのインターフェースによる方法ではなく、インターネットによる方法を使用します。さらに、無料で直接呼び出すこともでき、最後の非干渉検証コードをテストすることで、直接認識率は 99% に達し、pytesseract の 76% よりもはるかに優れています。もちろん、干渉する検証コードが追加された場合、認識率は干渉に対処した後にのみ向上します。

今回使用したOCRインターフェースのソース:Text Recognition_General Scene Text Recognition-Baidu AI Open Platform

簡易OCRテキスト認識は「一般テキスト認識」を中心に主に4種類あり、上記リンクから独学で学習することができます。

コードでは、type パラメータを通じて対応する OCR インターフェイスを指定する必要があります。デフォルトでは、「ユニバーサル テキスト認識インターフェイス、位置情報なしの高精度」が使用されます。

前回と同様に、ここでも 2 つの認識関数を書きました。つまり、画像ファイルによる認識と画像の Base64 エンコーディングによる認識です。

 

import requests
import base64
from urllib.parse import urlencode

def get_result_by_baiduOCR(file_path):
    url = 'https://cloud.baidu.com/aidemo'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36 Edg/94.0.992.47',
        'Content-Type': 'application/x-www-form-urlencoded',
        'Host': 'cloud.baidu.com',
        'Origin': 'https://cloud.baidu.com',
        ## 其他接口请详见https://cloud.baidu.com/product/ocr_general
        'Referer': 'https://cloud.baidu.com/product/ocr/general',  # 通用文字识别接口,高精度不带位置
        # 'Referer': 'https://cloud.baidu.com/product/ocr_others/handwriting', # 手写接口
        # 'Referer': 'https://cloud.baidu.com/product/ocr/doc_analysis_office', # 文档接口
        # 'Referer': 'https://cloud.baidu.com/product/ocr_others/webimage', # 网络图片接口
        # 'Connection':'keep-alive',
        # 'Cookie':'hadhsahjsaj',
        # # '':'',
    }
    with open(file_path, 'rb') as f:
        img_base64 = base64.b64encode(f.read())
        data = {
            'image':f'data:image/png;base64,{img_base64.decode()}',
            'image_url':'xxxxxx',
            'type':'https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic',
            # 'type':'https://aip.baidubce.com/rest/2.0/ocr/v1/handwriting',
            # 'type':'https://aip.baidubce.com/rest/2.0/ocr/v1/doc_analysis_office',
            # 'type':'https://aip.baidubce.com/rest/2.0/ocr/v1/webimage',
            'detect_direction': 'false',
            # 'language_type':'CHN_ENG',
            'language_type': 'ENG',
            # 'detect_direction':False,
        }
        data = urlencode(data)
        data = data.replace('image_url=xxxxxx', 'image_url')
        html = requests.post(url, data, headers=headers)
        # print(html.text)
        # rsp = {
        #     "errno": 0,
        #     "msg": "success",
        #     "data": {
        #         "words_result": [{"words": "Pi15"}],
        #         "words_result_num": 1,
        #         "log_id": "1515968155725851265"}
        # }
        html = html.json()
        print(html)
        if html.get('errno') == 0:
            result = html.get('data').get('words_result')[0].get('words')
            result = ''.join(list(filter(str.isalnum, result)))  # 只保留字母和数字
        else:
            result = ''
    return result

def get_result_by_baiduOCR_base64(img_base64):
    url = 'https://cloud.baidu.com/aidemo'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36 Edg/94.0.992.47',
        'Content-Type': 'application/x-www-form-urlencoded',
        'Host': 'cloud.baidu.com',
        'Origin': 'https://cloud.baidu.com',
        'Referer': 'https://cloud.baidu.com/product/ocr/general',
        # 'Connection': 'close'   # http的连接数超过最大限制,默认的情况下连接是Keep-alive的,所以这就导致了服务器保持了太多连接而不能再新建连接。
        # 'Connection':'keep-alive',
        # 'Cookie':'',
        # # '':'',
    }
    data = {
        'image':f'data:image/png;base64,{img_base64}',
        # 'image_url':'xxxxxx',
        'type':'https://aip.baidubce.com/rest/2.0/ocr/v1/accurate_basic',
        'detect_direction':'false',
        # 'language_type':'CHN_ENG',
        'language_type':'ENG',
    }
    data = urlencode(data)
    html = requests.post(url, data, headers=headers)
    html = html.json()
    if html.get('errno') == 0:
        result = html.get('data').get('words_result')[0].get('words')
        result = ''.join(list(filter(str.isalnum, result)))  # 只保留字母和数字
    else:
        result = ''
    return result

また、画像オブジェクト画像の Base64 エンコーディング間の変換が必要になる場合があります。それ以外の場合は、ファイルの保存と読み取りを行います。

import base64
from PIL import Image
from io import BytesIO

# image:图像对象


    def image_to_base64(image, fmt='JPEG'):
        output_buffer = BytesIO()
        image.save(output_buffer, format=fmt)
        byte_data = output_buffer.getvalue()
        base64_str = base64.b64encode(byte_data).decode('utf-8')
        return base64_str

    def base64_to_image(base64_str):
        byte_data = base64.b64decode(base64_str)
        image_data = BytesIO(byte_data)
        img = Image.open(image_data)
        return img

ここで余談を挟みますが、認証コードの取得については、




# 获取验证码,保存html到图片文件
session = requests.session()
vpic_url = 'https://xxxxxxx/getVerify'
html = session.get(vpic_url, headers=headers)
with open("py016.jpeg", "wb") as f:
    f.write(html.content)
    img = Image.open("py016.jpeg")


# 获取验证码,使用selenium.webdriver和谷歌浏览器方式
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
url = 'https://xxxxxx/login'
driver = webdriver.Chrome()
driver.get(url)

img = driver.find_element_by_tag_name('img') 
img.screenshot('aaa.jpeg')  # 神来之笔,保存为图像文件
verifyCode = get_result_by_baiduOCR_base64(
    driver.find_element_by_tag_name('img').screenshot_as_base64 # 神来之笔,直接变成图像base64编码
)

ここで別の余談ですが、検証コードの処理に関しては、背景の干渉が同じではなく、色が 1 つしかなく、比較的明るい色しかないことがわかりました。グレースケール処理と白黒の 2 値を使用してみてください。結果は素晴らしかったです。

 しきい値を 100 として使用すると、白黒バイナリの結果は次のようになります。

# 灰度化和其他阈值二值黑白化
def gray_processing(img, threshold = 127):
    img = img.convert('L')
    # threshold = 127 # image.convert('1')
    # threshold = 125
    lookup_table = [0 if i < threshold else 1 for i in range(256)]
    img = img.point(lookup_table, '1')
    return img


# 如果有干扰线,也可采用九宫格去噪,一次不行就两次,然后还可以膨胀腐蚀法
# 九宫格法去噪音点
def denoise(image, pixel_node):
    rows, cols = image.size
    noise_pos = []

    for i in range(1, rows-1):
        for j in range(1, cols-1):
            pixel_around = 0
            for m in range(i-1, i+2):
                for n in range(j-1, j+2):
                    if image.getpixel((m,n)) != 1:
                        pixel_around +=1
            if pixel_around <= pixel_node:
                noise_pos.append((i,j))
    for pos in noise_pos:
        image.putpixel(pos, 1)
    return image

 この時点では余談は挟みません。これで終わりです。

 

おすすめ

転載: blog.csdn.net/Cameback_Tang/article/details/126442051