|
|
from fastapi import FastAPI, HTTPException, Request |
|
|
from fastapi.responses import FileResponse |
|
|
import cv2 |
|
|
from PIL import Image |
|
|
import re |
|
|
import gdown |
|
|
import os |
|
|
import uuid |
|
|
|
|
|
URL = "https://leekwoon-edge-api.hf.space" |
|
|
|
|
|
|
|
|
app = FastAPI( |
|
|
version="0.0.1", |
|
|
servers=[ |
|
|
{ |
|
|
"url": URL, |
|
|
"description": "image edge detection API", |
|
|
} |
|
|
], |
|
|
) |
|
|
|
|
|
|
|
|
def extract_file_id(drive_url: str) -> str: |
|
|
""" |
|
|
Google Drive URL์์ ํ์ผ ID๋ฅผ ์ถ์ถํฉ๋๋ค. |
|
|
|
|
|
Parameters: |
|
|
drive_url (str): Google Drive ํ์ผ URL. |
|
|
|
|
|
Returns: |
|
|
str: ์ถ์ถ๋ ํ์ผ ID. |
|
|
""" |
|
|
|
|
|
match = re.search(r'/d/([a-zA-Z0-9_-]+)', drive_url) |
|
|
if match: |
|
|
return match.group(1) |
|
|
|
|
|
|
|
|
match = re.search(r'file/d/([a-zA-Z0-9_-]+)', drive_url) |
|
|
if match: |
|
|
return match.group(1) |
|
|
|
|
|
|
|
|
match = re.search(r'([a-zA-Z0-9_-]{33,})', drive_url) |
|
|
if match: |
|
|
return match.group(1) |
|
|
|
|
|
raise ValueError("Invalid Google Drive URL") |
|
|
|
|
|
|
|
|
@app.post("/detect-edges/") |
|
|
def detect_edges(url: str, request: Request): |
|
|
try: |
|
|
|
|
|
file_id = extract_file_id(url) |
|
|
download_url = f"https://drive.google.com/uc?id={file_id}" |
|
|
|
|
|
|
|
|
temp_input_image = f'/tmp/{uuid.uuid4()}.png' |
|
|
gdown.download(download_url, temp_input_image, quiet=False) |
|
|
|
|
|
|
|
|
image = cv2.imread(temp_input_image) |
|
|
|
|
|
|
|
|
if image is None: |
|
|
raise HTTPException(status_code=400, detail="Invalid image URL or file not found.") |
|
|
|
|
|
|
|
|
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) |
|
|
|
|
|
|
|
|
edges = cv2.Canny(gray_image, threshold1=100, threshold2=200) |
|
|
edges_image = Image.fromarray(edges) |
|
|
|
|
|
|
|
|
white_background = Image.new("RGB", edges_image.size, (255, 255, 255)) |
|
|
|
|
|
|
|
|
edges_on_white = Image.composite(Image.new("RGB", edges_image.size, (0, 0, 0)), white_background, edges_image) |
|
|
|
|
|
|
|
|
sobelx = cv2.Sobel(gray_image, cv2.CV_64F, 1, 0, ksize=5) |
|
|
sobely = cv2.Sobel(gray_image, cv2.CV_64F, 0, 1, ksize=5) |
|
|
|
|
|
|
|
|
sobel_combined = cv2.magnitude(sobelx, sobely) |
|
|
|
|
|
|
|
|
sobel_combined = cv2.normalize(sobel_combined, None, 0, 255, cv2.NORM_MINMAX) |
|
|
sobel_combined = sobel_combined.astype('uint8') |
|
|
|
|
|
|
|
|
sobel_image = Image.fromarray(sobel_combined) |
|
|
|
|
|
|
|
|
edges_on_white_sobel = Image.composite(Image.new("RGB", sobel_image.size, (0, 0, 0)), white_background, sobel_image) |
|
|
|
|
|
|
|
|
output_file_path = f'/tmp/{uuid.uuid4()}.png' |
|
|
edges_on_white_sobel.save(output_file_path, format='PNG') |
|
|
|
|
|
|
|
|
os.remove(temp_input_image) |
|
|
|
|
|
|
|
|
download_url = os.path.join(URL, "tmp", os.path.basename(output_file_path)) |
|
|
|
|
|
|
|
|
return {"download_url": download_url} |
|
|
|
|
|
except Exception as e: |
|
|
raise HTTPException(status_code=400, detail=str(e)) |
|
|
|
|
|
|
|
|
@app.get("/tmp/{filename}") |
|
|
def download_file(filename: str): |
|
|
file_path = f"/tmp/{filename}" |
|
|
if os.path.exists(file_path): |
|
|
return FileResponse(file_path, media_type='image/png', filename=filename) |
|
|
else: |
|
|
raise HTTPException(status_code=404, detail="File not found") |