felixkky commited on
Commit
c7bbdb8
·
verified ·
1 Parent(s): 992c796

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -107
app.py CHANGED
@@ -1,116 +1,29 @@
1
- # ==========================================
2
- # 核心修復:偽裝螢幕環境,防止雲端伺服器崩潰
3
- # ==========================================
4
- import sys
5
- import types
6
-
7
- # 建立一個假的 screeninfo 模組
8
- fake_screeninfo = types.ModuleType("screeninfo")
9
- fake_screeninfo.ScreenInfoError = Exception
10
-
11
- # 偽裝 get_monitors 函數,讓它回傳一個假的螢幕物件(包含 width 和 height 屬性)
12
- class FakeMonitor:
13
- width = 1920
14
- height = 1080
15
- fake_screeninfo.get_monitors = lambda: [FakeMonitor()]
16
-
17
- # 強行注入到 Python 的全域模組緩存中
18
- sys.modules["screeninfo"] = fake_screeninfo
19
- # ==========================================
20
-
21
  import os
 
22
  import shutil
23
  import subprocess
24
  import gradio as gr
25
 
26
  OMR_DIR = "OMRChecker"
 
27
 
28
- # 1. 啟動時檢查並自動克隆 OMRChecker 官方專案
29
- if not os.path.exists(OMR_DIR):
30
- print("正在從 GitHub 複製 OMRChecker 核心專案...")
31
- subprocess.run(["git", "clone", "https://github.com/udayraj123/OMRChecker.git"], check=True)
32
- # 安裝該專案可能缺失的其他微量依賴
33
- subprocess.run([sys.executable, "-m", "pip", "install", "-r", f"{OMR_DIR}/requirements.txt"], check=True)
34
-
35
- def process_omr(image_file, template_content):
36
- if image_file is None or not template_content:
37
- return None, None, "錯誤:請務必上傳答案卡圖片並填寫 Template JSON 配置。"
38
-
39
- # 定義 OMRChecker 的工作目錄結構
40
- job_dir = os.path.join(OMR_DIR, "inputs", "hf_space_job")
41
- outputs_dir = os.path.join(OMR_DIR, "outputs")
42
-
43
- # 清理舊的暫存輸入與輸出,避免前後兩次請求互相干擾
44
- if os.path.exists(job_dir):
45
- shutil.rmtree(job_dir)
46
- os.makedirs(job_dir, exist_ok=True)
47
-
48
- if os.path.exists(outputs_dir):
49
- shutil.rmtree(outputs_dir)
50
-
51
- # 將上傳的圖片複製到 OMR 要求的輸入目錄
52
- target_image_path = os.path.join(job_dir, "sheet.jpg")
53
- shutil.copy(image_file, target_image_path)
54
-
55
- # 將前端/API 傳入的 Template JSON 寫入對應位置
56
- with open(os.path.join(job_dir, "template.json"), "w", encoding="utf-8") as f:
57
- f.write(template_content)
58
-
59
- # 保險起見,也在 inputs 根目錄放一份
60
- with open(os.path.join(OMR_DIR, "inputs", "template.json"), "w", encoding="utf-8") as f:
61
- f.write(template_content)
62
 
63
- # 2. 執行 OMRChecker CLI 核心
64
- result = subprocess.run(
65
- [sys.executable, "main.py"],
66
- cwd=OMR_DIR,
67
- capture_output=True,
68
- text=True
69
- )
70
-
71
- # 3. 搜尋並收集 OMRChecker 產生的輸出結果 (CSV 與 標記圖片)
72
- csv_file = None
73
- output_image = None
74
-
75
- if os.path.exists(outputs_dir):
76
- for root, dirs, files in os.walk(outputs_dir):
77
- for file in files:
78
- if file.endswith(".csv"):
79
- csv_file = os.path.join(root, file)
80
- elif file.endswith((".jpg", ".jpeg", ".png")) and "results" in root.lower():
81
- output_image = os.path.join(root, file)
82
-
83
- # 彙整 CLI 的標準輸出日誌
84
- logs = f"--- STDOUT ---\n{result.stdout}\n\n--- STDERR ---\n{result.stderr}"
85
-
86
- return csv_file, output_image, logs
87
-
88
- # 4. 建立 Gradio 介面
89
- interface = gr.Interface(
90
- fn=process_omr,
91
- inputs=[
92
- gr.Image(type="filepath", label="1. 上傳 OMR 答案卡圖片 (JPG/PNG)"),
93
- gr.Textbox(lines=12, label="2. 填入 Template JSON 配置", placeholder='{"columns": [...]}')
94
- ],
95
- outputs=[
96
- gr.File(label="下載辨識結果 (CSV)"),
97
- gr.Image(label="視覺化劃記檢視圖片"),
98
- gr.Textbox(label="系統執行日誌 (Logs)")
99
- ],
100
- title="OMRChecker 雲端辨識系統 API",
101
- description="本系統基於 udayraj123/OMRChecker。除了網頁操作外,亦可透過頁尾的 'Use via API' 連結進行自動化調用。"
102
- )
103
-
104
- if __name__ == "__main__":
105
- interface.launch()
106
-
107
- import os
108
- import sys
109
- import shutil
110
- import subprocess
111
- import gradio as gr
112
 
