Spaces:
Sleeping
Sleeping
import gradio as gr | |
import tempfile | |
from pdf2image import convert_from_path | |
import fitz # PyMuPDF | |
import cv2 | |
import numpy as np | |
# ========== 解析ロジック関数 ========== | |
def estimate_blurriness(pil_image): | |
""" | |
ぼけ度を推定(Laplacian分散) | |
値が小さいほどぼけている | |
""" | |
gray = np.array(pil_image.convert('L')) | |
return cv2.Laplacian(gray, cv2.CV_64F).var() | |
def estimate_contrast(pil_image): | |
""" | |
コントラストを推定(標準偏差) | |
値が小さいほどグレーでのっぺり | |
""" | |
gray = np.array(pil_image.convert('L')) | |
return gray.std() | |
def analyze_pdf(pdf_file): | |
""" | |
アップロードされたPDFの各ページを画像に変換し | |
- 画像サイズ | |
- 総ピクセル数 | |
- ぼけ度 | |
- コントラスト | |
- 推定DPI | |
などをもとにAudiverisでの利用適性を判定 | |
""" | |
MAX_PIXELS_AUDIVERIS = 20_000_000 | |
results = [] | |
overall_rating = "OK" | |
try: | |
with tempfile.TemporaryDirectory() as tmpdir: | |
# PDF → 画像変換 | |
images = convert_from_path(pdf_file.name, dpi=300, output_folder=tmpdir) | |
doc = fitz.open(pdf_file.name) | |
dpi_infos = [] | |
for i, (img, page) in enumerate(zip(images, doc)): | |
width, height = img.size | |
total_pixels = width * height | |
reasons = [] | |
page_rating = "OK" | |
# Audiverisのピクセル上限チェック | |
if total_pixels > MAX_PIXELS_AUDIVERIS: | |
page_rating = "非推奨(画像が大きすぎる)" | |
reasons.append(f"総ピクセル数 {total_pixels:,} > 20,000,000") | |
# 解像度チェック | |
if width < 1000 or height < 1000 and "非推奨" not in page_rating: | |
page_rating = "非推奨(解像度が小さい)" | |
reasons.append("幅または高さが1000px未満") | |
elif width < 1500 or height < 1500 and page_rating == "OK": | |
page_rating = "注意(やや低め)" | |
# ぼけ度チェック | |
blur_score = estimate_blurriness(img) | |
if blur_score < 30 and "非推奨" not in page_rating: | |
page_rating = "非推奨(ぼけている)" | |
reasons.append(f"ぼけ度={blur_score:.1f}") | |
# コントラストチェック | |
contrast_score = estimate_contrast(img) | |
if contrast_score < 30 and "非推奨" not in page_rating: | |
page_rating = "非推奨(コントラストが低い)" | |
reasons.append(f"コントラスト={contrast_score:.1f}") | |
# DPI情報 | |
rect = page.rect | |
width_pt = rect.width | |
height_pt = rect.height | |
dpi_x = width / (width_pt / 72) | |
dpi_y = height / (height_pt / 72) | |
dpi_infos.append(f"ページ{i+1}推定DPI: {dpi_x:.1f}x{dpi_y:.1f}") | |
# 理由をまとめる | |
reasons_str = "; ".join(reasons) if reasons else "条件クリア" | |
# ページ結果 | |
results.append( | |
f"ページ{i+1}: {width}x{height}px / ピクセル数={total_pixels:,} / " | |
f"ぼけ度={blur_score:.1f} / コントラスト={contrast_score:.1f} → {page_rating} ({reasons_str})" | |
) | |
# 総合評価を更新 | |
if "非推奨" in page_rating: | |
overall_rating = "非推奨" | |
elif "注意" in page_rating and overall_rating == "OK": | |
overall_rating = "注意" | |
# まとめテキスト | |
result_text = "\n".join(results + [""] + dpi_infos) | |
result_text += f"\n\n総合評価: {overall_rating}" | |
# 改善提案 | |
if overall_rating == "非推奨": | |
result_text += "\n\n推奨対策: スキャン解像度を下げる・画像を縮小するなどして、ファイルサイズや画質を調整してください。" | |
return result_text, overall_rating | |
except Exception as e: | |
return f"処理中にエラーが発生しました: {str(e)}", "エラー" | |
# ========== Gradio UI部分 ========== | |
with gr.Blocks() as demo: | |
gr.Markdown("# 🎼 Audiveris適性チェック(非公式・推定)") | |
gr.Markdown( | |
""" | |
PDFをアップロードすると、ページごとの画像サイズ、ピクセル数、ぼけ度、コントラストを分析し、 | |
Audiverisで使用可能かを「OK / 注意 / 非推奨」で推定します。 | |
""" | |
) | |
with gr.Row(): | |
pdf_input = gr.File(label="PDFファイル") | |
analyze_button = gr.Button("判定") | |
result_output = gr.Textbox(label="詳細結果", lines=20) | |
rating_output = gr.Textbox(label="総合評価") | |
analyze_button.click(analyze_pdf, inputs=pdf_input, outputs=[result_output, rating_output]) | |
if __name__ == "__main__": | |
demo.launch() | |