├── requirements.txt ├── img.png ├── test.jpg ├── bg_image.png ├── test_calc.png ├── target_image.png ├── Dockerfile ├── Readme.md ├── demo_api_bytes ├── demo_api_b64 └── ocr_server.py /requirements.txt: -------------------------------------------------------------------------------- 1 | ddddocr 2 | flask 3 | -------------------------------------------------------------------------------- /img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CHERWING/CHERWIN_OCR/HEAD/img.png -------------------------------------------------------------------------------- /test.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CHERWING/CHERWIN_OCR/HEAD/test.jpg -------------------------------------------------------------------------------- /bg_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CHERWING/CHERWIN_OCR/HEAD/bg_image.png -------------------------------------------------------------------------------- /test_calc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CHERWING/CHERWIN_OCR/HEAD/test_calc.png -------------------------------------------------------------------------------- /target_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CHERWING/CHERWIN_OCR/HEAD/target_image.png -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # 使用更小的python基础镜像 2 | FROM python:3.10-slim 3 | 4 | # 设置工作目录 5 | WORKDIR /app 6 | 7 | # 将代码添加到镜像中 8 | COPY . /app 9 | 10 | # 设置 pip 源为阿里云 删除下方#号开启 11 | # RUN pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ 12 | 13 | # 安装所需的包,然后清理缓存 14 | RUN pip install --no-cache-dir flask ddddocr 15 | 16 | # 暴露端口 17 | EXPOSE 3721 18 | 19 | # 设置启动命令 20 | CMD ["python", "ocr_server.py"] 21 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | #

✨CHERWIN_OCR使用指南 ✨

