概要
工作之初,我们想利用ocr识别加上现如今火热的ai来制作一款能够便利简化人们在日常工作生活中对图像做一系列操作的软件。
在比对百度、腾讯、合合等三方api,觉得合合的功能最为完善,决定使用合合的api,并使用python代码来搭建后端服务。
整体架构流程
利用python的flask来构建轻量级的后端服务。
技术细节
接下来以通用文字识别的调用代码为例,搭建后端框架。
-
class CommonOcr(object): def __init__(self, img_path): # 请登录后前往 “工作台-账号设置-开发者信息” 查看 x-ti-app-id # 示例代码中 x-ti-app-id 非真实数据 self._app_id = get_app_id() # 请登录后前往 “工作台-账号设置-开发者信息” 查看 x-ti-secret-code # 示例代码中 x-ti-secret-code 非真实数据 self._secret_code = get_secret_code() self._img_path = img_path def recognize(self): # 通用文字识别 url = 'https://api.textin.com/ai/service/v2/recognize' head = {} try: image = get_file_content(self._img_path) head['x-ti-app-id'] = self._app_id head['x-ti-secret-code'] = self._secret_code result = requests.post(url, data=image, headers=head) # print(type(result.text)) # 解析JSON数据 data = json.loads(result.text) # 提取result中的text内容 texts = [line['text'] for line in data['result']['lines']] return texts # 返回值形如 ['NEW', 'Textin', '市场/价格', '体验中心'] 的list except Exception as e: print(e) return 0
查看合合api官方文档使用相应的api调用代码,在此基础上可以修改返回值以方便操作。
-
@app.route('/recognize', methods=['GET']) # 批量文字识别image->文本 def recognize(): try: files = os.listdir(modelTempPath) if not files: files = os.listdir(picPath) dirpath = picPath else: dirpath = modelTempPath except Exception as e: return jsonify({'message': 'Error listing input directory', 'error': str(e)}) results = [] for i, filename in enumerate(files): file_path = os.path.join(dirpath, filename) try: common_ocr = CommonOcr(file_path) texts = common_ocr.recognize() if texts: results.append({ 'file_name': str(random.randint(100, 999))+filename, 'texts': texts }) else: print('something went wrong with main/recognize.') except Exception as e: print(f"Error processing file {filename}: {e}") results.append({ 'file_name': filename, 'error': str(e) }) return jsonify({ 'message': 'Files processed successfully', 'results': results })
在sever端代码中设立recognize节点,同时调用相应功能,对调用的返回值进行操作封装成前端所需要的格式。这里的功能是提取图片文字,同时做了枚举操作使其能同时操作处理多个图片,并将处理后的返回值加入到我们需要的json中。
另一种功能是传入图片并返回处理后图片的功能,以去水印为例。
-
def watermark_remove(self): # 图像水印去除 url = 'https://api.textin.com/ai/service/v1/image/watermark_remove' head = {} try: image = get_file_content(self._img_path) head['x-ti-app-id'] = self._app_id head['x-ti-secret-code'] = self._secret_code result = requests.post(url, data=image, headers=head) # 解析JSON数据 result = (json.loads(result.text).get( 'result', {}).get('image', None)) return result except Exception as e: print(e) return 0
同样的,结合官方文档进行api调用,在ocr对象中添加相应的方法。
-
@app.route('/waterMarkRemove', methods=['GET']) # 去水印image->image def waterMarkRemove(): results = [] try: files = os.listdir(modelTempPath) if not files: files = os.listdir(picPath) # 列出目录下所有文件 dirpath = picPath else: dirpath = modelTempPath except Exception as e: return jsonify({'message': 'Error listing input directory', 'error': str(e)}) for i, filename in enumerate(files): file_path = os.path.join(dirpath, filename) try: common_ocr = CommonOcr(file_path) res = common_ocr.watermark_remove() if res: results.append({ 'file_name': str(random.randint(100, 999))+filename, 'res': res }) else: print('something went wrong with all/waterMarkRemove.') except Exception as e: print(f"Error processing file {filename}: {e}") results.append({ 'file_name': str(random.randint(100, 999))+filename, 'error': str(e) }) return jsonify({ 'message': 'Files processed successfully', 'results': results })
在sever端代码中添加相应节点,枚举法进行批量操作,将得到的结果加入到json中。
还有一种功能是传入文件,并将文件转成图片的形式,例如word转img。
-
def word_to_img(self): # Word转图片 url = 'https://api.textin.com/ai/service/v1/file-convert/word-to-image' head = {} try: image = get_file_content(self._img_path) head['x-ti-app-id'] = self._app_id head['x-ti-secret-code'] = self._secret_code result = requests.post(url, data=image, headers=head) result = (json.loads(result.text).get( 'result', {})) return result except Exception as e: print(e) return 0
同理,查看官方文档将api调用方法加入到ocr对象中。
-
@app.route('/word_to_img', methods=['GET']) # word转image def word_to_img(): results = [] try: files = os.listdir(modelTempPath) if not files: files = os.listdir(wordPath) # 列出目录下所有文件 dirpath = wordPath else: dirpath = modelTempPath except Exception as e: return jsonify({'message': 'Error listing input directory', 'error': str(e)}) for i, filename in enumerate(files): file_path = os.path.join(dirpath, filename) try: common_ocr = CommonOcr(file_path) res = common_ocr.word_to_img() if res: zip_bytes = base64.b64decode(res) # 使用io.BytesIO创建一个类文件对象 zip_stream = io.BytesIO(zip_bytes) # 使用zipfile读取类文件对象 with zipfile.ZipFile(zip_stream, 'r') as zip_ref: zip_ref.extractall(tempPath) base64_files = get_files_base64_andRemove(tempPath) for item in base64_files: results.append({ 'file_name': str(random.randint(100, 999))+item[0]+'.jpg', 'res': item[1] }) else: print('something went wrong with all/word_to_img.') except Exception as e: print(f"Error processing file {filename}: {e}") results.append({ 'file_name': str(random.randint(100, 999))+filename, 'error': str(e) }) return jsonify({ 'message': 'Files processed successfully', 'results': results })
将相应节点加到sever端中,枚举法进行批量操作。注意,由于这里api调用返回的是base64编码,我们需要对该base64编码做相应的解码操作才能得到我们想要的内容。由于可能是多份文件,解决思路是将三方返回的base64解码成zip文件,提取zip,得到相应图片后转base64传给前端。
-
def get_files_base64_andRemove(directory): # 从zip提取文件,转base64,并删除源文件 base64_files = [] for root, dirs, files in os.walk(directory): for file in files: file_path = os.path.join(root, file) with open(file_path, 'rb') as file_to_encode: file_content = file_to_encode.read() base64_content = base64.b64encode(file_content).decode('utf-8') base64_files.append((file, base64_content)) if os.path.exists(file_path): os.remove(file_path) return base64_files
在这里加一个函数,该功能就是提取zip,并转base64编码。在以上的节点加入该函数实现提取转码功能。
小结
合合信息的api接口调用着实方便,而且新人所有功能可以有1000次的免费额度,官方文档非常详细,有不同平台的调用代码,并且有很直观的在线调用功能,体验中心有着傻瓜式交互功能,让第一次接触的小白容易上手。