PDF-converter / app.py
soiz1's picture
Update app.py
f1cd04c verified
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()