点击上方“小白学视觉”,选择加"星标"或“置顶”
重磅干货,第一时间送达
收集数据
首先,我们要做的第一件事是创建一个简单的数据集,这样我们就可以测试我们工作流程的每一部分。理想情况下,我们的数据集将包含各种易读性和时间段的扫描文档,以及每个文档所属的高级主题。我找不到具有这些精确规格的数据集,所以我开始构建自己的数据集。我决定的高层次话题是政府、信件、吸烟和专利,随机的选择这些主要是因为每个地区都有各种各样的扫描文件。
我从这些来源中的每一个中挑选了 20 个左右的大小合适的文档,并将它们放入由主题定义的单独文件夹中。
经过将近一整天的搜索和编目所有图像后,我们将它们全部调整为 600x800 并将它们转换为 PNG 格式。
简单的调整大小和转换脚本如下:
from PIL import Image
img_folder = r'F:\Data\Imagery\OCR' # Folder containing topic folders (i.e "News", "Letters" ..etc.)
for subfol in os.listdir(img_folder): # For each of the topic folders
sfpath = os.path.join(img_folder, subfol)
for imgfile in os.listdir(sfpath): # Get all images in the topic
imgpath = os.path.join(sfpath, imgfile)
img = Image.open(imgpath) # Read in the image with Pillow
img = img.resize((600,800)) # Resize the image
newip = imgpath[0:-4] + ".png" # Convert to PNG
img.save(newip) # Save
构建OCR管道
光学字符识别是从图像中提取文字的过程。这通常是通过机器学习模型完成的,最常见的是通过包含卷积神经网络的管道来完成。虽然我们可以为我们的应用程序训练自定义 OCR 模型,但它需要更多的训练数据和计算资源。相反,我们将使用出色的 Microsoft 计算机视觉 API,其中包括专门用于 OCR 的特定模块。API 调用将使用图像(作为 PIL 图像)并输出几位信息,包括图像上文本的位置/方向作为以及文本本身。以下函数将接收一个 PIL 图像列表并输出一个大小相等的提取文本列表:
def image_to_text(imglist, ndocs=10):
'''
Take in a list of PIL images and return a list of extracted text using OCR
'''
headers = {
# Request headers
'Content-Type': 'application/octet-stream',
'Ocp-Apim-Subscription-Key': 'YOUR_KEY_HERE',
}
params = urllib.parse.urlencode({
# Request parameters
'language': 'en',
'detectOrientation ': 'true',
})
outtext = []
docnum = 0
for cropped_image in imglist:
print("Processing document -- ", str(docnum))
# Cropped image must have both height and width > 50 px to run Computer Vision API
#if (cropped_image.height or cropped_image.width) < 50:
# cropped_images_ocr.append("N/A")
# continue
ocr_image = cropped_image
imgByteArr = io.BytesIO()
ocr_image.save(imgByteArr, format='PNG')
imgByteArr = imgByteArr.getvalue()
try:
conn = http.client.HTTPSConnection('westus.api.cognitive.microsoft.com')
conn.request("POST", "/vision/v1.0/ocr?%s" % params, imgByteArr, headers)
response = conn.getresponse()
data = json.loads(response.read().decode("utf-8"))
curr_text = []
for r in data['regions']:
for l in r['lines']:
for w in l['words']:
curr_text.append(str(w['text']))
conn.close()
except Exception as e:
print("Could not process image
outtext.append(' '.join(curr_text))
docnum += 1
return(outtext)
后期处理
由于在某些情况下我们可能希望在这里结束我们的工作流程,而不是仅仅将提取的文本作为一个巨大的列表保存在内存中,我们还可以将提取的文本写入与原始输入文件同名的单个 txt 文件中。微软的OCR技术虽然不错,但偶尔也会出错。我们可以使用 SpellChecker 模块减少其中的一些错误,以下脚本接受输入和输出文件夹,读取输入文件夹中的所有扫描文档,使用我们的 OCR 脚本读取它们,运行拼写检查并纠正拼写错误的单词,最后将原始txt文件导出目录。
'''
Read in a list of scanned images (as .png files > 50x50px) and output a set of .txt files containing the text c