make words counter for image with the help of paddlehub model
目的
作文字数统计。
技术依赖
https://aistudio.baidu.com/aistudio/projectdetail/1725688?forkThirdPart=1
光学字符识别(Optical Character Recognition, OCR)是指对文本材料的图像文件进行分析识别处理,以获取文字和版本信息的过程。也就是说将图象中的文字进行识别,并返回文本形式的内容。例如(该预测效果基于PaddleHub一键OCR中文识别效果展示):
PaddleHub现已开源OCR文字识别的预训练模型
移动端的超轻量模型:仅有8.6M,chinese_ocr_db_crnn_mobile。
服务器端的精度更高模型:识别精度更高,chinese_ocr_db_crnn_server。
import paddlehub as hub ocr = hub.Module(name="chinese_ocr_db_crnn_mobile") #加载移动端预训练模型 import cv2 np_images =[cv2.imread(image_path) for image_path in test_img_path] #读取测试文件夹test.txt中的照片路径 results = ocr.recognize_text( images=np_images, #图片数据,ndarray.shape 为 [H, W, C],BGR格式; use_gpu=False, #是否使用 GPU;若使用GPU,请先设置CUDA_VISIBLE_DEVICES环境变量 output_dir='ocr_result', #图片的保存路径,默认设为 ocr_result; visualization=True, #是否将识别结果保存为图片文件; box_thresh=0.5, #检测文本框置信度的阈值; text_thresh=0.5) #识别中文文本置信度的阈值; for result in results: data = result['data'] save_path = result['save_path'] for infomation in data: print(infomation['text'], infomation['confidence'], infomation['text_box_position'])
Code
https://github.com/fanqingsong/writing_words_counter
# !pip install paddlehub --upgrade -i https://pypi.tuna.tsinghua.edu.cn/simple #由于PaddleHub升级比较快,建议大家直接升级到最新版本的PaddleHub,无需指定版本升级 # !pip install shapely -i https://pypi.tuna.tsinghua.edu.cn/simple #该Module依赖于第三方库shapely,使用该Module之前,请先安装shapely # !pip install pyclipper -i https://pypi.tuna.tsinghua.edu.cn/simple #该Module依赖于第三方库pyclipper,使用该Module之前,请先安装pyclipper # import paddlehub as hub import cv2 class WordsCounter: def __init__(self): self._ocr = hub.Module(name="chinese_ocr_db_crnn_server") self._workspace_path = "./workspace" self._snapshot_path = f"{self._workspace_path}/snapshot" def _get_ocr_results_from_image(self, image_path): img_data = cv2.imread(image_path) ocr_results = self._ocr.recognize_text(images=[img_data]) print(ocr_results) return ocr_results def _get_text_from_ocr_results(self, ocr_results): all_text = [] for one_result in ocr_results: data = one_result["data"] for one_info in data: one_text = one_info["text"] all_text.append(one_text) # add empty line before storing next image text all_text.append("") all_text = "\r\n".join(all_text) print("----- all text --------") print(all_text) return all_text def _count_words_in_text(self, text: str): pure_text = text.replace("\r\n", "") return len(pure_text) def count_words_for_one_image(self, image_path): ocr_results = self._get_ocr_results_from_image(image_path) text = self._get_text_from_ocr_results(ocr_results) num = self._count_words_in_text(text) print(f"num = {num}") return num def watch_camera(self): cap = cv2.VideoCapture(0) index = 0 while True: ret, frame = cap.read() print(f"capture ret={ret} frame={frame}") if ret: cv2.imwrite(f'{self._snapshot_path}/{index}.jpg', frame) print(type(frame)) print(frame.shape) index += 1 else: break cap.release() print('video split finish, all %d frame' % index) if __name__ == "__main__": # for test one_writing_path = './workspace/one_student_writing.jpeg' words_counter = WordsCounter() #words_counter.watch_camera() # words_counter.count_words_for_one_image(one_writing_path)
output
root@XXX:~/win/mine/writing_words_counter# python app.py
WARNING: Logging before InitGoogleLogging() is written to STDERR
W0329 15:42:58.143852 11317 default_variables.cpp:429] Fail to open /proc/self/io: No such file or directory [2]
[2021-03-29 15:43:10,312] [ WARNING] - The _initialize method in HubModule will soon be deprecated, you can use the __init__() to handle the initialization of the object
W0329 15:43:10.332775 11317 analysis_predictor.cc:1145] Deprecated. Please use CreatePredictor instead.
[2021-03-29 15:43:11,196] [ WARNING] - The _initialize method in HubModule will soon be deprecated, you can use the __init__() to handle the initialization of the object
[{'save_path': '', 'data': [{'text': '4月27日星其月三日春', 'confidence': 0.9224098324775696, 'text_box_position': [[69, 23], [378, 17], [379, 53], [70, 59]]}, {'text': '我的理想', 'confidence': 0.9905031323432922, 'text_box_position': [[210, 56], [349, 54], [349, 88], [210, 90]]}, {'text': '我的理想是做一地鸡尾坨', 'confidence': 0.7857702374458313, 'text_box_position': [[103, 97], [526, 91], [526, 123], [103, 130]]}, {'text': '又大又奥的鸡星,首先去息死我的同学', 'confidence': 0.8190749287605286, 'text_box_position': [[49, 130], [536, 131], [536, 165], [49, 164]]}, {'text': '韦友善,因为他欠我5毛钱,一直不还', 'confidence': 0.9070485830307007, 'text_box_position': [[51, 170], [526, 164], [526, 197], [51, 204]]}, {'text': '上课还享我本子乱画,我还要皇死数', 'confidence': 0.8423854112625122, 'text_box_position': [[50, 207], [527, 203], [527, 235], [50, 240]]}, {'text': '学老师,这个学其我每次考试都不皮格', 'confidence': 0.9008817076683044, 'text_box_position': [[52, 243], [540, 237], [540, 273], [52, 279]]}, {'text': '其实,我能友格的,但是,他不要我抄', 'confidence': 0.953991174697876, 'text_box_position': [[54, 280], [530, 277], [530, 312], [54, 316]]}, {'text': '同学的,我还要臭死语文老师,尽餐她', 'confidence': 0.8289876580238342, 'text_box_position': [[52, 318], [531, 309], [531, 346], [52, 355]]}, {'text': '长得很漂亮,谁叫女也总批评我不会写日记', 'confidence': 0.9028255343437195, 'text_box_position': [[53, 353], [540, 349], [540, 382], [53, 385]]}, {'text': '说我什么都了吗进来,难道,我这样的', 'confidence': 0.8958162069320679, 'text_box_position': [[51, 388], [545, 382], [545, 419], [51, 425]]}, {'text': '日把还不锈经吗', 'confidence': 0.5827445387840271, 'text_box_position': [[59, 427], [291, 429], [291, 448], [59, 446]]}]}]
----- all text --------
4月27日星其月三日春
我的理想
我的理想是做一地鸡尾坨
又大又奥的鸡星,首先去息死我的同学
韦友善,因为他欠我5毛钱,一直不还
上课还享我本子乱画,我还要皇死数
学老师,这个学其我每次考试都不皮格
其实,我能友格的,但是,他不要我抄
同学的,我还要臭死语文老师,尽餐她
长得很漂亮,谁叫女也总批评我不会写日记
说我什么都了吗进来,难道,我这样的
日把还不锈经吗
num = 170
原图
Next Step
图像使用摄像头拍摄,实现实时监测字数。