前回は、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
この時点では余談は挟みません。これで終わりです。