1.準備工作
準備一個海康相機
下載MVS 和SDK
海康機器人-機器視覺-下載中心
2.python MVS示例
(說明:MVS里有很多python示例,可以直接運行,但沒有用opencv)
下載完MVS后,我們打開路徑安裝路徑
我的:
D:\soft\MVS\MVS\Development\Samples\Python\BasicDemo
D:\soft\MVS\MVS\Development\Samples\Python\MvImport
可以看到有很多現成的示例。
我們借用一下"D:\soft\MVS\MVS\Development\Samples\Python\BasicDemo\BasicDemo.py"
創建 python項目test_HKcamera
復制BasicDemo.py
發現一片紅,
我們把
D:\soft\MVS\MVS\Development\Samples\Python\BasicDemo
D:\soft\MVS\MVS\Development\Samples\Python\MvImport
里面的文件都復制過來
復制后,如圖所示:
運行后:
成功輸出畫面。
3. python opencv 調用
創建test_HKcamera_opencv文件夾
創建test_hk_opecv.py文件
把第二節的文件復制進來
如圖:
test_hk_opecv.py完整代碼如下:
import cv2
import numpy as np
from MvCameraControl_class import *
from CameraParams_header import *#-------------------opencv操作部分--------------------------------------
def opencv_action(img):#自己定義操作result_img = imgreturn result_img#-----------------------海康相機設置部分---------------------------------------ret = MvCamera.MV_CC_Initialize()
if ret != 0:print(f"初始化SDK失敗,錯誤碼: {ret}")exit()# 枚舉設備
deviceList = MV_CC_DEVICE_INFO_LIST()
n_layer_type = MV_GIGE_DEVICE | MV_USB_DEVICE | MV_GENTL_CAMERALINK_DEVICE
ret = MvCamera.MV_CC_EnumDevices(n_layer_type, deviceList)
if ret != 0:print("枚舉設備失敗")exit()print(f"找到 {deviceList.nDeviceNum} 臺設備")
if deviceList.nDeviceNum == 0:exit()stDeviceList = cast(deviceList.pDeviceInfo[0], POINTER(MV_CC_DEVICE_INFO)).contentscamera = MvCamera()ret = camera.MV_CC_CreateHandle(stDeviceList)# 打開設備(使用已創建的句柄)
ret = camera.MV_CC_OpenDevice()
if ret != 0:print(f"打開設備失敗,錯誤碼: {ret}")exit()# 獲取相機參數
width = c_uint()
height = c_uint()
pixel_format = c_uint()
payload_size = c_uint()
stParam = MVCC_INTVALUE()ret = camera.MV_CC_GetIntValue("PayloadSize", stParam)
if ret != 0:print(f"獲取PayloadSize失敗,錯誤碼: {ret}")exit()
payload_size.value = stParam.nCurValue# 獲取寬度
ret = camera.MV_CC_GetIntValue("Width", stParam)
if ret != 0:print(f"獲取寬度失敗,錯誤碼: {ret}")exit()
width.value = stParam.nCurValue# 獲取高度
ret = camera.MV_CC_GetIntValue("Height", stParam)
if ret != 0:print(f"獲取高度失敗,錯誤碼: {ret}")exit()
height.value = stParam.nCurValueprint(width.value,height.value)pixel_format.value = 17301505 # RGB8
# 或
#pixel_format.value = 17301514 # Mono8#曝光時間
exposure_time = 15000 # 單位:微秒
ret = camera.MV_CC_SetFloatValue("ExposureTime", exposure_time)# 開始抓圖
ret = camera.MV_CC_StartGrabbing()
if ret != 0:print(f"開始抓圖失敗,錯誤碼: {ret}")exit()# 分配緩沖區
data_buf = (c_ubyte * payload_size.value)()
data_size = c_uint(payload_size.value)stFrameInfo = MV_FRAME_OUT_INFO_EX()#-----------------------------------------------運行部分---------------------------# 創建OpenCV窗口
cv2.namedWindow("Camera", cv2.WINDOW_NORMAL)try:while True:data_buf = (c_ubyte * payload_size.value)()ret = camera.MV_CC_GetOneFrameTimeout(byref(data_buf),payload_size.value,stFrameInfo,1000)if ret == 0:#print(f"獲取到幀: 寬度={stFrameInfo.nWidth}, 高度={stFrameInfo.nHeight}, "f"像素格式={stFrameInfo.enPixelType}, 幀大小={stFrameInfo.nFrameLen}")frame = np.frombuffer(data_buf, dtype=np.uint8)actual_width = stFrameInfo.nWidthactual_height = stFrameInfo.nHeightif stFrameInfo.enPixelType == 17301505: # RGB8expected_size = actual_width * actual_height * 3if len(frame) != expected_size:print(f"數據大小不匹配: 期望 {expected_size}, 實際 {len(frame)}")continueframe = frame.reshape((actual_height, actual_width, 3))frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)elif stFrameInfo.enPixelType == 17301514: # Mono8expected_size = actual_width * actual_heightif len(frame) != expected_size:print(f"數據大小不匹配: 期望 {expected_size}, 實際 {len(frame)}")continueframe = frame.reshape((actual_height, actual_width))elif stFrameInfo.enPixelType == 17301513: # 可能是 Bayer 格式expected_size = actual_width * actual_heightif len(frame) != expected_size:print(f"數據大小不匹配: 期望 {expected_size}, 實際 {len(frame)}")continueframe = frame.reshape((actual_height, actual_width))frame = cv2.cvtColor(frame, cv2.COLOR_BayerGB2BGR)frame = opencv_action(frame)else:print(f"不支持的像素格式: {stFrameInfo.enPixelType}")breakcv2.imshow("Camera", frame)if cv2.waitKey(1) & 0xFF == ord("q"):breakelse:print(f"獲取圖像失敗,錯誤碼: {ret}")breakfinally:# 停止抓圖camera.MV_CC_StopGrabbing()# 關閉設備camera.MV_CC_CloseDevice()# 銷毀句柄camera.MV_CC_DestroyHandle()# 銷毀窗口cv2.destroyAllWindows()
其中,比較復雜的就是格式的轉換。
海康SDK返回的數據類型(RGB8、Mono8、Bayer格式)轉成NumPy數組。
流程:
? ? A[SDK原始數據] --> B{像素格式判斷}
? ? B -->|RGB8| C[3通道重塑]? ? ? ? ? ? ? ?C --> F[RGB轉BGR]? ? ? ? F --> I[OpenCV顯示]
? ? B -->|Mono8| D[單通道重塑]? ? ? ? ? ??D --> G[灰度圖]? ? ? ? ? ? ? ? G --> I
? ? B -->|Bayer| E[顏色插值轉換]? ? ? ? ? E --> H[Bayer轉BGR]? ? ? ?H --> I
?
運行后
=========================================================
完整代碼如下:
通過網盤分享的文件:py_opencv_HK
鏈接:https://pan.baidu.com/s/1DmrVSV1LT9zGBCRx3nIKAQ
提取碼: usii
===================================
4.花絮
不知道哪個教程教的=-=
# 創建設備句柄handle = c_void_p()stDeviceList = cast(deviceList.pDeviceInfo[0], POINTER(MV_CC_DEVICE_INFO)).contents# 創建相機實例并調用方法(關鍵修正點) camera = MvCamera() # 實例化 MvCamera 類#方法一: ret = camera.MV_CC_CreateHandle(stDeviceList) #報錯:TypeError: MvCamera.MV_CC_GetIntValue() takes 3 positional arguments but 4 were given#方法二: #ret = MvCamera.MV_CC_CreateHandle(byref(handle), stDeviceList) #報錯AttributeError: '_ctypes.CArgObject' object has no attribute 'handle'#方法三: #ret = MvCamera.MV_CC_CreateHandle(byref(stDeviceList)) #報錯TypeError: MvCamera.MV_CC_CreateHandle() missing 1 required positional argument: 'stDevInfo'#方法四: #ret = camera.MV_CC_OpenDevice(byref(handle),byref(stDeviceList)) #報錯TypeError: MvCamera.MV_CC_CreateHandle() missing 1 required positional argument: 'stDevInfo'# 打開設備(使用已創建的句柄) ret = MvCamera.MV_CC_OpenDevice(handle) if ret != 0:print(f"打開設備失敗,錯誤碼: {ret}")exit()
創建
handle = c_void_p()
就瘋狂報錯。