├── 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 |
--------------------------------------------------------------------------------