2 | 3 | 4 | # 使用 ddddocr 的最简 API 搭建项目,支持 Docker 5 | 6 | 本项目地址:[ddddocr](https://github.com/CHERWING/CHERWIN_OCR) 7 | 8 | ddddocr项目地址:[ddddocr](https://github.com/sml2h3/ddddocr) 9 | 10 | 11 | **建议python版本3.10 64位** 12 | 13 | # 运行方式 14 | 15 | ## 最简单运行方式 16 | 17 | ```shell 18 | # 安装依赖 19 | pip install -r requirements.txt -i https://pypi.douban.com/simple 20 | 21 | # 最简单运行方式 22 | python ocr_server.py 23 | 24 | ``` 25 | 26 | ## docker运行方式 27 | 28 | ```shell 29 | git clone https://github.com:CHERWING/CHERWIN_OCR.git 30 | # docker怎么安装?百度吧 31 | 32 | cd CHERWIN_OCR 33 | 34 | # 编译镜像 35 | docker build -t cherwin_ocr . 36 | 37 | # 运行镜像 38 | docker run -p 3721:3721 -v /volume1/docker/ocr:/app --name cherwin_ocr cherwin_ocr 39 | 40 | ``` 41 | 42 | # 接口 43 | 44 | **具体请看demo_api_b64.py或demo_api_bytes.py文件** 45 | 46 | 正确返回示例: 47 | ``` 48 | {'result': 284} 49 | {'result': 'iepv'} 50 | {'result': [[50, 7, 67, 24]]} 51 | {'result': 3} 52 | ``` 53 | 54 | -------------------------------------------------------------------------------- /demo_api_bytes: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import base64 4 | # api_host = 'http://192.168.10.160:3723' 5 | api_host = 'http://localhost:3721' 6 | # 二进制提交示例 7 | 8 | # 滑块验证码识别示例 9 | with open('target_image.png', 'rb') as f: 10 | sliding_image = f.read() 11 | with open('bg_image.png', 'rb') as f: 12 | back_image = f.read() 13 | 14 | data = {'slidingImage': base64.b64encode(sliding_image).decode(), 'backImage': base64.b64encode(back_image).decode(), 'simpleTarget': True} 15 | response = requests.post(f'{api_host}/capcode', data=json.dumps(data), headers={'Content-Type': 'application/json'}) 16 | print(response.json()) 17 | 18 | # OCR识别示例 19 | with open('img.png', 'rb') as f: 20 | image = f.read() 21 | data = {'image': base64.b64encode(image).decode()} 22 | response = requests.post(f'{api_host}/classification', data=json.dumps(data), headers={'Content-Type': 'application/json'}) 23 | print(response.json()) 24 | 25 | # 检测示例 26 | with open('test.jpg', 'rb') as f: 27 | image = f.read() 28 | data = {'image': base64.b64encode(image).decode()} 29 | response = requests.post(f'{api_host}/detection', data=json.dumps(data), headers={'Content-Type': 'application/json'}) 30 | print(response.json()) 31 | 32 | # 计算示例 33 | with open('test_calc.png', 'rb') as f: 34 | image = f.read() 35 | data = {'image': base64.b64encode(image).decode()} 36 | response = requests.post(f'{api_host}/calculate', data=json.dumps(data), headers={'Content-Type': 'application/json'}) 37 | print(response.json()) 38 | -------------------------------------------------------------------------------- /demo_api_b64: -------------------------------------------------------------------------------- 1 | import ddddocr 2 | import requests 3 | import json 4 | import base64 5 | #base64请求示例 6 | 7 | # api_host = 'http://192.168.10.160:3722' 8 | api_host = 'http://localhost:3721' 9 | # 滑块验证码识别示例 10 | with open('target_image.png', 'rb') as f: 11 | sliding_image = base64.b64encode(f.read()).decode() 12 | with open('bg_image.png', 'rb') as f: 13 | back_image = base64.b64encode(f.read()).decode() 14 | 15 | data = {'slidingImage': sliding_image, 'backImage': back_image, 'simpleTarget': True} 16 | response = requests.post(f'{api_host}/capcode', data=json.dumps(data), headers={'Content-Type': 'application/json'}) 17 | print(response.json()) 18 | 19 | # OCR识别示例 20 | with open('img.png', 'rb') as f: 21 | image = base64.b64encode(f.read()).decode() 22 | data = {'image': image} 23 | response = requests.post(f'{api_host}/classification', data=json.dumps(data), headers={'Content-Type': 'application/json'}) 24 | print(response.json()) 25 | 26 | # 检测示例 27 | with open('test.jpg', 'rb') as f: 28 | image = base64.b64encode(f.read()).decode() 29 | data = {'image': image} 30 | response = requests.post(f'{api_host}/detection', data=json.dumps(data), headers={'Content-Type': 'application/json'}) 31 | print(response.json()) 32 | 33 | 34 | # 计算示例 35 | with open('test_calc.png', 'rb') as f: 36 | image = base64.b64encode(f.read()).decode() 37 | data = {'image': image} 38 | response = requests.post(f'{api_host}/calculate', data=json.dumps(data), headers={'Content-Type': 'application/json'}) 39 | print(response.json()) 40 | -------------------------------------------------------------------------------- /ocr_server.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, request, jsonify 2 | import ddddocr 3 | import logging 4 | import re 5 | import base64 6 | 7 | app = Flask(__name__) 8 | 9 | # 设置日志记录 10 | logging.basicConfig(filename='app.log', level=logging.DEBUG, format='%(asctime)s %(levelname)s %(name)s %(threadName)s : %(message)s') 11 | 12 | class CAPTCHA: 13 | def __init__(self): 14 | # 初始化两个识别器,一个用于OCR和滑块,一个用于检测 15 | self.ocr = ddddocr.DdddOcr() 16 | self.det = ddddocr.DdddOcr(det=True) 17 | 18 | # 滑块验证码识别函数,接收两个图像和一个simple_target参数,返回滑块的目标位置 19 | def capcode(self, sliding_image, back_image, simple_target): 20 | try: 21 | sliding_bytes = self.get_image_bytes(sliding_image) 22 | back_bytes = self.get_image_bytes(back_image) 23 | res = self.ocr.slide_match(sliding_bytes, back_bytes, simple_target=simple_target) 24 | return res['target'][0] 25 | except Exception as e: 26 | app.logger.error(f"出现错误: {e}") 27 | return None 28 | 29 | # OCR识别函数,接收一个图像和一个png_fix参数,返回OCR识别结果 30 | def classification(self, image): 31 | try: 32 | image_bytes = self.get_image_bytes(image) 33 | res = self.ocr.classification(image_bytes) 34 | return res 35 | except Exception as e: 36 | app.logger.error(f"出现错误: {e}") 37 | return None 38 | 39 | # 检测函数,接收一个图像,返回图像上的所有文字或图标的坐标位置 40 | def detection(self, image): 41 | try: 42 | image_bytes = self.get_image_bytes(image) 43 | poses = self.det.detection(image_bytes) 44 | return poses 45 | except Exception as e: 46 | app.logger.error(f"出现错误: {e}") 47 | return None 48 | 49 | # 计算类验证码处理函数,接收一个图像,返回计算结果 50 | def calculate(self, image): 51 | try: 52 | image_bytes = self.get_image_bytes(image) 53 | expression = self.ocr.classification(image_bytes) 54 | expression = re.sub('=.*$', '', expression) 55 | expression = re.sub('[^0-9+\-*/()]', '', expression) 56 | result = eval(expression) 57 | return result 58 | except Exception as e: 59 | app.logger.error(f"出现错误: {e}") 60 | app.logger.error(f"错误类型: {type(e)}") 61 | app.logger.error(f"错误详细信息: {e.args}") 62 | return None 63 | 64 | # 辅助函数,根据输入类型获取图像字节流 65 | def get_image_bytes(self, image_data): 66 | if isinstance(image_data, bytes): 67 | return image_data 68 | elif isinstance(image_data, str): 69 | return base64.b64decode(image_data) 70 | elif hasattr(image_data, 'read'): 71 | return image_data.read() 72 | else: 73 | raise ValueError("Unsupported image data type") 74 | 75 | # 初始化CAPTCHA类 76 | captcha = CAPTCHA() 77 | 78 | # 滑块验证码识别路由,接收POST请求,返回滑块的目标位置 79 | @app.route('/capcode', methods=['POST']) 80 | def capcode(): 81 | try: 82 | data = request.get_json() 83 | sliding_image = data['slidingImage'] 84 | back_image = data['backImage'] 85 | simple_target = data.get('simpleTarget', True) 86 | result = captcha.capcode(sliding_image, back_image, simple_target) 87 | if result is None: 88 | app.logger.error('处理过程中出现错误.') 89 | return jsonify({'error': '处理过程中出现错误.'}), 500 90 | return jsonify({'result': result}) 91 | except Exception as e: 92 | app.logger.error(f"出现错误: {e}") 93 | return jsonify({'error': f"出现错误: {e}"}), 400 94 | 95 | # OCR识别路由,接收POST请求,返回OCR识别结果 96 | @app.route('/classification', methods=['POST']) 97 | def classification(): 98 | try: 99 | data = request.get_json() 100 | image = data['image'] 101 | result = captcha.classification(image) 102 | if result is None: 103 | app.logger.error('处理过程中出现错误.') 104 | return jsonify({'error': '处理过程中出现错误.'}), 500 105 | return jsonify({'result': result}) 106 | except Exception as e: 107 | app.logger.error(f"出现错误: {e}") 108 | return jsonify({'error': f"出现错误: {e}"}), 400 109 | 110 | # 检测路由,接收POST请求,返回图像上的所有文字或图标的坐标位置 111 | @app.route('/detection', methods=['POST']) 112 | def detection(): 113 | try: 114 | data = request.get_json() 115 | image = data['image'] 116 | result = captcha.detection(image) 117 | if result is None: 118 | app.logger.error('处理过程中出现错误.') 119 | return jsonify({'error': '处理过程中出现错误.'}), 500 120 | return jsonify({'result': result}) 121 | except Exception as e: 122 | app.logger.error(f"出现错误: {e}") 123 | return jsonify({'error': f"出现错误: {e}"}), 400 124 | 125 | # 计算类验证码处理路由,接收POST请求,返回计算结果 126 | @app.route('/calculate', methods=['POST']) 127 | def calculate(): 128 | try: 129 | data = request.get_json() 130 | image = data['image'] 131 | result = captcha.calculate(image) 132 | if result is None: 133 | app.logger.error('处理过程中出现错误.') 134 | return jsonify({'error': '处理过程中出现错误.'}), 500 135 | return jsonify({'result': result}) 136 | except Exception as e: 137 | app.logger.error(f"出现错误: {e}") 138 | return jsonify({'error': f"出现错误: {e}"}), 400 139 | 140 | # 基本运行状态路由,返回一个表示服务器正常运行的消息 141 | @app.route('/') 142 | def hello_world(): 143 | return 'API运行成功!' 144 | 145 | # 启动Flask应用 146 | if __name__ == '__main__': 147 | app.run(host='0.0.0.0', debug=True, port=3721) 148 | --------------------------------------------------------------------------------