|
import logging |
|
import cv2 |
|
import numpy as np |
|
import requests |
|
import torch |
|
import base64 |
|
import gradio as gr |
|
from PIL import Image |
|
from io import BytesIO |
|
from fastapi import FastAPI |
|
from models import TextSimilarityRequest |
|
from extract_text import extract_text_from_image |
|
from text_similarity import analyze_similarity |
|
from app import generate_gradio |
|
|
|
|
|
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') |
|
app = FastAPI() |
|
|
|
@app.post("/text_similarity", summary="Perform images text similarity", response_model=float, tags=["Text Similarities"]) |
|
async def text_similarity(request: TextSimilarityRequest): |
|
image_info = request.imageInfo |
|
key_texts = request.keyTexts |
|
similarity_threshold = request.similarityThreshold |
|
origin_id = image_info.originId |
|
|
|
logging.info(f"Checking text similarity for main source with resource id {origin_id}") |
|
|
|
image = load_image_url(image_info.source) |
|
|
|
|
|
gpu_available = torch.cuda.is_available() |
|
extracted_texts = extract_text_from_image(image, gpu_available) |
|
|
|
results = analyze_similarity( |
|
extracted_texts, |
|
key_texts, |
|
similarity_threshold=similarity_threshold/100, |
|
fragment_threshold=100/100 |
|
) |
|
|
|
log_similarity_report(results, origin_id) |
|
|
|
total_texts = len(key_texts) |
|
passed_texts = results["statistics"]["direct_similarity"] + results["statistics"]["combined"] |
|
|
|
percentage_passed = (passed_texts / total_texts) * 100 |
|
|
|
logging.info(f"Text similarity for main source with resource id {origin_id} is {percentage_passed}%") |
|
|
|
return percentage_passed |
|
|
|
def log_similarity_report(results, originId): |
|
|
|
logging.info(f"[{originId}] Total texts analyzed: {results['statistics']['total_analyzed']}") |
|
logging.info(f"[{originId}] Texts with detected similarity: {results['statistics']['total_processed']}") |
|
|
|
|
|
if results["similar_texts"]: |
|
logging.info(f"[{originId}] Direct Similar Texts Found: {len(results['similar_texts'])}") |
|
for item in results["similar_texts"]: |
|
logging.info(f"[{originId}] Similar Text: '{item['text']}' -> Key Text: '{item['key_text']}' with Similarity: {item['similarity']:.2%}") |
|
|
|
|
|
if results["fragments_detected"]: |
|
logging.info(f"[{originId}] Fragments Detected: {len(results['fragments_detected'])}") |
|
for item in results["fragments_detected"]: |
|
logging.info(f"[{originId}] Fragment: '{item['text']}' -> Key Text: '{item['key_text']}' with Similarity: {item['similarity']:.2%}") |
|
|
|
|
|
if results["combined"]: |
|
logging.info(f"[{originId}] Texts to be Combined: {len(results['combined'])}") |
|
for item in results["combined"]: |
|
logging.info(f"[{originId}] Combined Text: '{item['combined_text']}' -> Key Text: '{item['key_text']}' with Similarity: {item['similarity']:.2%}") |
|
|
|
|
|
if not (results["similar_texts"] or results["fragments_detected"] or results["combined"]): |
|
logging.info(f"[{originId}] No significant similarity found.") |
|
|
|
|
|
logging.info(f"[{originId}] Direct similarity: {results['statistics']['direct_similarity']}") |
|
logging.info(f"[{originId}] Fragments: {results['statistics']['fragments']}") |
|
logging.info(f"[{originId}] Combined: {results['statistics']['combined']}") |
|
|
|
def load_image_url(source): |
|
Image.MAX_IMAGE_PIXELS = None |
|
|
|
if source.startswith('http'): |
|
response = requests.get(source) |
|
img = np.asarray(bytearray(response.content), dtype=np.uint8) |
|
img = cv2.imdecode(img, cv2.IMREAD_GRAYSCALE) |
|
else: |
|
img = base64.b64decode(source) |
|
img = Image.open(BytesIO(img)) |
|
img = np.array(img) |
|
img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) |
|
|
|
return img |
|
|
|
@app.on_event("startup") |
|
async def startup_event(): |
|
gr.mount_gradio_app(app, generate_gradio(), path="/") |