官網
https://www.hikrobotics.com/cn/machinevision/productdetail?id=1730
MV-CA050-20UC



https://www.hikrobotics.com/cn2/source/vision/document/2021/9/7/%E6%B5%B7%E5%BA%B7%E6%9C%BA%E5%99%A8%E4%BA%BAUSB3.0%E5%B7%A5%E4%B8%9A%E9%9D%A2%E9%98%B5%E7%9B%B8%E6%9C%BA%E7%94%A8%E6%88%B7%E6%89%8B%E5%86%8CV2.1.0.pdf


2 軟件
1. 請從海康機器人官網 www.hikrobotics.com“服務支持”>“下載中心”>“機器視覺” 中下載 MVS 客戶端安裝包及 SDK 開發包。
https://www.hikrobotics.com/cn/machinevision/service/download?module=0

注意下載linux的最新版本壓縮包

下載后解壓
linux找到x86的壓縮包 解壓

打開執行安裝腳本

安裝命令 step.sh中的內容
從其中看出,被安裝在 opt/文件夾下
#!/bin/bash DIRNAME=`dirname $0` #PWD = `pwd` cd $DIRNAME #sed -i "s/export LD_LIBRARY_PATH/#export LD_LIBRARY_PATH/g" ~/.bashrc source ~/.bashrc if [ ! -d "/opt/MVS" ]; then echo "Install MVS,Please wait..." tar -C /opt -xzf ./MVS.tar.gz else echo "Uninstall MVS,Please wait..." rm -rf /opt/MVS echo "Install MVS,Please wait..." tar -C /opt -xzf ./MVS.tar.gz fi # if [ ! -d "/usr/local/Qt-5.6.3/lib/fonts" ]; then mkdir -p /usr/local/Qt-5.6.3/lib/fonts cp -r /opt/MVS/bin/fonts/* /usr/local/Qt-5.6.3/lib/fonts else echo "path exist..." fi # #if cat ~/.bashrc | grep -c "export LD_LIBRARY_PATH=/opt/MVS/bin" > /dev/null #then # echo "Include path exist" #else # echo "export LD_LIBRARY_PATH=/opt/MVS/bin" >> ~/.bashrc #fi #source ~/.bashrc echo "Set up the SDK environment..." sh $DIRNAME/set_usb_priority.sh source $DIRNAME/set_env_path.sh sh $DIRNAME/set_sdk_version.sh if [ -f /opt/MVS/driver/unload.sh ]; then sh /opt/MVS/driver/unload.sh fi sh /opt/MVS/logserver/RemoveServer.sh sh /opt/MVS/logserver/InstallServer.sh echo "Install MVS complete!" echo "Tips: You should be launch a new terminal or execute source command for the bash environment!" cd $PWD
打開軟件

sdk文件
安裝的時候被解壓在 opt/ 文件夾

打開相機
設備列表會自動顯示當前枚舉到的設備。也可通過點擊 USB 接口處的刷新按鈕 , 對設備列表中顯示的設備進行手動刷新,如圖 2-7 所示。

枚舉到設備后,雙擊連接設備,MVS 客戶端主界面如圖 2-8 所示。


其他說明




SDK開發

開發樣例 

