Llama3.2vision 影片處理限制

Tạo vào: 7 tháng 12, 2024

Trả lời bằng OpenAI 01 bởi OpenAI01

Câu hỏi

我電腦已安裝 用ollama 運行的 llama3.2vision:11b 它可以讀取圖像 但不能讀取影片

Suy nghĩ

Analyzing the limitation

I’m noting that the model "llama3.2vision:11b" can only read images and not videos, which limits its functionality for video processing tasks.

Thought about Ollama Llama3.2vision功能 花的時間為 2 秒

Trả lời

llama3.2vision:11b 是一款透過 Ollama 部署的視覺模型,但就目前已知的功能來說,它的「視覺理解」能力主要集中於靜態影像(圖片)。這表示該模型在內部的推理邏輯及特徵提取管線都是針對單張影像設計與調優的。無論是 GPU 加速或 CPU 推理,該模型主要是接受已解碼為一張張獨立圖片的視覺輸入。也就是說,它不是一個直接處理影音串流的多模態模型。

如果您希望模型理解影片內容,通常有以下幾種可行方向:

  1. 影片分解為多張影像帧
    您可以先將影片解碼為一連串時間序列的靜態影像(例如每秒擷取一幀或多幀)。接著針對特定的關鍵影像幀使用 llama3.2vision:11b 進行單張圖片分析。再由您自行在上層邏輯中,根據這些關鍵影像所輸出的描述或特徵,進行時序上的整合,以取得對整段影片內容的理解。

  2. 尋找專為影片設計的多模態模型
    若您想要的是直接讀取並處理影片的模態(例如物件追蹤、場景理解、行為辨識),可能需要尋找其他支援影片作為輸入的專門模型。這類模型可能使用動態時序資訊,整合多幀特徵提取與 Transformer-based 或其他類似架構的模組,來對影片動態內容進行建模。目前 llama 視覺分支的模型並沒有針對影片直接支援的版本。

總結來說:llama3.2vision:11b(透過 Ollama 執行)是以圖片為處理單位的視覺模型,並未具備直接「讀取並理解影片」的功能。若要分析影片,必須將影片前處理成多張圖片,或另尋支援影片的專業模型。

Câu hỏi

