Kenqt commited on
Commit
ea2c6ef
·
verified ·
1 Parent(s): 58ac9e9

Upload 2 files

Browse files
Files changed (2) hide show
  1. captcha_api.py +88 -0
  2. requirements.txt +4 -0
captcha_api.py ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ from flask import Flask, request, jsonify
3
+ import cv2
4
+ import numpy as np
5
+ import base64
6
+ import os
7
+
8
+ app = Flask(__name__)
9
+
10
+ class SimpleCaptchaSolver:
11
+ def preprocess(self, img):
12
+ return cv2.resize(img, (64, 64))
13
+
14
+ def extract_features(self, img):
15
+ gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
16
+ hist = cv2.calcHist([gray], [0], None, [32], [0, 256])
17
+ hist = cv2.normalize(hist, hist).flatten()
18
+ edges = cv2.Canny(gray, 50, 150)
19
+ edge_ratio = np.sum(edges > 0) / edges.size
20
+ return np.append(hist, edge_ratio)
21
+
22
+ def compare(self, feat1, feat2):
23
+ dot = np.dot(feat1, feat2)
24
+ norm1 = np.linalg.norm(feat1)
25
+ norm2 = np.linalg.norm(feat2)
26
+ if norm1 == 0 or norm2 == 0:
27
+ return 0.0
28
+ return dot / (norm1 * norm2)
29
+
30
+ def solve(self, target, options):
31
+ target = self.preprocess(target)
32
+ options = [self.preprocess(opt) for opt in options]
33
+ target_feat = self.extract_features(target)
34
+ scores = []
35
+ for opt in options:
36
+ opt_feat = self.extract_features(opt)
37
+ score = self.compare(target_feat, opt_feat)
38
+ scores.append(float(score))
39
+ best_idx = int(np.argmax(scores))
40
+ return {
41
+ 'answer': best_idx + 1,
42
+ 'confidence': scores[best_idx],
43
+ 'scores': scores
44
+ }
45
+
46
+ solver = SimpleCaptchaSolver()
47
+
48
+ def b64_to_cv2(b64_str):
49
+ img_data = base64.b64decode(b64_str.split(',')[-1])
50
+ img_array = np.frombuffer(img_data, np.uint8)
51
+ return cv2.imdecode(img_array, cv2.IMREAD_COLOR)
52
+
53
+ @app.route('/', methods=['GET'])
54
+ def home():
55
+ return jsonify({
56
+ 'service': 'CAPTCHA Solver API',
57
+ 'version': '2.0',
58
+ 'status': 'online',
59
+ 'endpoints': {
60
+ '/health': 'GET - Health check',
61
+ '/solve': 'POST - Solve CAPTCHA'
62
+ }
63
+ })
64
+
65
+ @app.route('/health', methods=['GET'])
66
+ def health():
67
+ return jsonify({'status': 'ok', 'solver': 'SimpleCaptchaSolver v2.0'})
68
+
69
+ @app.route('/solve', methods=['POST'])
70
+ def solve():
71
+ try:
72
+ data = request.json
73
+ if not data or 'target' not in data or 'options' not in data:
74
+ return jsonify({'status': 0, 'error': 'Missing fields'}), 400
75
+ target = b64_to_cv2(data['target'])
76
+ options = [b64_to_cv2(opt) for opt in data['options']]
77
+ result = solver.solve(target, options)
78
+ return jsonify({'status': 1, 'result': result})
79
+ except Exception as e:
80
+ return jsonify({'status': 0, 'error': str(e)}), 500
81
+
82
+ if __name__ == '__main__':
83
+ port = int(os.environ.get('PORT', 10000))
84
+ print("="*60)
85
+ print(f"🚀 CAPTCHA Solver API")
86
+ print(f"🌐 Port: {port}")
87
+ print("="*60)
88
+ app.run(host='0.0.0.0', port=port, debug=False)
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ flask==3.0.3
2
+ opencv-python-headless>=4.10.0
3
+ numpy>=1.26.0
4
+ gunicorn==23.0.0