說明
工業相機Linux SDK使用說明。Build20180531
===========================================================================
版本號: 2.4.0.5
支持相機:GigE相機和U3V相機
支持系統:ubuntu 14.04(32和64位)、ubuntu 16.04(32和64位)、centos7(32和64位)、
redhat(64位)
===========================================================================
運行環境配置
===========================================================================
在編譯示例程序之前,確認LD_LIBRARY_PATH和MVCAM_COMMON_RUNENV兩個環境變量已經生效.
eg: echo $LD_LIBRARY_PATH
輸出:/opt/MVS/lib/xxx:...
echo $MVCAM_COMMON_RUNENV
輸出:/opt/MVS/lib
如果當前環境不存在以上兩個環境變量或者變量中不包含/opt/MVS/lib相關值時,需要跳轉到安裝包所在路徑,並輸入:
source ./set_env_path.sh
===========================================================================
程序演示
===========================================================================
Display:圖像顯示例程。
使用前請先安裝X11相關庫:sudo apt-get install libx11-dev.
創建的顯示窗口不支持拉伸。
1. 使用xlib庫來創建圖像窗口
2. 枚舉設備,選擇設備並創建句柄,打開設備
3. 開始取流,調用顯示函數傳入窗口句柄
4. 輸入enter結束取流
===========================================================================
ForceIP:設置forceip
1. 枚舉設備,選擇設備並創建句柄
2. 設置forceip
3. 輸入enter結束取流
===========================================================================
Grab_ImageCallback:回調方式抓取圖像
1. 枚舉設備,選擇設備並創建句柄,打開設備
2. 設置觸發模式為off
3. 開始取流
4. 若有圖像數據,ImageCallBackEx會被調用
5. 輸入enter結束取流
===========================================================================
GrabImage:主動方式抓取圖像
1. 枚舉設備,選擇設備並創建句柄,打開設備
2. 設置觸發模式為off
3. 開始取流,開線程用來獲取圖像數據
4. 若有圖像數據,MV_CC_GetOneFrameTimeout會返回MV_OK
5. 輸入enter結束取流
===========================================================================
GrabMultipleCamera:多相機取流
1. 枚舉設備,選擇設備並創建句柄,打開設備
2. 設置觸發模式為off
3. 開始取流,開線程用來獲取圖像數據
4. 若有圖像數據,MV_CC_GetOneFrameTimeout會返回MV_OK
5. 輸入enter結束取流
===========================================================================
ImageProcess:圖像處理(存圖和像素格式轉換)
1. 枚舉設備,選擇設備並創建句柄,打開設備
2. 開始取流,若有圖像數據,MV_CC_GetOneFrameTimeout會返回MV_OK
3. 選擇case 0、1或2來進行不同圖像處理方式
4. 輸入enter結束取流
===========================================================================
ReconnectDemo:重連示例
1. 開線程,用於重連相機,線程中有枚舉、創建句柄、打開相機、注冊異常回調功能
2. 若有相機異常斷線,則會重新枚舉相機並連接第0個相機,
3. 輸入enter結束程序
===========================================================================
SetIO:設置IO
1. 枚舉設備,選擇設備並創建句柄,打開設備
2. 獲取LineSelector,設置LineSelector
3. 獲取LineMode,設置LineMode
4. 輸入enter結束程序
===========================================================================
SetParam:設置參數
1. 枚舉設備,選擇設備並創建句柄,打開設備
2. 設置int型變量,獲取int型變量
3. 設置float型變量,獲取float型變量
4. 設置enum型變量,獲取enum型變量
5. 設置bool型變量,獲取bool型變量
6. 設置string型變量,獲取string型變量
7. 輸入enter結束程序
===========================================================================
Trigger_Image:觸發方式取流
1. 枚舉設備,選擇設備並創建句柄,打開設備
2. 設置觸發模式為on,設置觸發源為軟觸發
3. 開始取流,開線程用來發送觸發命令以及獲取圖像數據
4. 輸入enter結束取流
===========================================================================
Trigger_ImageCallback: 觸發回調方式取流
1. 枚舉設備,選擇設備並創建句柄,打開設備
2. 設置觸發模式為on,設置觸發源為軟觸發
3. 開始取流,開線程用來發送觸發命令
4. 若有圖像數據,ImageCallBackEx會被調用
5. 輸入enter結束取流
===========================================================================
ConnectSpecCamera: 無枚舉連接相機(相當於MVS中的遠程連接相機)
1. 填充相機ip、網卡ip
2. 創建句柄,連接相機
3. 開始取流
===========================================================================
Events: 使用相機事件
1. 枚舉設備,選擇設備並創建句柄,打開設備
2. 開啟Event
3. 注冊Event事件回調(可注冊單個、多個、全部事件)
4. 開啟取流,當事件來臨時會在回調中響應
===========================================================================
MultiCast: 組播取流
1. 枚舉設備,選擇設備並創建句柄,打開設備
2. 選擇control或monitor模式
3. 輸入組播組ip和端口
4. 開始取流(若是m端需c端開啟取流命令)
===========================================================================
ParametrizeCamera_FileAccess:
1. 枚舉設備,選擇設備並創建句柄,打開設備
2. 開線程,使用FileAccess讀取相機配置文件
3. 開線程,使用FileAccess將配置文件寫入相機
===========================================================================
ParametrizeCamera_LoadAndSave:
需要確保代碼編輯器輸入的路徑為UTF-8編碼格式
1. 枚舉設備,選擇設備並創建句柄,打開設備
2. 將相機屬性導出到文件中
3. 從文件中導入相機屬性
python開發樣例(1) 獲取原始視頻流-無法opencv顯示


