opex792's picture
Upload app.py
2495559 verified
import base64
import logging
import re
import requests
import cv2
import numpy as np
import pytesseract
from flask import Flask, render_template, jsonify
from threading import Lock
import math
app = Flask(__name__)
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
solved_captchas = []
lock = Lock()
CAPTCHA_URL = 'https://checkege.rustest.ru/api/captcha'
HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}
def deskew(image):
"""
Вычисляет угол наклона и поворачивает изображение, но только если угол адекватен.
"""
gray = cv2.bitwise_not(image)
coords = np.column_stack(np.where(gray > 0))
if len(coords) < 1:
logging.warning("Нет контента для выпрямления, пропуск deskew.")
return image
angle = cv2.minAreaRect(coords)[-1]
if angle < -45:
correction_angle = -(90 + angle)
else:
correction_angle = -angle
# --- КЛЮЧЕВОЕ ИЗМЕНЕНИЕ: ПРОВЕРКА НА АДЕКВАТНОСТЬ ---
# Если вычисленный угол слишком большой, это почти наверняка ошибка.
# Безопаснее пропустить поворот, чем повернуть на 90 градусов.
if abs(correction_angle) > 45:
logging.warning(f"Вычислен неадекватный угол {correction_angle:.2f}. Пропуск коррекции наклона.")
return image
# Пропускаем, если наклон незначителен
if abs(correction_angle) < 1:
logging.info("Угол наклона незначителен, коррекция не требуется.")
return image
logging.info(f"Обнаружен адекватный угол наклона: {correction_angle:.2f} градусов. Применяется коррекция.")
(h, w) = image.shape[:2]
center = (w // 2, h // 2)
M = cv2.getRotationMatrix2D(center, correction_angle, 1.0)
rotated = cv2.warpAffine(image, M, (w, h), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_CONSTANT, borderValue=(255,255,255))
return rotated
def fetch_and_solve_captcha():
try:
logging.info("Получение новой капчи...")
response = requests.get(CAPTCHA_URL, headers=HEADERS)
response.raise_for_status()
data = response.json()
base64_image_data = data.get("Image")
if not base64_image_data:
return None
image_bytes = base64.b64decode(base64_image_data)
nparr = np.frombuffer(image_bytes, np.uint8)
original_image = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
scale_factor = 2
width = int(original_image.shape[1] * scale_factor)
height = int(original_image.shape[0] * scale_factor)
upscaled_image = cv2.resize(original_image, (width, height), interpolation=cv2.INTER_CUBIC)
hsv = cv2.cvtColor(upscaled_image, cv2.COLOR_BGR2HSV)
lower_blue = np.array([90, 50, 50])
upper_blue = np.array([130, 255, 255])
mask = cv2.inRange(hsv, lower_blue, upper_blue)
kernel = np.ones((2, 2), np.uint8)
cleaned_mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel, iterations=2)
inverted_mask = cv2.bitwise_not(cleaned_mask)
deskewed_image = deskew(inverted_mask)
processed_image = deskewed_image
tesseract_config = r'--oem 3 --psm 6 -c tessedit_char_whitelist=0123456789'
text = pytesseract.image_to_string(processed_image, config=tesseract_config)
recognized_text = re.sub(r'\s+', '', text).strip() or "Не распознано"
logging.info(f"Распознано: {recognized_text}")
_, buffer_orig = cv2.imencode('.png', original_image)
original_b64 = base64.b64encode(buffer_orig).decode('utf-8')
_, buffer_proc = cv2.imencode('.png', processed_image)
processed_b64 = base64.b64encode(buffer_proc).decode('utf-8')
return {
"text": recognized_text,
"original_b64": original_b64,
"processed_b64": processed_b64
}
except Exception as e:
logging.error(f"Произошла ошибка при решении капчи: {e}", exc_info=True)
return None
@app.route('/')
def index():
with lock:
return render_template('index.html', captchas=list(solved_captchas))
@app.route('/solve', methods=['POST'])
def solve_new_captcha():
new_captcha = fetch_and_solve_captcha()
if new_captcha:
with lock:
solved_captchas.insert(0, new_captcha)
return jsonify(new_captcha)
return jsonify({"error": "Не удалось решить капчу"}), 500
if __name__ == '__main__':
logging.info("Запуск приложения...")
initial_captcha = fetch_and_solve_captcha()
if initial_captcha:
solved_captchas.append(initial_captcha)
app.run(host='0.0.0.0', port=7860, debug=False)