# -*- coding: utf-8 -*- import sys from ids_peak ...
創建於:2025年7月23日
創建於:2025年7月23日
import sys
from ids_peak import ids_peak
from ids_peak_ipl import ids_peak_ipl
import numpy as np
def main():
"""
主函式,執行相機的初始化、影像擷取和資源釋放。
"""
device = None
datastream = None
nodemap_remote_device = None
texttry: ids_peak.Library.Initialize() print("IDS peak Library 初始化成功。") except Exception as e: print(f"初始化 IDS peak Library 失敗: {e}") return -1 try: device_manager = ids_peak.DeviceManager.Instance() device_manager.Update() if device_manager.Devices().empty(): print("錯誤:找不到任何相機。請檢查相機連接與驅動程式。") return -1 device = device_manager.Devices()[0].OpenDevice(ids_peak.DeviceAccessType_Control) print(f"成功開啟相機: {device.ModelName()}") datastreams = device.DataStreams() if not datastreams: print("錯誤:相機不支援資料流。") return -1 datastream = datastreams[0].OpenDataStream() print("成功開啟資料流。") nodemap_remote_device = device.RemoteDevice().NodeMaps()[0] payload_size = nodemap_remote_device.FindNode("PayloadSize").Value() buffer_count_max = datastream.NumBuffersAnnouncedMinRequired() for _ in range(buffer_count_max): buffer = datastream.AllocAndAnnounceBuffer(payload_size) datastream.QueueBuffer(buffer) datastream.StartAcquisition() print("資料流開始擷取...") nodemap_remote_device.FindNode("AcquisitionStart").Execute() nodemap_remote_device.FindNode("AcquisitionStart").WaitUntilDone() print("相機開始傳送影像...") ipl_converter = ids_peak_ipl.ImageConverter() print("\n--- 開始擷取 10 張影像 ---") for i in range(10): buffer = datastream.WaitForFinishedBuffer(5000) # [最終修正] # 1. 使用正確的靜態方法 `Image.create_from()` 從 buffer 建立一個原始 Image 物件。 # 這是 C++ 的 `CreateFrom` 在 Python 繫結中最常見的 snake_case 形式。 ipl_image = ids_peak_ipl.Image.create_from(buffer) # 2. 將這個建立好的 `ipl_image` 物件傳入轉換器,轉換成目標格式。 converted_image = ipl_converter.Convert(ipl_image, ids_peak_ipl.PixelFormatName_BGRa8) # 3. 從轉換好的 Image 物件取得 NumPy 陣列。 image_np = converted_image.get_numpy_1d_view().reshape( converted_image.Height(), converted_image.Width(), converted_image.PixelPerChannel() ) print(f"成功擷取第 {i+1}/10 張影像,尺寸 (HxW): {image_np.shape[0]}x{image_np.shape[1]}") datastream.QueueBuffer(buffer) print("--- 影像擷取完成 ---\n") except Exception as e: print(f"程式執行期間發生錯誤: {e}") return -1 finally: print("開始清理與釋放資源...") if device is not None and nodemap_remote_device is not None: try: nodemap_remote_device.FindNode("AcquisitionStop").Execute() except Exception: pass if datastream is not None: try: datastream.StopAcquisition(ids_peak.AcquisitionStopMode_Default) datastream.Flush(ids_peak.DataStreamFlushMode_DiscardAll) for buffer in datastream.AnnouncedBuffers(): datastream.RevokeBuffer(buffer) except Exception: pass try: ids_peak.Library.Close() print("IDS peak Library 已成功關閉。") except Exception as e: print(f"關閉 IDS peak Library 時發生錯誤: {e}") print("程式執行完畢。") return 0
if name == 'main':
sys.exit(main())
(OTMS) $ py read_IDS.py
IDS peak Library 初始化成功。
成功開啟相機: U3-38CxXLS-C
成功開啟資料流。
資料流開始擷取...
相機開始傳送影像...
--- 開始擷取 10 張影像 ---
程式執行期間發生錯誤: type object 'Image' has no attribute 'create_from'
開始清理與釋放資源...
IDS peak Library 已成功關閉。
程式執行完畢。
ids_peak_ipl.Image
in the current Python bindings never had a lowercase-snake-case constructor called create_from(...)
, so the import line
pythonipl_image = ids_peak_ipl.Image.create_from(buffer)
raises the AttributeError
.
There are two supported ways to turn a finished Buffer
into an Image
:
ids_peak_ipl_extension.BufferToImage
)IDS ship a tiny helper module that does exactly the C++ peak::BufferTo<Image>
conversion for you:
pythonfrom ids_peak import ids_peak_ipl_extension # NEW import buffer = datastream.WaitForFinishedBuffer(5_000) ipl_img = ids_peak_ipl_extension.BufferToImage(buffer) # shallow copy
BufferToImage
is part of the official docs and keeps the call short.(en.ids-imaging.com)
Image
If you really need a deep-copy or want to build an image manually, the binding exposes Pascal-Case factories that mirror the C++ names, e.g.
pythonipl_img = ids_peak_ipl.Image.CreateFromSizeAndBuffer( buffer.PixelFormat(), # pixel format object buffer.BasePtr(), # raw pointer buffer.Size(), # size in bytes buffer.Width(), buffer.Height() )
Notice the uppercase C in CreateFrom…
.(PyPI)
pythonfrom ids_peak import ids_peak_ipl, ids_peak_ipl_extension import numpy as np ipl_converter = ids_peak_ipl.ImageConverter() buffer = datastream.WaitForFinishedBuffer(5_000) ipl_img = ids_peak_ipl_extension.BufferToImage(buffer) # convert to 4-channel BGRa8 (keep alpha so width*height*4 is easy to reshape) converted = ipl_converter.Convert( ipl_img, ids_peak_ipl.PixelFormatName_BGRa8 ) h, w = converted.Height(), converted.Width() c = converted.PixelFormat().NumChannels() # =4 for BGRa8 ([en.ids-imaging.com](https://en.ids-imaging.com/manuals/ids-peak/ids-peak-ipl-documentation/2.14.0/en/classpeak_1_1ipl_1_1_pixel_format.html)) img_np = np.frombuffer(converted.Data(), dtype=np.uint8).reshape(h, w, c)
get_numpy_1d_view()
still works, but np.frombuffer(converted.Data(), …)
avoids an extra copy and lets you choose the dtype.PixelFormat().NumChannels()
is the portable way to find the channel count; PixelPerChannel
never existed in the public API.Queue the buffer back only after you finish using ipl_img
/converted
to avoid dangling memory.
That change alone should make your script run without throwing the AttributeError
and start printing the ten frame sizes as intended.
請給出完整的程式,以下請都用繁體中文回答
以下提供一份已修正、可直接執行的完整範例程式碼。
主要變動:
ids_peak_ipl_extension.BufferToImage()
將 Buffer
轉成 Image
,取代不存在的 Image.create_from()
。np.frombuffer()
取得 NumPy 陣列,並用 PixelFormat().NumChannels()
來取得通道數。buffer
重新排入佇列 (QueueBuffer),避免記憶體仍被占用。python# -*- coding: utf-8 -*- """ 使用 IDS peak SDK 擷取 10 張影像,並轉成 NumPy 陣列顯示尺寸 """ import sys import numpy as np from ids_peak import ids_peak, ids_peak_ipl, ids_peak_ipl_extension # 若需要顯示影像,可安裝 opencv-python 並取消下列註解 # import cv2 def main(): device = None datastream = None nodemap_remote_device = None # ---------- 初始化 IDS peak Library ---------- try: ids_peak.Library.Initialize() print("IDS peak Library 初始化成功。") except Exception as e: print(f"初始化 IDS peak Library 失敗: {e}") return -1 try: # ---------- 搜尋並開啟第一台相機 ---------- device_manager = ids_peak.DeviceManager.Instance() device_manager.Update() if device_manager.Devices().empty(): print("錯誤:找不到任何相機。請檢查相機連接與驅動程式。") return -1 device = device_manager.Devices()[0].OpenDevice( ids_peak.DeviceAccessType_Control ) print(f"成功開啟相機: {device.ModelName()}") # ---------- 建立並啟動資料流 ---------- datastreams = device.DataStreams() if not datastreams: print("錯誤:相機不支援資料流。") return -1 datastream = datastreams[0].OpenDataStream() print("成功開啟資料流。") nodemap_remote_device = device.RemoteDevice().NodeMaps()[0] payload_size = nodemap_remote_device.FindNode("PayloadSize").Value() buffer_count_max = datastream.NumBuffersAnnouncedMinRequired() for _ in range(buffer_count_max): buf = datastream.AllocAndAnnounceBuffer(payload_size) datastream.QueueBuffer(buf) datastream.StartAcquisition() print("資料流開始擷取...") nodemap_remote_device.FindNode("AcquisitionStart").Execute() nodemap_remote_device.FindNode("AcquisitionStart").WaitUntilDone() print("相機開始傳送影像...") # ---------- 建立影像轉換器 ---------- ipl_converter = ids_peak_ipl.ImageConverter() print("\n--- 開始擷取 10 張影像 ---") for i in range(10): # 1. 等待單張完整 Buffer buffer = datastream.WaitForFinishedBuffer(5_000) # 2. 轉成 IDS peak IPL Image (shallow copy,不複製畫素資料) ipl_image = ids_peak_ipl_extension.BufferToImage(buffer) # 3. 轉成 BGRa8,方便後續顯示或儲存 converted = ipl_converter.Convert( ipl_image, ids_peak_ipl.PixelFormatName_BGRa8 ) # 4. 取得 NumPy 陣列 h, w = converted.Height(), converted.Width() channels = converted.PixelFormat().NumChannels() image_np = np.frombuffer( converted.Data(), dtype=np.uint8 ).reshape(h, w, channels) print( f"成功擷取第 {i + 1}/10 張影像,尺寸 (HxW): " f"{image_np.shape[0]}x{image_np.shape[1]}" ) # 需要顯示時可用下列程式 # cv2.imshow("Frame", image_np) # cv2.waitKey(1) # 5. 使用完畢後再將 Buffer 排回佇列 datastream.QueueBuffer(buffer) print("--- 影像擷取完成 ---\n") except Exception as e: print(f"程式執行期間發生錯誤: {e}") return -1 finally: # ---------- 清理與釋放資源 ---------- print("開始清理與釋放資源...") if device is not None and nodemap_remote_device is not None: try: nodemap_remote_device.FindNode("AcquisitionStop").Execute() except Exception: pass if datastream is not None: try: datastream.StopAcquisition(ids_peak.AcquisitionStopMode_Default) datastream.Flush(ids_peak.DataStreamFlushMode_DiscardAll) for buf in datastream.AnnouncedBuffers(): datastream.RevokeBuffer(buf) except Exception: pass try: ids_peak.Library.Close() print("IDS peak Library 已成功關閉。") except Exception as e: print(f"關閉 IDS peak Library 時發生錯誤: {e}") print("程式執行完畢。") return 0 if __name__ == "__main__": sys.exit(main())
使用說明
- 如需顯示畫面,請安裝
opencv-python
並取消cv2
相關註解。- 若想改存成 PNG/JPEG,或用其他像素格式,只需調整
Convert()
的目標格式與後續處理即可。
執行後,終端機應會列印十張影像的解析度,並再正常結束不拋出 AttributeError
。祝開發順利!