參考其SDK提供的流程圖我們可以看出,相機控制分成枚舉、打開、參數設置、關閉,銷毀句柄五個步驟
python開發樣例(2) 獲取原始視頻流-opencv顯示
1設置相機輸出像素格式
鏈接相機-屬性樹-Image Format Control-pixel format - RGB8

2設置相機分辨率
鏈接相機-屬性樹-Image Format Control- width max height max

保存

用戶設置保存-執行

斷開相機鏈接,不然占用導致后續無法程序連接

保險一點重新鏈接相機,查看默認參數是否為上次保存的。
創建和執行代碼

# -- coding: utf-8 --
import sys
import threading
import os
import termios
import time
import cv2
import numpy as np
from ctypes import *
sys.path.append("../MvImport")
from MvCameraControl_class import *
g_bExit = False
img_w=1920
img_h=1080
img_c=3
# 顯示圖像
def image_show(image):
image = cv2.resize(image, (600, 400), interpolation=cv2.INTER_AREA)
cv2.imshow('test', image)
k = cv2.waitKey(1) & 0xff
# 源程序-為線程定義一個函數
def work_thread(cam=0, pData=0, nDataSize=0):
stFrameInfo = MV_FRAME_OUT_INFO_EX()
memset(byref(stFrameInfo), 0, sizeof(stFrameInfo))
while True:
ret = cam.MV_CC_GetOneFrameTimeout(pData, nDataSize, stFrameInfo, 1000)
if ret == 0:
print ("get one frame: Width[%d], Height[%d], PixelType[0x%x], nFrameNum[%d]" % (stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.enPixelType,stFrameInfo.nFrameNum))
else:
print ("no data[0x%x]" % ret)
if g_bExit == True:
break
#opencv轉換顯示
def work_thread_rgb82bgr(cam=0, pData=0, nDataSize=0):
stFrameInfo = MV_FRAME_OUT_INFO_EX()
memset(byref(stFrameInfo), 0, sizeof(stFrameInfo))
while True:
ret = cam.MV_CC_GetOneFrameTimeout(pData, nDataSize, stFrameInfo, 1000)
if ret == 0:
print ("get one frame: Width[%d], Height[%d], PixelType[0x%x], nFrameNum[%d]" % (stFrameInfo.nWidth, stFrameInfo.nHeight, stFrameInfo.enPixelType,stFrameInfo.nFrameNum))
print('----', stFrameInfo.enPixelType)
#if stFrameInfo.enPixelType=='PixelType_Gvsp_RGB8_Packed':
temp = np.asarray(pData)
temp = temp.reshape((img_h, img_w, img_c))
temp = cv2.cvtColor(temp, cv2.COLOR_BGR2RGB)
cv2.namedWindow("temp", cv2.WINDOW_NORMAL)
cv2.imshow('temp',temp)
cv2.waitKey(1)
#else:
#print("圖像輸出格式不是BGR8,請先使用MVS軟件設置相機默認輸出圖像格式為BGR8....")
else:
print ("no data[0x%x]" % ret)
if g_bExit == True:
break
def press_any_key_exit():
fd = sys.stdin.fileno()
old_ttyinfo = termios.tcgetattr(fd)
new_ttyinfo = old_ttyinfo[:]
new_ttyinfo[3] &= ~termios.ICANON
new_ttyinfo[3] &= ~termios.ECHO
#sys.stdout.write(msg)
#sys.stdout.flush()
termios.tcsetattr(fd, termios.TCSANOW, new_ttyinfo)
try:
os.read(fd, 7)
except:
pass
finally:
termios.tcsetattr(fd, termios.TCSANOW, old_ttyinfo)
if __name__ == "__main__":
SDKVersion = MvCamera.MV_CC_GetSDKVersion()
print ("SDKVersion[0x%x]" % SDKVersion)
deviceList = MV_CC_DEVICE_INFO_LIST()
tlayerType = MV_GIGE_DEVICE | MV_USB_DEVICE
# ch:枚舉設備 | en:Enum device
ret = MvCamera.MV_CC_EnumDevices(tlayerType, deviceList)
if ret != 0:
print ("enum devices fail! ret[0x%x]" % ret)
sys.exit()
if deviceList.nDeviceNum == 0:
print ("find no device!")
sys.exit()
print ("Find %d devices!" % deviceList.nDeviceNum)
for i in range(0, deviceList.nDeviceNum):
mvcc_dev_info = cast(deviceList.pDeviceInfo[i], POINTER(MV_CC_DEVICE_INFO)).contents
if mvcc_dev_info.nTLayerType == MV_GIGE_DEVICE:
print ("\ngige device: [%d]" % i)
strModeName = ""
for per in mvcc_dev_info.SpecialInfo.stGigEInfo.chModelName:
strModeName = strModeName + chr(per)
print ("device model name: %s" % strModeName)
nip1 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >> 24)
nip2 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >> 16)
nip3 = ((mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >> 8)
nip4 = (mvcc_dev_info.SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff)
print ("current ip: %d.%d.%d.%d\n" % (nip1, nip2, nip3, nip4))
elif mvcc_dev_info.nTLayerType == MV_USB_DEVICE:
print ("\nu3v device: [%d]" % i)
strModeName = ""
for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chModelName:
if per == 0:
break
strModeName = strModeName + chr(per)
print ("device model name: %s" % strModeName)
strSerialNumber = ""
for per in mvcc_dev_info.SpecialInfo.stUsb3VInfo.chSerialNumber:
if per == 0:
break
strSerialNumber = strSerialNumber + chr(per)
print ("user serial number: %s" % strSerialNumber)
if sys.version >= '3':
nConnectionNum = input("please input the number of the device to connect:")
else:
nConnectionNum = raw_input("please input the number of the device to connect:")
if int(nConnectionNum) >= deviceList.nDeviceNum:
print ("intput error!")
sys.exit()
# ch:創建相機實例 | en:Creat Camera Object
cam = MvCamera()
# ch:選擇設備並創建句柄| en:Select device and create handle
stDeviceList = cast(deviceList.pDeviceInfo[int(nConnectionNum)], POINTER(MV_CC_DEVICE_INFO)).contents
ret = cam.MV_CC_CreateHandle(stDeviceList)
if ret != 0:
print ("create handle fail! ret[0x%x]" % ret)
sys.exit()
# ch:打開設備 | en:Open device
ret = cam.MV_CC_OpenDevice(MV_ACCESS_Exclusive, 0)
if ret != 0:
print ("open device fail! ret[0x%x]" % ret)
sys.exit()
# ch:探測網絡最佳包大小(只對GigE相機有效) | en:Detection network optimal package size(It only works for the GigE camera)
if stDeviceList.nTLayerType == MV_GIGE_DEVICE:
nPacketSize = cam.MV_CC_GetOptimalPacketSize()
if int(nPacketSize) > 0:
ret = cam.MV_CC_SetIntValue("GevSCPSPacketSize",nPacketSize)
if ret != 0:
print ("Warning: Set Packet Size fail! ret[0x%x]" % ret)
else:
print ("Warning: Get Packet Size fail! ret[0x%x]" % nPacketSize)
# ch:設置觸發模式為off | en:Set trigger mode as off
ret = cam.MV_CC_SetEnumValue("TriggerMode", MV_TRIGGER_MODE_OFF)
if ret != 0:
print ("set trigger mode fail! ret[0x%x]" % ret)
sys.exit()
# ch:獲取數據包大小 | en:Get payload size
stParam = MVCC_INTVALUE()
memset(byref(stParam), 0, sizeof(MVCC_INTVALUE))
ret = cam.MV_CC_GetIntValue("PayloadSize", stParam)
if ret != 0:
print ("get payload size fail! ret[0x%x]" % ret)
sys.exit()
nPayloadSize = stParam.nCurValue
# ch:開始取流 | en:Start grab image
ret = cam.MV_CC_StartGrabbing()
if ret != 0:
print ("start grabbing fail! ret[0x%x]" % ret)
sys.exit()
#將PayloadSize的uint數據轉為可供numpy處理的數據,后面就可以用numpy將其轉化為numpy數組格式。
data_buf = (c_ubyte * nPayloadSize)()
try:
#有些代碼可能會在data_buf前面加上byteref,如果這樣做的話,就會將數據轉為浮點型,
# 而opencv需要的是整型,會報錯,所以這里就不需要轉化了
#hThreadHandle = threading.Thread(target=work_thread_rgb82bgr, args=(cam, byref(data_buf), nPayloadSize))
hThreadHandle = threading.Thread(target=work_thread_rgb82bgr, args=(cam, data_buf, nPayloadSize))
hThreadHandle.start()
hThreadHandle.start()
except:
print ("error: unable to start thread")
print ("press a key to stop grabbing.")
press_any_key_exit()
g_bExit = True
hThreadHandle.join()
# ch:停止取流 | en:Stop grab image
ret = cam.MV_CC_StopGrabbing()
if ret != 0:
print ("stop grabbing fail! ret[0x%x]" % ret)
del data_buf
sys.exit()
# ch:關閉設備 | Close device
ret = cam.MV_CC_CloseDevice()
if ret != 0:
print ("close deivce fail! ret[0x%x]" % ret)
del data_buf
sys.exit()
# ch:銷毀句柄 | Destroy handle
ret = cam.MV_CC_DestroyHandle()
if ret != 0:
print ("destroy handle fail! ret[0x%x]" % ret)
del data_buf
sys.exit()
del data_buf
注意
0 修改代碼中湘囧分辨率
img_w=1920 img_h=1080 img_c=3
1 導入SDK路徑
因為需要用到SDK的接口函數,所以需要導入相應的庫,官方的路徑是這樣的,這是因為這個包在程序的同一個文件夾下,所以前面的都可以省略,但我們使用的時候,最好把它的絕對路徑給寫上,我的路徑是這樣的,可以參考
sys.path.append("../MvImport") #導入相應SDK的庫,實際安裝位置絕對路徑
#/opt/MVS/Samples/64/Python/MvImport
2 原始數據轉化成numpy
data_buf = (c_ubyte * nPayloadSize)()這一句話將PayloadSize的uint數據轉為可供numpy處理的數據,后面就可以用numpy將其轉化為numpy數組格式。
# ch:開始取流 | en:Start grab image
ret = cam.MV_CC_StartGrabbing()
if ret != 0:
print ("start grabbing fail! ret[0x%x]" % ret)
sys.exit()
#將PayloadSize的uint數據轉為可供numpy處理的數據,后面就可以用numpy將其轉化為numpy數組格式。
data_buf = (c_ubyte * nPayloadSize)()
3 線程調用
try: #有些代碼可能會在data_buf前面加上byteref,如果這樣做的話,就會將數據轉為浮點型, # 而opencv需要的是整型,會報錯,所以這里就不需要轉化了 #hThreadHandle = threading.Thread(target=work_thread_rgb82bgr, args=(cam, byref(data_buf), nPayloadSize)) hThreadHandle = threading.Thread(target=work_thread_rgb82bgr, args=(cam, data_buf, nPayloadSize)) hThreadHandle.start()
