Spaces:
No application file
No application file
| from flask import Flask, request, jsonify | |
| import cv2 | |
| import numpy as np | |
| from pathlib import Path | |
| import tempfile | |
| import os | |
| import logging | |
| from hloc import logger as hloc_logger | |
| from common.api import ImageMatchingAPI | |
| from common.utils import ( | |
| DEVICE, | |
| get_matcher_zoo, | |
| load_config, | |
| ROOT, | |
| ) | |
| app = Flask(__name__) | |
| # Load configuration and matcher zoo | |
| config = load_config(ROOT / "common/config.yaml") | |
| matcher_zoo_restored = get_matcher_zoo(config["matcher_zoo"]) | |
| # Initialize API instances for each model | |
| api_instances = {} | |
| for model_name, conf in matcher_zoo_restored.items(): | |
| api_instances[model_name] = ImageMatchingAPI(conf=conf, device=DEVICE) | |
| # Set up logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger(__name__) | |
| def match_images(img_path1, img_path2, api_instance): | |
| logger.info(f"Matching images with {DEVICE} using provided API instance") | |
| try: | |
| # Read the images using OpenCV | |
| image0 = cv2.imread(img_path1) | |
| image1 = cv2.imread(img_path2) | |
| if image0 is None or image1 is None: | |
| raise ValueError("One or both images could not be read. Ensure the files are valid images.") | |
| # Convert BGR to RGB | |
| image0 = cv2.cvtColor(image0, cv2.COLOR_BGR2RGB) | |
| image1 = cv2.cvtColor(image1, cv2.COLOR_BGR2RGB) | |
| results = api_instance(image0, image1) | |
| return { | |
| "num_keypoints0": len(results["keypoints0_orig"]), | |
| "num_keypoints1": len(results["keypoints1_orig"]), | |
| "num_matches": len(results["mkeypoints0_orig"]), | |
| "num_inliers": len(results["mmkeypoints0_orig"]), | |
| "keypoints0": results["keypoints0_orig"].tolist(), | |
| "keypoints1": results["keypoints1_orig"].tolist(), | |
| "matches0": results["mkeypoints0_orig"].tolist(), | |
| "matches1": results["mmkeypoints0_orig"].tolist(), | |
| "inliers0": results["mmkeypoints0_orig"].tolist(), | |
| "inliers1": results["mmkeypoints0_orig"].tolist(), | |
| "confidence": results["mconf"].tolist(), | |
| "inlier_confidence": results["mmconf"].tolist(), | |
| } | |
| except Exception as e: | |
| logger.error("Matching failed: %s", str(e)) | |
| return {"error": str(e)} | |
| finally: | |
| try: | |
| os.remove(img_path1) | |
| os.remove(img_path2) | |
| except Exception as cleanup_error: | |
| logger.error("Failed to clean up temporary files: %s", str(cleanup_error)) | |
| def match_images_endpoint(): | |
| if 'img1' not in request.files or 'img2' not in request.files: | |
| return jsonify({"error": "Please upload both images."}), 400 | |
| img1_file = request.files['img1'] | |
| img2_file = request.files['img2'] | |
| model_name = request.form.get('model', 'superpoint+superglue') | |
| # Validate file types | |
| valid_extensions = {'png', 'jpg', 'jpeg', 'bmp', 'tiff'} | |
| if not (img1_file.filename.split('.')[-1].lower() in valid_extensions and | |
| img2_file.filename.split('.')[-1].lower() in valid_extensions): | |
| return jsonify({"error": "Invalid file type. Please upload images in one of the following formats: png, jpg, jpeg, bmp, tiff"}), 400 | |
| try: | |
| # Save the uploaded files to a temporary directory with unique filenames | |
| temp_dir = tempfile.mkdtemp() | |
| img_path1 = os.path.join(temp_dir, next(tempfile._get_candidate_names()) + os.path.splitext(img1_file.filename)[1]) | |
| img_path2 = os.path.join(temp_dir, next(tempfile._get_candidate_names()) + os.path.splitext(img2_file.filename)[1]) | |
| img1_file.save(img_path1) | |
| img2_file.save(img_path2) | |
| # Get the pre-initialized API instance for the selected model | |
| api_instance = api_instances.get(model_name) | |
| if not api_instance: | |
| raise ValueError(f"Model '{model_name}' not found in matcher zoo.") | |
| # Run the matching task synchronously | |
| result = match_images(img_path1, img_path2, api_instance) | |
| except Exception as e: | |
| logger.error("Error processing images: %s", str(e)) | |
| return jsonify({"error": str(e)}), 500 | |
| finally: | |
| # Clean up the temporary directory | |
| if os.path.exists(temp_dir): | |
| try: | |
| os.rmdir(temp_dir) | |
| except Exception as cleanup_error: | |
| logger.error("Failed to clean up temporary directory: %s", str(cleanup_error)) | |
| return jsonify(result), 200 | |
| if __name__ == '__main__': | |
| app.run(debug=True) | |