113
- OMR_DIR = "OMRChecker"
 
 
 
114
 
115
  # 1. 啟動時檢查並自動克隆 OMRChecker 官方專案
116
  if not os.path.exists(OMR_DIR):
@@ -147,12 +60,17 @@ def process_omr(image_file, template_content):
147
  with open(os.path.join(OMR_DIR, "inputs", "template.json"), "w", encoding="utf-8") as f:
148
  f.write(template_content)
149
 
150
- # 2. 執行 OMRChecker CLI 核心
 
 
 
 
151
  result = subprocess.run(
152
  [sys.executable, "main.py"],
153
  cwd=OMR_DIR,
154
  capture_output=True,
155
- text=True
 
156
  )
157
 
158
  # 3. 搜尋並收集 OMRChecker 產生的輸出結果 (CSV 與 標記圖片)
@@ -172,7 +90,7 @@ def process_omr(image_file, template_content):
172
 
173
  return csv_file, output_image, logs
174
 
175
- # 4. 建立 Gradio 介面(這會自動產生對應的 API 接口)
176
  interface = gr.Interface(
177
  fn=process_omr,
178
  inputs=[
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
+ import sys
3
  import shutil
4
  import subprocess
5
  import gradio as gr
6
 
7
  OMR_DIR = "OMRChecker"
8
+ MOCK_DIR = os.path.abspath("mock_libs")
9
 
10
+ # =======================================================
11
+ # 核心修復:在硬碟建立實體偽裝庫,並透過 PYTHONPATH 注入子程序
12
+ # =======================================================
13
+ os.makedirs(MOCK_DIR, exist_ok=True)
14
+ with open(os.path.join(MOCK_DIR, "screeninfo.py"), "w", encoding="utf-8") as f:
15
+ f.write('''\
16
+ class ScreenInfoError(Exception):
17
+ pass
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
+ class FakeMonitor:
20
+ width = 1920
21
+ height = 1080
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
 
23
+ def get_monitors():
24
+ return [FakeMonitor()]
25
+ ''')
26
+ # =======================================================
27
 
28
  # 1. 啟動時檢查並自動克隆 OMRChecker 官方專案
29
  if not os.path.exists(OMR_DIR):
 
60
  with open(os.path.join(OMR_DIR, "inputs", "template.json"), "w", encoding="utf-8") as f:
61
  f.write(template_content)
62
 
63
+ # 配置環境變數,強迫子程序優先載��我們的 mock_libs
64
+ current_env = os.environ.copy()
65
+ current_env["PYTHONPATH"] = MOCK_DIR + os.pathsep + current_env.get("PYTHONPATH", "")
66
+
67
+ # 2. 執行 OMRChecker CLI 核心 (帶入偽裝環境變數)
68
  result = subprocess.run(
69
  [sys.executable, "main.py"],
70
  cwd=OMR_DIR,
71
  capture_output=True,
72
+ text=True,
73
+ env=current_env
74
  )
75
 
76
  # 3. 搜尋並收集 OMRChecker 產生的輸出結果 (CSV 與 標記圖片)
 
90
 
91
  return csv_file, output_image, logs
92
 
93
+ # 4. 建立 Gradio 介面
94
  interface = gr.Interface(
95
  fn=process_omr,
96
  inputs=[