Rould-Bot commited on
Commit
df35553
·
verified ·
1 Parent(s): 28f3881

Create server.py

Browse files
Files changed (1) hide show
  1. server.py +278 -0
server.py ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from io import BytesIO
2
+
3
+ import cv2
4
+ import numpy as np
5
+ import requests
6
+ from PIL import Image
7
+ from flask import Flask, request, jsonify
8
+ import ddddocr
9
+ import logging
10
+ import re
11
+ import base64
12
+
13
+ app = Flask(__name__)
14
+
15
+ # 设置日志记录
16
+ logging.basicConfig(filename='app.log', level=logging.DEBUG,
17
+ format='%(asctime)s %(levelname)s %(name)s %(threadName)s : %(message)s')
18
+
19
+
20
+ def get_image_bytes(image_data):
21
+ if isinstance(image_data, bytes):
22
+ return image_data
23
+ elif image_data.startswith('http'):
24
+ response = requests.get(image_data, verify=False)
25
+ response.raise_for_status()
26
+ return response.content
27
+ elif isinstance(image_data, str):
28
+ return base64.b64decode(image_data)
29
+ else:
30
+ raise ValueError("Unsupported image data type")
31
+
32
+ def image_to_base64(image, format='PNG'):
33
+ buffered = BytesIO()
34
+ image.save(buffered, format=format)
35
+ img_str = base64.b64encode(buffered.getvalue()).decode('utf-8')
36
+ return img_str
37
+
38
+ class CAPTCHA:
39
+ def __init__(self):
40
+ # 初始化两个识别器,一个用于OCR和滑块,一个用于检测
41
+ self.ocr = ddddocr.DdddOcr()
42
+ self.det = ddddocr.DdddOcr(det=True)
43
+
44
+ # 滑块验证码识别函数,接收两个图像和一个simple_target参数,返回滑块的目标位置
45
+ def capcode(self, sliding_image, back_image, simple_target):
46
+ try:
47
+ sliding_bytes = get_image_bytes(sliding_image)
48
+ back_bytes = get_image_bytes(back_image)
49
+ res = self.ocr.slide_match(sliding_bytes, back_bytes, simple_target=simple_target)
50
+ return res['target'][0]
51
+ except Exception as e:
52
+ app.logger.error(f"出现错误: {e}")
53
+ return None
54
+
55
+ # 滑块对比函数,接收两个图像,返回滑块的目标位置
56
+ def slideComparison(self, sliding_image, back_image):
57
+ try:
58
+ sliding_bytes = get_image_bytes(sliding_image)
59
+ back_bytes = get_image_bytes(back_image)
60
+ res = self.ocr.slide_comparison(sliding_bytes, back_bytes)
61
+ return res['target'][0]
62
+ except Exception as e:
63
+ app.logger.error(f"出现错误: {e}")
64
+ return None
65
+
66
+ # OCR识别函数,接收一个图像和一个png_fix参数,返回OCR识别结果
67
+ def classification(self, image):
68
+ try:
69
+ image_bytes = get_image_bytes(image)
70
+ res = self.ocr.classification(image_bytes)
71
+ return res
72
+ except Exception as e:
73
+ app.logger.error(f"出现错误: {e}")
74
+ return None
75
+
76
+ # 检测函数,接收一个图像,返回图像上的所有文字或图标的坐标位置
77
+ def detection(self, image):
78
+ try:
79
+ image_bytes = get_image_bytes(image)
80
+ poses = self.det.detection(image_bytes)
81
+ return poses
82
+ except Exception as e:
83
+ app.logger.error(f"出现错误: {e}")
84
+ return None
85
+
86
+ # 计算类验证码处理函数,接收一个图像,返回计算结果
87
+ def calculate(self, image):
88
+ try:
89
+ image_bytes = get_image_bytes(image)
90
+ expression = self.ocr.classification(image_bytes)
91
+ expression = re.sub('=.*$', '', expression)
92
+ expression = re.sub('[^0-9+\-*/()]', '', expression)
93
+ result = eval(expression)
94
+ return result
95
+ except Exception as e:
96
+ app.logger.error(f"出现错误: {e}")
97
+ app.logger.error(f"错误类型: {type(e)}")
98
+ app.logger.error(f"错误详细信息: {e.args}")
99
+ return None
100
+
101
+
102
+ # 图片分割处理函数,接收一个图像,返回计算结果
103
+ def crop(self, image, y_coordinate):
104
+ try:
105
+ image = Image.open(BytesIO(requests.get(image).content))
106
+ # 分割图片
107
+ upper_half = image.crop((0, 0, image.width, y_coordinate))
108
+ middle_half = image.crop((0, y_coordinate, image.width, y_coordinate*2))
109
+ lower_half = image.crop((0, y_coordinate*2, image.width, image.height))
110
+ # 将分割后的图片转换为Base64编码
111
+ slidingImage = image_to_base64(upper_half)
112
+ backImage = image_to_base64(lower_half)
113
+ return jsonify({'slidingImage': slidingImage, 'backImage': backImage})
114
+ except Exception as e:
115
+ app.logger.error(f"出现错误: {e}")
116
+ app.logger.error(f"错误类型: {type(e)}")
117
+ app.logger.error(f"错误详细信息: {e.args}")
118
+ return None
119
+
120
+ # 点选处理函数,接收一个图像,返回计算结果
121
+ def select(self, image):
122
+ try:
123
+ image_bytes = get_image_bytes(image)
124
+ # 将二进制数据转换为 numpy 数组
125
+ image_array = np.frombuffer(image_bytes, dtype=np.uint8)
126
+ # 使用 cv2.imdecode 将 numpy 数组解码为图像
127
+ im = cv2.imdecode(image_array, cv2.IMREAD_COLOR)
128
+ bboxes = self.det.detection(image_bytes)
129
+ json = []
130
+ for bbox in bboxes:
131
+ x1, y1, x2, y2 = bbox
132
+ x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
133
+ cropped_image = im[y1:y2, x1:x2]
134
+ # 将图像编码为内存中的字节流(如png格式)
135
+ _, buffer = cv2.imencode('.png', cropped_image)
136
+ # 将字节流转换为 Base64 编码
137
+ image_base64 = base64.b64encode(buffer).decode('utf-8')
138
+ result = self.ocr.classification(image_base64)
139
+ json.append({result: bbox})
140
+
141
+ return json
142
+ except Exception as e:
143
+ app.logger.error(f"出现错误: {e}")
144
+ app.logger.error(f"错误类型: {type(e)}")
145
+ app.logger.error(f"错误详细信息: {e.args}")
146
+ return None
147
+
148
+ # 辅助函数,根据输入类型获取图像字节流
149
+
150
+
151
+ # 初始化CAPTCHA类
152
+ captcha = CAPTCHA()
153
+
154
+
155
+ # 滑块验证码识别路由,接收POST请求,返回滑块的目标位置
156
+ @app.route('/capcode', methods=['POST'])
157
+ def capcode():
158
+ try:
159
+ data = request.get_json()
160
+ sliding_image = data['slidingImage']
161
+ back_image = data['backImage']
162
+ simple_target = data.get('simpleTarget', True)
163
+ result = captcha.capcode(sliding_image, back_image, simple_target)
164
+ if result is None:
165
+ app.logger.error('处理过程中出现错误.')
166
+ return jsonify({'error': '处理过程中出现错误.'}), 500
167
+ return jsonify({'result': result})
168
+ except Exception as e:
169
+ app.logger.error(f"出现错误: {e}")
170
+ return jsonify({'error': f"出现错误: {e}"}), 400
171
+
172
+
173
+ # 滑块对比路由,接收POST请求,返回滑块的目标位置
174
+ @app.route('/slideComparison', methods=['POST'])
175
+ def slideComparison():
176
+ try:
177
+ data = request.get_json()
178
+ sliding_image = data['slidingImage']
179
+ back_image = data['backImage']
180
+
181
+ result = captcha.slideComparison(sliding_image, back_image)
182
+ if result is None:
183
+ app.logger.error('处理过程中出现错误.')
184
+ return jsonify({'error': '处理过程中出现错误.'}), 500
185
+ return jsonify({'result': result})
186
+ except Exception as e:
187
+ app.logger.error(f"出现错误: {e}")
188
+ return jsonify({'error': f"出现错误: {e}"}), 400
189
+
190
+
191
+ # OCR识别路由,接收POST请求,返回OCR识别结果
192
+ @app.route('/classification', methods=['POST'])
193
+ def classification():
194
+ try:
195
+ data = request.get_json()
196
+ image = data['image']
197
+ result = captcha.classification(image)
198
+ if result is None:
199
+ app.logger.error('处理过程中出现错误.')
200
+ return jsonify({'error': '处理过程中出现错误.'}), 500
201
+ return jsonify({'result': result})
202
+ except Exception as e:
203
+ app.logger.error(f"出现错误: {e}")
204
+ return jsonify({'error': f"出现错误: {e}"}), 400
205
+
206
+
207
+ # 检测路由,接收POST请求,返回图像上的所有文字或图标的坐标位置
208
+ @app.route('/detection', methods=['POST'])
209
+ def detection():
210
+ try:
211
+ data = request.get_json()
212
+ image = data['image']
213
+ result = captcha.detection(image)
214
+ if result is None:
215
+ app.logger.error('处理过程中出现错误.')
216
+ return jsonify({'error': '处理过程中出现错误.'}), 500
217
+ return jsonify({'result': result})
218
+ except Exception as e:
219
+ app.logger.error(f"出现错误: {e}")
220
+ return jsonify({'error': f"出现错误: {e}"}), 400
221
+
222
+
223
+ # 计算类验证码处理路由,接收POST请求,返回计算结果
224
+ @app.route('/calculate', methods=['POST'])
225
+ def calculate():
226
+ try:
227
+ data = request.get_json()
228
+ image = data['image']
229
+ result = captcha.calculate(image)
230
+ if result is None:
231
+ app.logger.error('处理过程中出现错误.')
232
+ return jsonify({'error': '处理过程中出现错误.'}), 500
233
+ return jsonify({'result': result})
234
+ except Exception as e:
235
+ app.logger.error(f"出现错误: {e}")
236
+ return jsonify({'error': f"出现错误: {e}"}), 400
237
+
238
+ # 图片分割路由,接收POST请求,返回计算结果
239
+ @app.route('/crop', methods=['POST'])
240
+ def crop():
241
+ try:
242
+ data = request.get_json()
243
+ image = data['image']
244
+ y_coordinate = data['y_coordinate']
245
+ result = captcha.crop(image, y_coordinate)
246
+ if result is None:
247
+ app.logger.error('处理过程中出现错误.')
248
+ return jsonify({'error': '处理过程中出现错误.'}), 500
249
+ return result
250
+ except Exception as e:
251
+ app.logger.error(f"出现错误: {e}")
252
+ return jsonify({'error': f"出现错误: {e}"}), 400
253
+
254
+ # 点选路由,接收POST请求,返回计算结果
255
+ @app.route('/select', methods=['POST'])
256
+ def select():
257
+ try:
258
+ data = request.get_json()
259
+ image = data['image']
260
+
261
+ result = captcha.select(image)
262
+ if result is None:
263
+ app.logger.error('处理过程中出现错误.')
264
+ return jsonify({'error': '处理过程中出现错误.'}), 500
265
+ return result
266
+ except Exception as e:
267
+ app.logger.error(f"出现错误: {e}")
268
+ return jsonify({'error': f"出现错误: {e}"}), 400
269
+
270
+ # 基本运行状态路由,返回一个表示服务器正常运行的消息
271
+ @app.route('/')
272
+ def hello_world():
273
+ return 'API运行成功!'
274
+
275
+
276
+ # 启动Flask应用
277
+ if __name__ == '__main__':
278
+ app.run(host='::', threaded=True, debug=True, port=7777)