from flask import Flask, request, jsonify import cv2 import numpy as np import requests app = Flask(__name__) app.config['MAX_CONTENT_LENGTH'] = 10 * 1024 * 1024 # Maksymalny rozmiar: 10 MB def preprocess_image(image_path): """Wczytaj obraz i przetwórz go (progowanie, usuwanie szumu).""" image = cv2.imread(image_path, cv2.IMREAD_COLOR) if image is None: raise ValueError(f"Nie udało się wczytać obrazu: {image_path}") # Konwersja do skali szarości gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Usunięcie szumu (rozmycie Gaussa) blurred = cv2.GaussianBlur(gray, (5, 5), 0) # Adaptacyjne progowanie thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 3) return thresh, image def detect_shapes(thresh, original_image): """Wykryj jeden najbardziej istotny kształt na obrazie.""" contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) largest_contour = None largest_area = 0 detected_shape = "Unknown" for contour in contours: # Filtracja konturów na podstawie pola area = cv2.contourArea(contour) if area < 500: # Pomijamy małe kontury continue # Wybór największego konturu if area > largest_area: largest_contour = contour largest_area = area if largest_contour is not None: # Aproksymacja konturu epsilon = 0.02 * cv2.arcLength(largest_contour, True) approx = cv2.approxPolyDP(largest_contour, epsilon, True) # Analiza kształtu if len(approx) == 3: detected_shape = "Triangle" elif len(approx) == 4: # Weryfikacja kwadratu/prostokąta x, y, w, h = cv2.boundingRect(approx) aspect_ratio = float(w) / h if 0.95 <= aspect_ratio <= 1.05: detected_shape = "Square" else: detected_shape = "Rectangle" elif len(approx) > 4: # Weryfikacja okręgu ((x, y), radius) = cv2.minEnclosingCircle(largest_contour) circle_area = np.pi * radius * radius if abs(largest_area - circle_area) < 0.1 * largest_area: detected_shape = "Circle" # Rysowanie konturu i nazwy kształtu na obrazie cv2.drawContours(original_image, [largest_contour], -1, (0, 255, 0), 2) x, y, w, h = cv2.boundingRect(largest_contour) cv2.putText(original_image, detected_shape, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2) return detected_shape @app.route('/upload', methods=['POST']) def upload_image(): try: # Pobieranie obrazu z żądania file = request.data nparr = np.frombuffer(file, np.uint8) img = cv2.imdecode(nparr, cv2.IMREAD_COLOR) if img is None: return jsonify({"error": "Invalid image format"}), 400 # Zapisywanie zdjęcia tymczasowo na serwerze temp_image_path = "received_image.jpg" cv2.imwrite(temp_image_path, img) # Przetwarzanie obrazu thresh, original_image = preprocess_image(temp_image_path) shape = detect_shapes(thresh, original_image) # Wysyłanie informacji do ESP32 esp_ip = "http://192.168.242.159" # Zmień na poprawny adres IP ESP32 try: print(f"Sending shape to ESP32: {shape}") response = requests.post(esp_ip, json={"shape": shape}) response.raise_for_status() print("Informacje wysłane do ESP32") except requests.exceptions.RequestException as e: print(f"Błąd wysyłania danych do ESP32: {e}") # Wysyłanie odpowiedzi JSON z wykrytym kształtem do klienta return jsonify({"shape": shape}), 200 except Exception as e: print(f"Error processing image: {e}") return jsonify({"error": str(e)}), 500 if __name__ == '__main__': app.run(host='0.0.0.0', port=5000)