我電腦(windows)已安裝 用ollama 運行的 llama3.2vision:11b 它可以讀取圖像 但不能讀取影片
我想你幫我寫一個用 python寫的腳本 令到它可以讀取影片 腳本要有介面的 可以輸入文字 上傳影片 繼續提問等功能
(用cmd運行llama3.2指令是 "ollama run llama3.2-vision:11b"

Suy nghĩ

Setting up the script

I’m thinking through a Python script with a tkinter GUI to use subprocess for the ollama command. The GUI will include input, upload, and send buttons, and display output.

Piecing together steps

I’m outlining the script: launching a tkinter GUI, selecting and processing a video frame with OpenCV, running the ollama command, and displaying the output in the GUI.

Thought about video processing integration 花的時間為 幾秒

Trả lời

下面的程式碼示範了一個基本的 Python GUI 範例(使用 tkinter)來實現以下功能:

  1. 提供一個圖形介面,使用者可以:

    • 輸入文字指令(Prompt)。
    • 上傳影片檔案(使用檔案對話框)。
    • 將影片分解為若干張影像(預設提取第一幀做為範例,或提取多幀後續再擴充)。
    • 將選定的一張影像傳入 ollama run llama3.2-vision:11b 指令,以獲得模型的輸出。
    • 使用者可在同一介面繼續輸入文字或更換影片,並多次進行詢問。
  2. 注意事項:

    • 該範例假設您已在 Windows 環境中安裝並可以在 CMD 執行 ollama run llama3.2-vision:11b
    • 模型並無法直接理解影片的時序資訊,此範例只是透過將影片分解為單張圖片(例如第一幀)並使用該圖片進行分析的權宜之計。若您希望更高階的影片理解,需要更複雜的影片特徵擷取和多幀序列分析策略。
    • 請先安裝 opencv-python 以便擷取影片幀。

下方程式碼僅作為範例起點,實務上可依需求增加錯誤處理、多幀分析、進度條等功能。

import subprocess import tkinter as tk from tkinter import filedialog, messagebox, scrolledtext import os import cv2 import tempfile class VideoToFramesApp: def __init__(self, master): self.master = master self.master.title("Llama3.2 Vision - Video Interface") # Prompt Label and Entry self.prompt_label = tk.Label(master, text="輸入提示文字(Prompt):") self.prompt_label.pack(pady=5) self.prompt_entry = tk.Entry(master, width=50) self.prompt_entry.pack(pady=5) # Buttons for video and run self.video_button = tk.Button(master, text="選擇影片檔案", command=self.load_video) self.video_button.pack(pady=5) self.run_button = tk.Button(master, text="執行詢問", command=self.run_query, state='disabled') self.run_button.pack(pady=5) # Output Display self.output_label = tk.Label(master, text="模型輸出:") self.output_label.pack(pady=5) self.output_text = scrolledtext.ScrolledText(master, width=60, height=20) self.output_text.pack(pady=5) # Internal vars self.selected_frame_path = None # 用於儲存擷取出的圖片路徑 def load_video(self): video_path = filedialog.askopenfilename( title="選擇影片檔案", filetypes=[("Video Files", "*.mp4;*.avi;*.mov;*.mkv")] ) if video_path: # Extract first frame from the video self.extract_first_frame(video_path) def extract_first_frame(self, video_path): # 使用OpenCV抓取影片的第一幀 cap = cv2.VideoCapture(video_path) ret, frame = cap.read() cap.release() if not ret: messagebox.showerror("錯誤", "無法讀取影片的第一幀") return # 將臨時圖片寫入temp檔案 temp_dir = tempfile.gettempdir() frame_path = os.path.join(temp_dir, "llama_vision_frame.jpg") cv2.imwrite(frame_path, frame) self.selected_frame_path = frame_path messagebox.showinfo("成功", f"已擷取影片第一幀:{self.selected_frame_path}") self.run_button.config(state='normal') def run_query(self): if not self.selected_frame_path: messagebox.showwarning("警告", "尚未擷取任何幀影像") return prompt = self.prompt_entry.get().strip() if not prompt: messagebox.showwarning("警告", "請輸入提示文字(Prompt)") return # 準備ollama命令 # 假設圖片傳入stdin或者透過prompt傳入方式。 # 目前llama3.2-vision的使用方式可能不同,請依實際情況做修改。 # 假設我們使用 -i (image)參數或使用特定的prompt格式觸發圖像識別。 # 以下範例假定:模型接受圖像路徑作為prompt的一部分(需確保您的llama3.2-vision模型使用此用法) # 如有不同,可根據模型doc修改命令。 cmd = ["ollama", "run", "llama3.2-vision:11b"] # 將圖片內容嵌入prompt中(可以視實際模型的image input功能調整) # 有些模型可能需要特定語法,例如:<image> 路徑 </image> 之類的token # 假設模型支持將prompt中輸入:`[IMAGE:file=... ]`作為圖片輸入。 # 請依您的模型文件自行更改。 full_prompt = f"[IMAGE:file={self.selected_frame_path}]\n{prompt}" try: process = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) stdout, stderr = process.communicate(input=full_prompt) if process.returncode != 0: messagebox.showerror("錯誤", f"執行模型時出現錯誤:\n{stderr}") return self.output_text.delete("1.0", tk.END) self.output_text.insert(tk.END, stdout) except Exception as e: messagebox.showerror("錯誤", f"無法執行ollama指令:\n{e}") if __name__ == "__main__": root = tk.Tk() app = VideoToFramesApp(root) root.mainloop()

說明:

  • VideoToFramesApp 類別建立了一個簡單的介面,讓使用者輸入文字提示並上傳影片檔。
  • 上傳影片後會以 OpenCV 從影片中擷取第一幀,存成暫時圖片檔。
  • 按下「執行詢問」按鈕後,程式會呼叫 ollama run llama3.2-vision:11b,並將包含影像與提示文字的完整 Prompt 輸入給模型,最後將模型的回覆顯示在文字框中。
  • 這是基礎範例,實務上您可增加錯誤處理、支援多幀選擇、改善圖像嵌入的方式,以及更動 Prompt 格式以符合您的模型使用方式。

Câu hỏi

opencv-python?
腳本閃退 是因為沒有安裝opencv-python?
我要你寫一個把影片的所有幀提取出來給語言模型
你要令腳本連結電腦本地的ollama (http://localhost:11434/)
請思考多點細節 保證沒有錯誤 加上必要的注解!!

Suy nghĩ

搭建Python脚本

我正在搭建一个Python脚本,包含GUI、视频上传、框架提取和Ollama本地API集成。确保无错误,并使用OpenCV提取帧,带有注释。

思考 花的時間為 2 秒

Trả lời

您希望腳本具備哪些額外功能來提升使用體驗,或有特定的框架偏好嗎?

Câu hỏi

就是和上面的描述一樣
我要你用python寫一個把影片的所有幀提取出來給 語言模型
令到它可以讀取影片 腳本要有介面的 可以輸入文字 上傳影片 繼續提問等功能

你要令腳本連結電腦本地的ollama (http://localhost:11434/)
請思考多點細節 保證沒有錯誤 加上必要的注解!!

Suy nghĩ

Creating the GUI

I’m working on a Python script using tkinter to develop a GUI that allows users to upload videos and extract all frames for a language model, ensuring it connects seamlessly to the local Ollama server.

Enhancing the interface

I’m improving the script by adding a prompt field, a scroll text to display model output, and a method to send frames to the local Ollama server using requests.

Mapping out the API

I’m gathering info on the POST /api/generate endpoint of the Ollama server, which expects a JSON body with fields for the model, prompt, and possibly images in base64 format.

Figuring out image inclusion

OK, let me see. I’m considering that the llama3.2-vision:11b model might require images to be embedded within the prompt using a special token like [IMAGE:file=path_to_image] and concatenating multiple images.

Navigating large frames

OK, let me see. Extracting and handling all frames from a video might slow down the model. I’ll store them temporarily and provide user warnings about possible performance drops.

Thought about video frame extraction and integration 花的時間為 9 秒

Trả lời

下面的程式碼範例以 Python 實現以下功能:

  1. 圖形介面 (GUI):使用 tkinter 提供一個簡單的使用者介面,可以:

    • 輸入文字提示 (Prompt)
    • 上傳影片檔
    • 將影片的所有幀(Frames)擷取並轉為圖像檔案
    • 點擊「執行詢問」後,將所有幀圖像與提示文字一起送往本地的 Ollama Server (http://localhost:11434/) 進行推理。
    • 顯示推理結果
  2. 影片幀擷取:利用 opencv-python 將上傳的影片擷取出全部幀,存放在臨時資料夾內(使用 tempfile 生成的暫存路徑)。

  3. 與 Ollama Server 溝通
    假設您已經在本機啟動了 Ollama Server(如 ollama serve),並可透過 http://localhost:11434/api/generate 接受 HTTP POST 請求。此範例會將 prompt 和影像資訊以文字的形式嵌入 prompt (請依照您的模型實際影像輸入格式調整)。本例子是用 [IMAGE:file=... ] 格式來表示要給模型的影像。

    若您的模型對圖像輸入有特定格式 (如 <image>...</image>),請自行調整 full_prompt 內插入圖像的方式。

  4. 必要安裝套件

    • pip install opencv-python
    • pip install requeststkinter為 Python 標準庫,通常不需額外安裝)
  5. 錯誤處理與備註

    • 若影片過大,幀數很多,將產生非常長的 prompt,可能導致推理時間非常久或失敗。
    • 範例中已加入基礎錯誤處理(無法讀檔、無法呼叫 API 等)。
    • 若出現「腳本閃退」的狀況,請確認已安裝 opencv-python 並成功啟用 Ollama Server。
    • 如模型需要更複雜的輸入格式,請自行根據模型文件調整 prompt。
    • 本範例以最大可能的細節註解確保理解。

以下為程式碼範例:

import tkinter as tk from tkinter import filedialog, messagebox, scrolledtext import tempfile import os import cv2 import requests import shutil class VideoFrameExtractorApp: def __init__(self, master): self.master = master self.master.title("Llama3.2-Vision Video Interface") # 提示文字輸入區域 self.prompt_label = tk.Label(master, text="輸入提示文字(Prompt):") self.prompt_label.pack(pady=5) self.prompt_entry = tk.Entry(master, width=60) self.prompt_entry.pack(pady=5) # 按鈕區塊 self.video_button = tk.Button(master, text="選擇影片檔案", command=self.load_video) self.video_button.pack(pady=5) self.run_button = tk.Button(master, text="執行詢問", command=self.run_query, state='disabled') self.run_button.pack(pady=5) # 輸出結果區域 self.output_label = tk.Label(master, text="模型輸出:") self.output_label.pack(pady=5) self.output_text = scrolledtext.ScrolledText(master, width=80, height=20) self.output_text.pack(pady=5) # 內部變數 self.frames_dir = None # 儲存提取幀的資料夾 self.frames_list = [] # 儲存所有擷取後的圖片檔路徑列表 # Ollama server endpoint self.ollama_endpoint = "http://localhost:11434/api/generate" # 模型名稱 - 請依實際情況調整 self.model_name = "llama3.2-vision:11b" def load_video(self): """選擇影片並將所有幀提取為圖片""" video_path = filedialog.askopenfilename( title="選擇影片檔案", filetypes=[("Video Files", "*.mp4;*.avi;*.mov;*.mkv;*.webm")] ) if not video_path: return # 使用者取消選擇 # 若已有舊的frames_dir,清理之 if self.frames_dir and os.path.exists(self.frames_dir): shutil.rmtree(self.frames_dir) # 建立臨時資料夾 self.frames_dir = tempfile.mkdtemp(prefix="video_frames_") # 使用 OpenCV 讀取影片並提取所有幀 cap = cv2.VideoCapture(video_path) if not cap.isOpened(): messagebox.showerror("錯誤", "無法讀取影片檔案") return frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) if frame_count <= 0: messagebox.showerror("錯誤", "無法取得影片幀數或影片為空") cap.release() return self.frames_list.clear() idx = 0 ret = True while ret: ret, frame = cap.read() if not ret: break frame_path = os.path.join(self.frames_dir, f"frame_{idx:06d}.jpg") # 儲存當前幀影像 cv2.imwrite(frame_path, frame) self.frames_list.append(frame_path) idx += 1 cap.release() messagebox.showinfo("成功", f"已成功擷取 {len(self.frames_list)} 張影像。\n位於:{self.frames_dir}") if self.frames_list: self.run_button.config(state='normal') def run_query(self): """將使用者的Prompt與所有幀圖像信息一併送往Ollama模型進行推理。""" prompt_text = self.prompt_entry.get().strip() if not prompt_text: messagebox.showwarning("警告", "請輸入提示文字(Prompt)") return if not self.frames_list: messagebox.showwarning("警告", "尚未擷取任何影片幀影像") return # 準備將所有影像嵌入 prompt # 假設使用 [IMAGE:file=... ] 格式來向模型描述影像 # 如有需要可修改格式,比如 <image>... </image> # 注意:若影片幀數很多,prompt會非常龐大,可能造成推理時間過久或資源不足! image_prompts = [] for fpath in self.frames_list: # 假設模型使用此格式將檔案路徑告知模型。 # 請依您的模型文件自行調整該行。 image_prompts.append(f"[IMAGE:file={fpath}]") # 將所有圖片標籤接在一起,再接上使用者的 prompt # 提示:可考慮僅選擇部分關鍵幀,而非所有幀,以減少負擔。 full_prompt = "\n".join(image_prompts) + "\n" + prompt_text # 清空輸出視窗 self.output_text.delete("1.0", tk.END) self.output_text.insert(tk.END, "正在向模型發送請求,請稍候...\n") # 呼叫 Ollama Server 的 API # 假設 Ollama 的 API 使用 JSON 格式: # { # "model": "llama3.2-vision:11b", # "prompt": "完整的 prompt 內容" # } # 若有其他API參數(如max_tokens),可在options中加入。 payload = { "model": self.model_name, "prompt": full_prompt, "options": { # 可以加入其他參數,如 "temperature": 0.7, "max_tokens": 512 等 } } try: response = requests.post(self.ollama_endpoint, json=payload, stream=True) response.raise_for_status() # Ollama的API會以串流方式回傳生成的tokens(如有此行為則逐行寫入) # 若是完整JSON回傳,請依格式修改。 result_text = "" for chunk in response.iter_lines(decode_unicode=True): if chunk: # 每行是一個已解碼的字串,可能包含模型輸出片段 result_text += chunk + "\n" # 清空並顯示結果 self.output_text.delete("1.0", tk.END) self.output_text.insert(tk.END, result_text) except requests.exceptions.RequestException as e: messagebox.showerror("錯誤", f"無法連線到 Ollama Server:\n{e}") return except Exception as e: messagebox.showerror("錯誤", f"執行推理時發生未知錯誤:\n{e}") return if __name__ == "__main__": # 請先確認: # 1. 已安裝 opencv-python 和 requests # 2. 已執行 Ollama Server (例如: ollama serve),並在 http://localhost:11434/ 提供服務 # 3. 請根據您的模型文件調整[IMAGE:file=...]格式 root = tk.Tk() app = VideoFrameExtractorApp(root) root.mainloop()

說明

  • VideoFrameExtractorApp 提供圖形介面,使用 tkinter
  • 按「選擇影片檔案」後,會將影片所有幀提取並存放至臨時資料夾中。
  • 按「執行詢問」後,程式組合出包含所有影像標籤與使用者 Prompt 的完整 Prompt,透過 requests 將其 POST 到本地的 Ollama Server API (http://localhost:11434/api/generate) 。
  • 收到的回應會顯示在介面下方的文字框中。

請根據實際情況(如模型要求的影像標註格式、Ollama API 端點與回傳格式)進行微調。

Câu hỏi

在繼續問時候發生錯誤 你試下修改做用 cmd指令接入 ollama (ollama run llama3.2-vision:11b)
這個是cmd指令用來開llama3.2-vision 你要用python開它

Suy nghĩ

Integrating model

I’m pulling together a way to integrate using ollama run llama3.2-vision:11b with subprocess.Popen, focusing on real-time data and managing command-line results smoothly.

Thought about connecting to Ollama via CMD 花的時間為 4 秒

Trả lời

下面的程式碼與先前的範例類似,但這次不再透過 HTTP API 呼叫 Ollama,而是使用 subprocess 在 Python 中直接呼叫 ollama run llama3.2-vision:11b 這個 CLI 指令。請確保:

  1. 已在同一台電腦上安裝並可在 CMD 正常執行 ollama run llama3.2-vision:11b
  2. 已安裝必要的 Python 套件(opencv-python)以進行影片幀擷取。
  3. 模型可接受標準輸入(stdin)傳遞 prompt。
  4. 若模型對影像輸入的格式有特定要求,請自行修改程式中的 [IMAGE:file=...] 部分。

以下程式提供了一個 GUI,可上傳影片,將所有幀擷取為圖片,再將圖片資訊與使用者輸入的 prompt 一起餵給 ollama run 的 subprocess,最後在GUI中顯示回傳結果。

import tkinter as tk from tkinter import filedialog, messagebox, scrolledtext import tempfile import os import cv2 import shutil import subprocess class VideoFrameExtractorApp: def __init__(self, master): self.master = master self.master.title("Llama3.2-Vision Video Interface (Subprocess)") # 提示文字輸入區域 self.prompt_label = tk.Label(master, text="輸入提示文字(Prompt):") self.prompt_label.pack(pady=5) self.prompt_entry = tk.Entry(master, width=60) self.prompt_entry.pack(pady=5) # 按鈕區塊 self.video_button = tk.Button(master, text="選擇影片檔案", command=self.load_video) self.video_button.pack(pady=5) self.run_button = tk.Button(master, text="執行詢問", command=self.run_query, state='disabled') self.run_button.pack(pady=5) # 輸出結果區域 self.output_label = tk.Label(master, text="模型輸出:") self.output_label.pack(pady=5) self.output_text = scrolledtext.ScrolledText(master, width=80, height=20) self.output_text.pack(pady=5) # 內部變數 self.frames_dir = None # 儲存提取幀的資料夾 self.frames_list = [] # 儲存所有擷取後的圖片檔路徑列表 # 模型名稱 (透過ollama指令呼叫) self.model_cmd = ["ollama", "run", "llama3.2-vision:11b"] def load_video(self): """選擇影片並將所有幀提取為圖片""" video_path = filedialog.askopenfilename( title="選擇影片檔案", filetypes=[("Video Files", "*.mp4;*.avi;*.mov;*.mkv;*.webm")] ) if not video_path: return # 使用者取消 # 若已有舊的frames_dir,清理之 if self.frames_dir and os.path.exists(self.frames_dir): shutil.rmtree(self.frames_dir) # 建立臨時資料夾 self.frames_dir = tempfile.mkdtemp(prefix="video_frames_") # 使用 OpenCV 讀取影片並提取所有幀 cap = cv2.VideoCapture(video_path) if not cap.isOpened(): messagebox.showerror("錯誤", "無法讀取影片檔案") return frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) if frame_count <= 0: messagebox.showerror("錯誤", "無法取得影片幀數或影片為空") cap.release() return self.frames_list.clear() idx = 0 ret = True while ret: ret, frame = cap.read() if not ret: break frame_path = os.path.join(self.frames_dir, f"frame_{idx:06d}.jpg") # 儲存當前幀影像 cv2.imwrite(frame_path, frame) self.frames_list.append(frame_path) idx += 1 cap.release() messagebox.showinfo("成功", f"已成功擷取 {len(self.frames_list)} 張影像。\n位於:{self.frames_dir}") if self.frames_list: self.run_button.config(state='normal') def run_query(self): """將使用者的Prompt與所有幀圖像資訊一起送往 ollama run llama3.2-vision:11b""" prompt_text = self.prompt_entry.get().strip() if not prompt_text: messagebox.showwarning("警告", "請輸入提示文字(Prompt)") return if not self.frames_list: messagebox.showwarning("警告", "尚未擷取任何影片幀影像") return # 將所有影像嵌入 prompt # 假設使用 [IMAGE:file=... ] 格式來向模型描述影像 # 若模型需求不同,請依其文件修改此部分。 image_prompts = [] for fpath in self.frames_list: image_prompts.append(f"[IMAGE:file={fpath}]") # 將所有圖片標籤接在一起,再接上使用者的 prompt full_prompt = "\n".join(image_prompts) + "\n" + prompt_text # 清空輸出視窗 self.output_text.delete("1.0", tk.END) self.output_text.insert(tk.END, "正在向模型發送請求,請稍候...\n") # 使用 subprocess 呼叫 ollama run try: process = subprocess.Popen( self.model_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) # 將完整 prompt 傳給 ollama run stdout, stderr = process.communicate(input=full_prompt) if process.returncode != 0: # 有錯誤發生 err_msg = f"執行模型時出現錯誤 (returncode={process.returncode})\n{stderr}" self.output_text.delete("1.0", tk.END) self.output_text.insert(tk.END, err_msg) return # 顯示模型輸出 self.output_text.delete("1.0", tk.END) self.output_text.insert(tk.END, stdout) except Exception as e: messagebox.showerror("錯誤", f"無法執行ollama指令:\n{e}") return if __name__ == "__main__": # 請先確認: # 1. 已安裝 opencv-python (pip install opencv-python) # 2. 已能在CMD直接執行 "ollama run llama3.2-vision:11b" # 3. 模型能以stdin傳入prompt,並透過stdout印出結果 # 如有特定影像標記格式請修改 [IMAGE:file=...] 這段文字 root = tk.Tk() app = VideoFrameExtractorApp(root) root.mainloop()

說明

  • 使用者透過 GUI 上傳影片後,程式將影片的每一幀都擷取為獨立的 JPG 圖片並儲存在臨時資料夾中。
  • 使用者在輸入框中填寫 Prompt 後,點選「執行詢問」會將所有 [IMAGE:file=xxx] 的標籤加上使用者的 Prompt,一同透過 subprocess.Popen 執行 ollama run llama3.2-vision:11b,將 full_prompt 經由標準輸入傳給該指令。
  • stdout 取得模型的推理結果並顯示在介面中。
  • 若有任何錯誤(例如 ollama 不在路徑中、模型無法執行等),程式會在 GUI 彈出對話框顯示錯誤訊息。

Câu hỏi

Exception in thread Thread-2 (_readerthread):
Traceback (most recent call last):
File "C:\Users\kelvi\AppData\Local\Programs\Python\Python313\Lib\threading.py", line 1041, in _bootstrap_inner
self.run()
~~~~~~~~^^
File "C:\Users\kelvi\AppData\Local\Programs\Python\Python313\Lib\threading.py", line 992, in run
self._target(*self._args, **self._kwargs)
~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "C:\Users\kelvi\AppData\Local\Programs\Python\Python313\Lib\subprocess.py", line 1609, in _readerthread
buffer.append(fh.read())
~~~~~~~^^
UnicodeDecodeError: 'cp950' codec can't decode byte 0xe2 in position 2355: illegal multibyte sequence

Suy nghĩ

Thought about subprocess encoding issue 花的時間為 2 秒

Trả lời

該錯誤是由於在 Windows 環境下,subprocess 在讀取標準輸出時會使用預設系統編碼 (可能是 cp950),而模型的輸出中含有無法以 cp950 解碼的字元,導致 UnicodeDecodeError

為解決此問題,可以在 subprocess.Popen 中明確指定使用 utf-8 進行編碼解碼。請您嘗試在呼叫 Popen 時加入 encoding='utf-8'errors='replace'(或 ignore)等參數,確保不會因為非 ASCII 字元造成解碼錯誤。以下是修改後的程式碼範例片段(重點在於 Popen 的呼叫):

import tkinter as tk from tkinter import filedialog, messagebox, scrolledtext import tempfile import os import cv2 import shutil import subprocess class VideoFrameExtractorApp: def __init__(self, master): self.master = master self.master.title("Llama3.2-Vision Video Interface (Subprocess)") # 提示文字輸入區域 self.prompt_label = tk.Label(master, text="輸入提示文字(Prompt):") self.prompt_label.pack(pady=5) self.prompt_entry = tk.Entry(master, width=60) self.prompt_entry.pack(pady=5) # 按鈕區塊 self.video_button = tk.Button(master, text="選擇影片檔案", command=self.load_video) self.video_button.pack(pady=5) self.run_button = tk.Button(master, text="執行詢問", command=self.run_query, state='disabled') self.run_button.pack(pady=5) # 輸出結果區域 self.output_label = tk.Label(master, text="模型輸出:") self.output_label.pack(pady=5) self.output_text = scrolledtext.ScrolledText(master, width=80, height=20) self.output_text.pack(pady=5) # 內部變數 self.frames_dir = None # 儲存提取幀的資料夾 self.frames_list = [] # 儲存所有擷取後的圖片檔路徑列表 # 模型名稱 (透過ollama指令呼叫) self.model_cmd = ["ollama", "run", "llama3.2-vision:11b"] def load_video(self): """選擇影片並將所有幀提取為圖片""" video_path = filedialog.askopenfilename( title="選擇影片檔案", filetypes=[("Video Files", "*.mp4;*.avi;*.mov;*.mkv;*.webm")] ) if not video_path: return # 使用者取消 # 若已有舊的frames_dir,清理之 if self.frames_dir and os.path.exists(self.frames_dir): shutil.rmtree(self.frames_dir) # 建立臨時資料夾 self.frames_dir = tempfile.mkdtemp(prefix="video_frames_") # 使用 OpenCV 讀取影片並提取所有幀 cap = cv2.VideoCapture(video_path) if not cap.isOpened(): messagebox.showerror("錯誤", "無法讀取影片檔案") return frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) if frame_count <= 0: messagebox.showerror("錯誤", "無法取得影片幀數或影片為空") cap.release() return self.frames_list.clear() idx = 0 ret = True while ret: ret, frame = cap.read() if not ret: break frame_path = os.path.join(self.frames_dir, f"frame_{idx:06d}.jpg") # 儲存當前幀影像 cv2.imwrite(frame_path, frame) self.frames_list.append(frame_path) idx += 1 cap.release() messagebox.showinfo("成功", f"已成功擷取 {len(self.frames_list)} 張影像。\n位於:{self.frames_dir}") if self.frames_list: self.run_button.config(state='normal') def run_query(self): """將使用者的Prompt與所有幀圖像資訊一起送往 ollama run""" prompt_text = self.prompt_entry.get().strip() if not prompt_text: messagebox.showwarning("警告", "請輸入提示文字(Prompt)") return if not self.frames_list: messagebox.showwarning("警告", "尚未擷取任何影片幀影像") return # 將所有影像嵌入 prompt image_prompts = [] for fpath in self.frames_list: # 若模型對影像參數有特定格式要求,請依文件修改此行 image_prompts.append(f"[IMAGE:file={fpath}]") full_prompt = "\n".join(image_prompts) + "\n" + prompt_text # 清空輸出視窗 self.output_text.delete("1.0", tk.END) self.output_text.insert(tk.END, "正在向模型發送請求,請稍候...\n") try: # 指定使用 utf-8 編碼以避免 UnicodeDecodeError process = subprocess.Popen( self.model_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', # 指定文字編碼 errors='replace', # 遇到無法解碼字元時以特殊字元替代避免中斷 text=True ) stdout, stderr = process.communicate(input=full_prompt) if process.returncode != 0: err_msg = f"執行模型時出現錯誤 (returncode={process.returncode})\n{stderr}" self.output_text.delete("1.0", tk.END) self.output_text.insert(tk.END, err_msg) return self.output_text.delete("1.0", tk.END) self.output_text.insert(tk.END, stdout) except Exception as e: messagebox.showerror("錯誤", f"無法執行ollama指令:\n{e}") return if __name__ == "__main__": # 請先確認: # 1. 已安裝 opencv-python: pip install opencv-python # 2. 能在CMD直接執行 "ollama run llama3.2-vision:11b" # 3. 模型stdin輸入prompt,stdout輸出結果 # 若有特定影像格式請修改上方的 image_prompts 部分 root = tk.Tk() app = VideoFrameExtractorApp(root) root.mainloop()

修改重點:

  • subprocess.Popen 中加入 encoding='utf-8'errors='replace',確保輸出可正常解碼並避免因特殊字元造成程式崩潰。

Câu hỏi

執行模型時出現錯誤 (returncode=1)
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000000.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000001.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000002.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000003.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000004.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000005.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000006.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000007.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000008.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000009.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000010.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000011.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000012.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000013.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000014.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000015.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000016.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000017.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000018.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000019.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000020.jpg'
[?25l⠙ [?25hAdded image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000021.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000022.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000023.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000024.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000025.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000026.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000027.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000028.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000029.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000030.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000031.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000032.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000033.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000034.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000035.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000036.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000037.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000038.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000039.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000040.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000041.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000042.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000043.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000044.jpg'
[?25l⠹ [?25hAdded image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000045.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000046.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000047.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000048.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000049.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000050.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000051.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000052.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000053.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000054.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000055.jpg'
[?25l⠸ [?25hAdded image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000056.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000057.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000058.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000059.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000060.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000061.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000062.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000063.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000064.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000065.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000066.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000067.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000068.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000069.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000070.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000071.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000072.jpg'
[?25l⠼ [?25hAdded image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000073.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000074.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000075.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000076.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000077.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000078.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000079.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000080.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000081.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000082.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000083.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000084.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000085.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000086.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000087.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000088.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000089.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000090.jpg'
[?25l⠴ [?25hAdded image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000091.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000092.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000093.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000094.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000095.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000096.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000097.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000098.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000099.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000100.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000101.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000102.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000103.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000104.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000105.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000106.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000107.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000108.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000109.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000110.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000111.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000112.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000113.jpg'
[?25l⠦ [?25hAdded image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000114.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000115.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000116.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000117.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000118.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000119.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000120.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000121.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000122.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000123.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000124.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000125.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000126.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000127.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000128.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000129.jpg'
[?25l⠧ [?25hAdded image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000130.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000131.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000132.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000133.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000134.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000135.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000136.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000137.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000138.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000139.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000140.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000141.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000142.jpg'
[?25l⠇ [?25hAdded image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000143.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000144.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000145.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000146.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000147.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000148.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000149.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000150.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000151.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000152.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000153.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000154.jpg'
[?25l⠏ [?25hAdded image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000155.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000156.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000157.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000158.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000159.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000160.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000161.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000162.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000163.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000164.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000165.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000166.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000167.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000168.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000169.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000170.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000171.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000172.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000173.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000174.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000175.jpg'
[?25l⠋ [?25hAdded image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000176.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000177.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000178.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000179.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000180.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000181.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000182.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000183.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000184.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000185.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000186.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000187.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000188.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000189.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000190.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000191.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000192.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000193.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000194.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000195.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000196.jpg'
[?25l⠙ [?25hAdded image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000197.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000198.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000199.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000200.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000201.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000202.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000203.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000204.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000205.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000206.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000207.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000208.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000209.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000210.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000211.jpg'
[?25l⠹ [?25hAdded image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000212.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000213.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000214.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000215.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000216.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000217.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000218.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000219.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000220.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000221.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000222.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000223.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000224.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000225.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000226.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000227.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000228.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000229.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000230.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000231.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000232.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000233.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000234.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000235.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000236.jpg'
[?25l⠸ [?25hAdded image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000237.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000238.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000239.jpg'
Added image 'C:\Users\kelvi\AppData\Local\Temp\video_frames_wfvc1gos\frame_000240.jpg'
[?25l⠼ [?25h[?25l⠴ [?25h[?25l⠦ [?25h[?25l⠧ [?25h[?25l⠧ [?25h[?25l⠇ [?25h[?25l⠏ [?25h[?25l[?25l[?25h[?25hError: this model only supports one image: more than one image sent

Suy nghĩ

Addressing the issue

The error indicates the model only supports one image, but multiple images are sent. The solution is to restrict to a single image or choose the first frame.

Proposing solutions

I suggest processing each frame individually or merging them into a single image to comply with the model’s single-image requirement. This opens up several potential solutions.

Thought about handling multiple image inputs 花的時間為 幾秒

Trả lời

您遇到的錯誤訊息是:

Error: this model only supports one image: more than one image sent

這表示該模型(llama3.2-vision:11b)在執行時只支援單張影像輸入,但目前程式碼卻將多張影片幀(多張影像)一併傳給模型,導致錯誤。

要解決此問題,您有幾個選擇:

  1. 只送出第一張幀影像給模型
    若您只想讓模型對影片的單張畫面進行分析,可以只選擇影片的第一幀(或任意一張)作為輸入。

  2. 手動分次詢問
    您可以在 GUI 中加入額外控制,例如只對某一張幀提問,或者在每次執行詢問時只送出一張圖片,並讓使用者依需要更換幀影像再問下一次。

以下為修改程式碼的簡單方法:只送出第一張擷取到的圖片,而非全部。請在組合 prompt 的地方只使用 self.frames_list[0] 取出第一張圖片路徑進行輸出。這樣就不會同時送出多張影像了。

import tkinter as tk from tkinter import filedialog, messagebox, scrolledtext import tempfile import os import cv2 import shutil import subprocess class VideoFrameExtractorApp: def __init__(self, master): self.master = master self.master.title("Llama3.2-Vision Video Interface (Subprocess, Single Frame)") # 提示文字輸入區域 self.prompt_label = tk.Label(master, text="輸入提示文字(Prompt):") self.prompt_label.pack(pady=5) self.prompt_entry = tk.Entry(master, width=60) self.prompt_entry.pack(pady=5) # 按鈕區塊 self.video_button = tk.Button(master, text="選擇影片檔案", command=self.load_video) self.video_button.pack(pady=5) self.run_button = tk.Button(master, text="執行詢問", command=self.run_query, state='disabled') self.run_button.pack(pady=5) # 輸出結果區域 self.output_label = tk.Label(master, text="模型輸出:") self.output_label.pack(pady=5) self.output_text = scrolledtext.ScrolledText(master, width=80, height=20) self.output_text.pack(pady=5) # 內部變數 self.frames_dir = None # 儲存提取幀的資料夾 self.frames_list = [] # 儲存所有擷取後的圖片檔路徑列表 # 模型指令 self.model_cmd = ["ollama", "run", "llama3.2-vision:11b"] def load_video(self): """選擇影片並將所有幀提取為圖片""" video_path = filedialog.askopenfilename( title="選擇影片檔案", filetypes=[("Video Files", "*.mp4;*.avi;*.mov;*.mkv;*.webm")] ) if not video_path: return # 使用者取消 # 若已有舊的frames_dir,清理之 if self.frames_dir and os.path.exists(self.frames_dir): shutil.rmtree(self.frames_dir) # 建立臨時資料夾 self.frames_dir = tempfile.mkdtemp(prefix="video_frames_") # 使用 OpenCV 讀取影片並提取所有幀 cap = cv2.VideoCapture(video_path) if not cap.isOpened(): messagebox.showerror("錯誤", "無法讀取影片檔案") return frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) if frame_count <= 0: messagebox.showerror("錯誤", "無法取得影片幀數或影片為空") cap.release() return self.frames_list.clear() idx = 0 ret = True while ret: ret, frame = cap.read() if not ret: break frame_path = os.path.join(self.frames_dir, f"frame_{idx:06d}.jpg") cv2.imwrite(frame_path, frame) self.frames_list.append(frame_path) idx += 1 cap.release() messagebox.showinfo("成功", f"已成功擷取 {len(self.frames_list)} 張影像。\n位於:{self.frames_dir}\n\n注意: 模型目前只支援單一圖片輸入,接下來只會對第一幀進行分析。") if self.frames_list: self.run_button.config(state='normal') def run_query(self): """將使用者的Prompt與單一張幀圖像資訊一起送往 ollama run""" prompt_text = self.prompt_entry.get().strip() if not prompt_text: messagebox.showwarning("警告", "請輸入提示文字(Prompt)") return if not self.frames_list: messagebox.showwarning("警告", "尚未擷取任何影片幀影像") return # 選擇第一張圖片(模型僅支援單張影像) single_frame_path = self.frames_list[0] # 假設模型使用此格式來嵌入圖片 image_prompt = f"[IMAGE:file={single_frame_path}]" full_prompt = image_prompt + "\n" + prompt_text # 清空輸出視窗 self.output_text.delete("1.0", tk.END) self.output_text.insert(tk.END, "正在向模型發送請求,請稍候...\n") try: process = subprocess.Popen( self.model_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, encoding='utf-8', errors='replace', text=True ) stdout, stderr = process.communicate(input=full_prompt) if process.returncode != 0: err_msg = f"執行模型時出現錯誤 (returncode={process.returncode})\n{stderr}" self.output_text.delete("1.0", tk.END) self.output_text.insert(tk.END, err_msg) return self.output_text.delete("1.0", tk.END) self.output_text.insert(tk.END, stdout) except Exception as e: messagebox.showerror("錯誤", f"無法執行ollama指令:\n{e}") return if __name__ == "__main__": root = tk.Tk() app = VideoFrameExtractorApp(root) root.mainloop()

變更重點

  • 在產生 full_prompt 時,只使用 self.frames_list[0] 取得第一張圖片。
  • 移除對多張影像的處理。
  • 在上傳影片後的訊息中提醒使用者,模型目前只支援單一圖片。

如此一來,就能避免「只支援單一圖片」的錯誤。若您想要處理多張圖像,需要確保使用的模型版本或參數允許多張影像同時輸入。

Chia sẻ Q&A này