Hoangthanh's picture
commit tạm
0518690
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))
@app.route('/match-images', methods=['POST'])
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)