問題與前置條件
取像迴圈看似一直在回傳有效影格,卻可能在重新連線後洩漏緩衝區,或重複使用舊影像。請在實際使用的 SDK 中確認緩衝區的生命週期和裝置移除事件。下方附錄是與廠商無關的虛擬碼,不是可執行的 SDK 呼叫,也不構成對 Deyi 能力的宣告。
準備測試
假設影像為 2000 × 1500 的 Mono8:每張 3 MB,因此 8 個原始緩衝區在計入中繼資料和處理副本之前就佔用 24 MB。固定裝置身分,並在每次重新連線後定義新的取像世代(generation)。
設計工作執行緒迴圈之前,先閱讀所選 SDK 中有關取像和生命週期的文件。弄清楚誰配置緩衝區、誰擁有取像結果、緩衝區何時歸還給驅動程式,以及歸還之後保留的參照是否仍然有效。確認文件中記載的裝置移除通知,以及該通知在哪個執行緒上觸發。如果 SDK 禁止在通知回呼中阻塞,就把狀態變更和關閉協調放到回呼之外處理。裝置身分應取自文件記載的穩定識別碼,而不是列舉之後找到的第一台裝置。把影像尺寸、像素格式、酬載大小、觸發模式和傳輸設定記為驗收通過的取像參數集。下文各個概念性操作名稱,都不代表 Deyi 提供相應的 SDK 介面。
操作步驟
- 先設定影像尺寸和像素格式,再按 SDK 回報的酬載大小分配緩衝區。
- 取像時設定有限的逾時時間;區分未收到觸發、傳輸失敗和裝置被移除三種情況。
- 按文件規定的所有權規則複製或持有影像,然後再釋放取像結果。
- 裝置被移除時,停止工作執行緒,歸還尚未歸還的緩衝區,並丟棄舊世代的待處理結果。
- 只重新連線預期的那台裝置,重新套用並確認設定,然後以新的世代識別碼恢復執行。
VENDOR-NEUTRAL PSEUDOCODE — conceptual operations, not SDK API names
connect(expected_device_identity)
verify_configuration_and_payload()
generation = new_generation()
while connected:
result = none
owned_image = none
try:
result = acquire_with_deadline()
if result.is_valid:
owned_image = copy_or_retain_under_documented_rules(result)
process(owned_image, generation)
else:
record_acquisition_fault(result, generation)
finally:
release_owned_image_if_present(owned_image)
release_grab_result_if_present(result)
on_coordinator_receives_device_removed:
invalidate_current_generation()
stop_and_join_workers()
return_all_buffers()
discard_old_generation_results()
reconnect_expected_device_and_verify_configuration()
generation = new_generation()取像時設定有限的逾時時間,並在存取影像資料之前先檢查取像結果。逾時可能只是外部觸發沒有到來;傳輸故障或裝置被移除則需要走另一條復原路徑。把每個有效影格交給處理環節之前,先將它與取像世代以及影格或事件的識別資訊關聯起來。可以複製到應用程式自己管理的儲存空間,也可以按 SDK 文件規定的規則保留所有權。無論哪種做法,處理過程擲出例外時和正常完成時一樣,都要釋放資源。為處理佇列設定上限,並明確佇列滿了之後怎麼辦。記憶體悄悄越漲越大,不能算作有效的背壓策略;拿最近一張影格去充當新請求的影像,也不能替代缺失的影像。
測試紀錄範例
以下為說明用的假設,並非 Deyi 的實測效能。請將這些數值替換為你自己經簽字確認的測試紀錄。
| 紀錄項 | 假設值 |
|---|---|
| 佇列容量 | 8 |
| 未壓縮影像資料量 | 3 MB |
| 儲存容量 | 24 MB |
| 樣本數 | 1000 |
在維持已設定取像速率的同時,人為讓消費端變慢。紀錄取像世代、影格識別碼、佇列深度、存活緩衝區數量和逾時原因。如果影像被複製,24 MB 的計算結果不包含這些副本;如果保留的是參照,SDK 必須允許這些參照在相應的時間內保持有效。finally 區塊同樣示範了處理過程擲出例外時的釋放。重新連線之後,注入一個延遲到達的舊世代結果,確認它不會變成目前的檢測結果。
裝置被移除時,停止接收受影響世代的新任務,並先協調好工作執行緒的終止,再釋放它們可能仍在存取的資源。按 SDK 的約定取消或完成尚未完成的操作,歸還緩衝區,並丟棄未被消費的舊世代結果。重新連線預期的裝置,並確認已驗收的設定,不要想當然地認為預設值與上一次工作階段一致。分配新緩衝區之前,先回讀酬載資訊。新工作階段準備就緒之後,才建立新的世代。來自舊工作階段的遲到回呼或排隊中的結果,即使影格編號與目前影格相似,也必須被世代檢查拒絕。範例中的原始緩衝區算式只是記憶體消耗的一個組成部分;應把副本、佇列和演算法工作空間也納入依實測得出的預算。
流程的兩種視角
穩定的相機取像:緩衝區、逾時與重新連線 — 1
所有權從取像環節轉到處理環節,只有在消費端不再需要這些資料之後才歸還。
- 取像
- 持有或複製
- 處理
- 釋放
穩定的相機取像:緩衝區、逾時與重新連線 — 2
逾時、移除和有序關閉需要不同的狀態轉換;重新連線必須開啟一個乾淨的新取像世代。
- 逾時
- 移除
- 關閉
故障排除
- 記憶體持續增長,說明存在未釋放的取像結果,或消費端佇列沒有上限。
- 影像損壞,提示緩衝區歸還給驅動程式之後仍被使用。
- 重新連線後反覆出現舊影像時,需要檢查佇列和世代識別碼,而不能只是重新開啟裝置。
驗收與交接
執行範例中的 1000 影格試驗,並加上裝置移除、恢復和關閉這幾種情況。確認記憶體有界、沒有跨世代的結果,並且以明確的故障取代被重複使用的影像。再用慢速消費端重複一遍;原始緩衝區的算式並不是總記憶體預算。
測試前先設定驗收限值,並保留原始佐證。此處的範例並不能說明所供應的型號具備相應能力。
驗收要把持續取像、人為中斷和慢速消費端情境結合起來。對每個計畫內的請求,都紀錄存活緩衝區、佇列深度、行程記憶體、世代轉換和終止原因。按受控流程移除並恢復裝置,然後在取像尚未完成時停止應用程式。確認關閉流程能夠完成,沒有任何工作執行緒存取已釋放的記憶體,也沒有舊影像變成新的檢測結果。測試處理過程中的例外,以走通 finally 路徑。放行前,把最終的裝置身分和設定與驗收紀錄比對。範例中的 1000 影格執行只提供功能覆蓋,不能保證長期無洩漏或長期可靠。交接資料應包含實際使用的 SDK 版本、所有權決定、佇列策略、重新連線順序和故障佐證,其中可執行的廠商專用程式碼要對照其自身文件審查。
來源與技術參考資料
這些資料說明本教學所用方法的依據與適用範圍。文中的檢查範例僅供參考;量產驗收需要用你自己的樣品取得佐證。
- Programming with pylon CBasler查核於
- pylon .NET SamplesBasler查核於
部件與選型參考
- 智慧型相機與基於 PC 的視覺系統
- GigE 與 USB3 工業相機
- 機器視覺系統
- machine vision software · 英文參考資料
- EAN-13 追溯:產線驗收
- EAN-13 追溯:解碼與資料規則
- 驗收並整合可見液位工作流程
- 可見液位替代指標的 AI 輔助工作流程
- 關聯檢測紀錄、影像與工件識別碼
- OCR 標籤核對:驗收與 PLC 約定
- OCR 標籤核對:原生工作流程與精確比對
- 未封口包裝完整性檢測的驗收與整合
- 搭建 AI 輔助的未封口包裝完整性工作流程
- 用明確的狀態建立 PLC 與視覺系統的交握
- 密封與膠條外觀:產線驗收
- 密封與膠條外觀:工作流程規則
- SKU 顏色分選:驗收與未知物品分流
- SKU 顏色分選:類型明確的顏色與 SKU 規則
- 表面瑕疵檢測:驗收與產線輸出
- 表面瑕疵檢測:限定範圍的 AI 評估
- 觸發到 PLC 判定的延遲負載測試
- 完整視覺配方的版本管理與回滾

