日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

海康威视工业相机SDK的开发使用笔记

發布時間:2023/12/14 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 海康威视工业相机SDK的开发使用笔记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

環境說明:Ubuntu16.04
海康威視SDK包:MVS-2.1.0_x86_64_20201228.tar.gz

如若在Windows環境下配合Visual Studio使用請移至
海康威視工業相機SDK二次開發(VS+Opencv+QT+海康SDK+C++)(一)
海康威視工業相機SDK二次開發(VS+Opencv+QT+海康SDK+C++)(二)

記錄自己的學習過程,方便以后查閱,若有錯誤或遺漏,歡迎大佬指正補充。


這里寫目錄標題

  • 1.準備
    • 1.1 相關資料
    • 1.2 Debug常備
    • 1.3 針對錯誤碼的解析
      • MV_E_HANDLE 0x80000000 錯誤或無效的句柄
      • MV_E_SUPPORT 0x80000001 不支持的功能
      • MV_E_BUFOVER 0x80000002 緩存已滿
      • MV_E_CALLORDER 0x80000003 函數調用順序有誤
      • MV_E_PARAMETER 0x80000004 錯誤的參數
      • MV_E_RESOURCE 0x80000006 資源申請失敗
      • MV_E_NODATA 0x80000007 無數據
      • MV_E_NOENOUGH_BUF 0x8000000A 傳入的內存空間不足
      • MV_E_UNKNOW 0x800000FF 未知的錯誤
      • MV_E_GC_GENERIC 0x80000100 通用錯誤
      • MV_E_GC_RANGE 0x80000102 值超出范圍
      • MV_E_GC_ACCESS 0x80000106 節點訪問條件有誤
      • MV_E_GC_TIMEOUT 0x80000107 超時
      • MV_E_ACCESS_DENIED 0x80000203 設備無訪問權限
      • MV_E_NETER 0x80000206 網絡相關錯誤
      • MV_E_IP_CONFLICT 0x80000221 設備IP沖突
      • MV_E_USB_READ 0x80000300 讀USB出錯
      • MV_E_USB_WRITE 0x80000301 寫USB出錯
      • MV_E_USB_DRIVER 0x80000305 驅動不匹配或者未裝驅動
  • 2.通過海康相機SDK熟悉C接口取圖流程和取圖方式
    • 2.1 設備連接接口流程
    • 2.2 相機取圖——主動取流
    • 2.3 設置相機的一些參數
  • 3.將相機抓取到的圖像轉為Mat格式,方便后續使用
  • 4.將Mat格式圖像轉為QImage格式,用于UI界面上控件的顯示

1.準備

??首先是安裝海康威視的MVS軟件,VMware虛擬機中Ubuntu16.04系統下通過MVS運行海康威視工業相機。

1.1 相關資料

  • 工業相機SDK(C)開發指南
    這是最重要的資料,里面有(環境配置:SDK編程環境配置,包括網絡配置、驅動安裝等)、(編程導引:相機連接流程和取圖方式介紹)、相機的常用節點等等。

  • 相機的常用節點查詢
    這部分主要是用于SDK提供API接口中的參數設置,如設置曝光模式、曝光值、增益模式、增益值、外觸發等等。

    根據我實際開發過程中常用的相機節點值如下:
  • CameraParams.h:包含編程需要的所有結構體、宏定義和枚舉量
  • MvCameraControl.h包含所有控制相機的API接口
  • 相關示例程序

1.2 Debug常備

??如果遇到問題,比如相機未正常打開、相機無法取圖等等,及時打印每次調用SDK接口返回的輸出值,對照錯誤碼定義去排查問題(記得將輸出值轉化為十六進制)事半功倍。

??如果函數正常完成而沒有檢測到任何錯誤,則返回值為MV_OK,否則返回錯誤碼 。

1.3 針對錯誤碼的解析

??調試時如果遇到常見的錯誤碼,如0x80000000——錯誤或無效的句柄,很自然的我們就會去排查是不是對于句柄的操作有誤,好歹給了我們一些方向,但有些錯誤碼如0x80000006——資源申請失敗或者通用錯誤這些,僅憑類型信息描述根本無法提供方向去排查,這里列出我網上找到的和我實際遇到的及其解決方法供大家參考。
參考:https://zhuanlan.zhihu.com/p/437976222

MV_E_HANDLE 0x80000000 錯誤或無效的句柄

解析:-2147483648/0x80000000 無效句柄。
常見問題如下
用戶沒有申請句柄,直接調用接口,新手常犯的錯誤,要引導去學習我們接口使用流程。
用戶創建了句柄,但是其他地方銷毀了句柄,用戶沒有注意到,需要仔細排查代碼。

MV_E_SUPPORT 0x80000001 不支持的功能

解析:-2147483647/0x80000001
SDK接口的bayer空域降噪、無損壓縮、色彩矯正等ISP功能,需要配合CS-Pro系列相機支持。
格式轉化時,不同格式的相互轉化,超出了算法能力集,詳情請仔細查閱SDK接口說明。

MV_E_BUFOVER 0x80000002 緩存已滿

解析:-2147483646/0x80000002
常見于gige驅動啟動時報錯,低版本SDK在某些網卡上面易發,驅動啟動失敗后,走socket協議發送接收相機數據,效率低,CPU負載大 推薦使用SDK3.5版本解決此問題。

MV_E_CALLORDER 0x80000003 函數調用順序有誤

解析:-2147483645/0x80000003
sdk接口調用,有一定流程順序,例如getimagebuffer在startgrabing之前調用,就違反了接口流程,就會報錯順序調用錯誤 還比如,沒有調用startgrabing接口,就去調用頻繁調用stopgrabing接口,也會報此錯誤。

MV_E_PARAMETER 0x80000004 錯誤的參數

解析:-2147483644/0x80000004
常見問題: 常見于格式轉化、圖像保存等需要補充數據結構的接口調用,部分參數傳入錯誤,或者沒有傳入,這個時候,要去仔細檢查參數的傳入是否正確。

MV_E_RESOURCE 0x80000006 資源申請失敗

解析:-2147483654/0x80000004
這個問題我在另一臺設備上部署相機服務端時,枚舉相機第一步就報了這個錯誤,最后是安裝了MVS后才得以解決,推測是缺了什么依賴庫,但ldd的時候并未顯示缺失的庫。

2022-9-14記錄:今天又遇到了這個問題,原來是缺了libMVGigEVisionSDK.so.3.1.3.0和libMVGigEVisionSDK.so這兩個庫。猜測海康這里是dlopen的這兩個庫,巨坑!!!通過ldd根本看不出什么錯誤。

MV_E_NODATA 0x80000007 無數據

解析:-2147483641/0x80000007無數據
相機幀率低,用戶調用主動取流接口getimagebuffer/getoneframetimout頻率高于相機出圖頻率,且超時時間短,沒有拿到圖片,此時應該打印相機幀號,如幀號連續則為正常現象。
相機處于觸發模式,沒有觸發信號給到相機,此時,應該排查用戶是否給了軟觸發或者硬觸發信號。
相機停流,此時,建議打開MVS,觀察相機狀態。
耐心尋找規律,看看是否跟packsize、scpd、取流超時時間不合理所致。

MV_E_NOENOUGH_BUF 0x8000000A 傳入的內存空間不足

解析:-2147483638/0x8000000A
1.用戶自行開辟的內存大小,小于當前相機圖像所需要的圖像大小,例如用mono8的圖像大小,接收RGB的圖像。
2.用戶定義的內存大小,中途更換了分辨率更高的相機,導致所需內存較多
3.相機開啟了chunk功能,用戶開辟緩存大小,僅考慮了圖像寬高像素格式,沒有考慮到chunk。
解決方法:
排查內存開辟大小,建議使用相機payloadsize大小
檢查相機圖像格式
關閉相機chunk等功能

MV_E_UNKNOW 0x800000FF 未知的錯誤

解析:-2147483137/0x800000FF GenICam未知錯誤
未知錯誤,形成原因較難分析,建議如下:
更新最新版本的sdk
開啟sdk日志等級,通過日志分析形成原因

MV_E_GC_GENERIC 0x80000100 通用錯誤

解析:-2147483392/0x80000100
通用接口調用,關鍵詞寫錯,例如曝光:ExposureTime,拼寫錯誤就會報錯。
第三方相機鏈接,例如邁德威視相機鏈接MVS,也會報通用錯誤,這是因為邁德威視不是標準的genicam協議的相機導致的。
接口類型用錯,例如曝光時float型節點,我們使用了一個int型的節點接口進行讀寫,訪問,那么也會報通用錯誤。

MV_E_GC_RANGE 0x80000102 值超出范圍

解析:-2147483390/0x80000102
接口傳入的參數值,超出相機接受范圍,例如,曝光存在上下限,圖像寬高存在步進,沒有按照步進進行設置等等。

MV_E_GC_ACCESS 0x80000106 節點訪問條件有誤

解析:-2147483386/0x80000106
常見的問題類型有: 相機節點不存在或者無法訪問,例如,自動曝光,在手動曝光情況下,自動曝光節點會被隱藏,或者其他相機存在這個參數,而使用的相機無此參數,例如線掃相機的行頻參數等等,還比如說部分相機無此功能,例如event參數,部分相機固件暫不支持用戶調用。

MV_E_GC_TIMEOUT 0x80000107 超時

解析:-2147483385/0x80000107
GVCP命名包回復超時,一般出現在網絡環境不好的情況下,此時應該調用接口加大gvcp命令包等待時間(MV_GIGE_GetGvcpTimeout()),持續出現該報錯,應該排查網絡環境問題。

MV_E_ACCESS_DENIED 0x80000203 設備無訪問權限

解析:-2147483133/0x80000203常見問題有:
相機被其他軟件打開占用,關閉其他軟件,檢查設備管理器中,可能存在的殘留進程。
代碼debug下,心跳時間問題,等待60s后,可以重新打開(此問題參考心跳問題解決方法,可縮短打開時間)。
其余問題,例如一上電就打不開相機,需要重新插拔網線、USB線,就是其他問題,需要具體問題,具體分析。

MV_E_NETER 0x80000206 網絡相關錯誤

解析:-2147483130/0x80000206
此類報錯非常常見,主要分以下集中:
相機掉線,能夠在日志中發現大量的206報錯,此時需要去區分掉線原因,結合相機上電時間、心跳時間、相機權限,日志等信息,綜合判斷。
網線異常,導致相機掉線,也需要具體問題分析。

MV_E_IP_CONFLICT 0x80000221 設備IP沖突

解析:-2147483103/0x80000221
常見于IP設置時,當前ip已經被其他設備使用,需要更換ip重新設置。

MV_E_USB_READ 0x80000300 讀USB出錯

解析:-2147482880/0x80000300
USB讀取相機信息失敗,此類問題較為復制,與USB接口穩定性、線纜長度、電磁環境相關,往往不好分析,可以嘗試插拔一下,或者更換USB接口嘗試。

MV_E_USB_WRITE 0x80000301 寫USB出錯

解析:-2147482879/0x80000301
同0x80000300一樣,不好分析,可以嘗試插拔一下,或者更換USB接口嘗試。

MV_E_USB_DRIVER 0x80000305 驅動不匹配或者未裝驅動

解析: -2147482875/0x80000305
同0x80000300一樣,問題復雜,除了更換USB接口外,還可以嘗試更換sdk版本。

2.通過海康相機SDK熟悉C接口取圖流程和取圖方式

個人總結:句柄(void *handle)是相機開發中重要的一環,SDK中的接口中,大部分都是針對句柄的操作,如果有多個相機,要將每個相機和其對應的句柄關聯好,防止后期使用的過程中未及時釋放句柄、造成混亂等。

2.1 設備連接接口流程

??對設備進行操作,實現圖像采集、參數配置等功能,需要先連接設備(打開設備),具體流程如下圖所示:

??1.調用 MV_CC_EnumDevices() 枚舉子網內指定傳輸協議對應的所有設備。可以通過 pstDevList 在結構 MV_CC_DEVICE_INFO_LIST 中找到設備的信息。

#include "MvCameraControl.h"void main() {unsigned int nTLayerType = MV_GIGE_DEVICE | MV_USB_DEVICE;MV_CC_DEVICE_INFO_LIST m_stDevList = {0};int nRet = MV_CC_EnumDevices(nTLayerType, &m_stDevList);if (MV_OK != nRet){printf("error: EnumDevices fail [%x]\n", nRet);} }

??關于搜索到的所有相機設備信息在 MV_CC_DEVICE_INFO_LIST結構體中,

/// \~chinese 設備信息列表 \~english Device Information List typedef struct _MV_CC_DEVICE_INFO_LIST_ {unsigned int nDeviceNum; ///< [OUT] \~chinese 在線設備數量 \~english Online Device NumberMV_CC_DEVICE_INFO* pDeviceInfo[MV_MAX_DEVICE_NUM]; ///< [OUT] \~chinese 支持最多256個設備 \~english Support up to 256 devices}MV_CC_DEVICE_INFO_LIST;

??通過MV_CC_DEVICE_INFO結構體可以訪問每個設備的詳細信息,

/// \~chinese 設備信息 \~english Device info typedef struct _MV_CC_DEVICE_INFO_ {unsigned short nMajorVer; ///< [OUT] \~chinese 主要版本 \~english Major Versionunsigned short nMinorVer; ///< [OUT] \~chinese 次要版本 \~english Minor Versionunsigned int nMacAddrHigh; ///< [OUT] \~chinese 高MAC地址 \~english High MAC Addressunsigned int nMacAddrLow; ///< [OUT] \~chinese 低MAC地址 \~english Low MAC Addressunsigned int nTLayerType; ///< [OUT] \~chinese 設備傳輸層協議類型,e.g. MV_GIGE_DEVICE \~english Device Transport Layer Protocol Type, e.g. MV_GIGE_DEVICEunsigned int nReserved[4]; ///< \~chinese 預留 \~english Reservedunion{MV_GIGE_DEVICE_INFO stGigEInfo; ///< [OUT] \~chinese GigE設備信息 \~english GigE Device InfoMV_USB3_DEVICE_INFO stUsb3VInfo; ///< [OUT] \~chinese USB設備信息 \~english USB Device InfoMV_CamL_DEV_INFO stCamLInfo; ///< [OUT] \~chinese CameraLink設備信息 \~english CameraLink Device Info// more ...}SpecialInfo;}MV_CC_DEVICE_INFO;

??這里以我使用的網口相機GigE設備為例,要獲取到設備的詳細內容:

// 我通過std::map<std::string, std::tuple<void*,MV_CC_DEVICE_INFO*>>m_dev_info_list_;來存儲枚舉到的所示設備。 // 第一個參數的設備的名稱,這個可以自己定義,方便后面對哪一個相機進行操作; // 第二個參數是句柄 // 第三個參數就是MV_CC_DEVICE_INFO設備信息的結構體 MV_CC_DEVICE_INFO* pstMVDevInfo = std::get<1>(m_dev_info_list_[dev_name]);if (pstMVDevInfo->nTLayerType == MV_GIGE_DEVICE) {std::string model =(char*)pstMVDevInfo->SpecialInfo.stGigEInfo.chModelName;std::string cam_ip = "Current IP Address: " ;int nIp1 =((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0xff000000) >>24);int nIp2 =((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x00ff0000) >>16);int nIp3 =((pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x0000ff00) >>8);int nIp4 =(pstMVDevInfo->SpecialInfo.stGigEInfo.nCurrentIp & 0x000000ff);}

??有些參數我也沒搞懂是什么信息。。。

??2.在打開指定設備之前,調用 MV_CC_IsDeviceAccessible() 檢查指定設備是否可訪問。 (這一步在實際使用中并未用到)

??3.調用 MV_CC_CreateHandle() 以創建設備句柄。

#include "MvCameraControl.h"void main() {int nRet = -1;void* m_handle = NULL;//枚舉子網內指定的傳輸協議對應的所有設備unsigned int nTLayerType = MV_GIGE_DEVICE | MV_USB_DEVICE;MV_CC_DEVICE_INFO_LIST m_stDevList = {0};int nRet = MV_CC_EnumDevices(nTLayerType, &m_stDevList);if (MV_OK != nRet){printf("error: EnumDevices fail [%x]\n", nRet);return;}int i = 0;if (m_stDevList.nDeviceNum == 0){printf("no camera found!\n");return;}//選擇查找到的第一臺在線設備,創建設備句柄int nDeviceIndex = 0;MV_CC_DEVICE_INFO m_stDevInfo = {0};memcpy(&m_stDevInfo, m_stDevList.pDeviceInfo[nDeviceIndex], sizeof(MV_CC_DEVICE_INFO));nRet = MV_CC_CreateHandle(&m_handle, &m_stDevInfo);if (MV_OK != nRet){printf("error: CreateHandle fail [%x]\n", nRet);return;}//...其他處理//銷毀句柄,釋放資源nRet = MV_CC_DestroyHandle(m_handle);if (MV_OK != nRet){printf("error: DestroyHandle fail [%x]\n", nRet);return;} }

??4.調用 MV_CC_OpenDevice() 打開設備。

??去該API定義后發現,后面兩個參數有默認值,所以實際使用中只需要輸入第一個參數設備的句柄即可。

/********************************************************************//*** @~chinese* @brief 打開設備* @param handle [IN] 設備句柄* @param nAccessMode [IN] 訪問權限* @param nSwitchoverKey [IN] 切換訪問權限時的密鑰* @return 成功,返回MV_OK;錯誤,返回錯誤碼 * @remarks 根據設置的設備參數,找到對應的設備,連接設備。\n 調用接口時可不傳入nAccessMode和nSwitchoverKey,此時默認設備訪問模式為獨占權限。目前設備暫不支持MV_ACCESS_ExclusiveWithSwitch、MV_ACCESS_ControlWithSwitch、MV_ACCESS_ControlSwitchEnable、MV_ACCESS_ControlSwitchEnableWithKey這四種搶占模式。\n 對于U3V設備,nAccessMode、nSwitchoverKey這兩個參數無效。 */ #ifndef __cplusplus MV_CAMCTRL_API int __stdcall MV_CC_OpenDevice(IN void* handle, IN unsigned int nAccessMode, IN unsigned short nSwitchoverKey); #else MV_CAMCTRL_API int __stdcall MV_CC_OpenDevice(IN void* handle, IN unsigned int nAccessMode = MV_ACCESS_Exclusive, IN unsigned short nSwitchoverKey = 0); #endif int nRet = MV_CC_OpenDevice(m_handle);

??5.調用 MV_CC_CloseDevice() 關閉設備。

??6.調用 MV_CC_DestroyHandle() 來銷毀句柄并釋放資源。

2.2 相機取圖——主動取流

??SDK提供主動獲取圖像的接口,用戶可以在開啟取流后直接調用此接口獲取圖像,也可以使用異步方式(線程、定時器等)獲取圖像。示例代碼詳見 GrabImage.cpp 和 GrabImage_HighPerformance.cpp 。

  • 主動獲取圖像有兩種方式(兩種方式不能同時使用)
    方式一:調用 MV_CC_StartGrabbing() 開始采集,需要自己開啟一個buffer,然后在應用層循環調用 MV_CC_GetOneFrameTimeout() 獲取指定像素格式的幀數據,獲取幀數據時上層應用程序需要根據幀率控制好調用該接口的頻率。
    方式二:調用 MV_CC_StartGrabbing() 開始采集,然后在應用層調用 MV_CC_GetImageBuffer() 獲取指定像素格式的幀數據,然后調用 MV_CC_FreeImageBuffer() 釋放buffer,獲取幀數據時上層應用程序需要根據幀率控制好調用該接口的頻率。
  • 主動取圖方式使用的場景
    主動取圖方式需要先調用 MV_CC_StartGrabbing() 啟動圖像采集。上層應用程序需要根據幀率,控制好調用主動取圖接口的頻率。兩種主動取圖方式都支持設置超時時間,SDK內部等待直到有數據時返回,可以增加取流平穩性,適合用于對平穩性要求較高的場合。
  • 兩種主動取圖方式的區別
    a、 MV_CC_GetImageBuffer() 需要與 MV_CC_FreeImageBuffer() 配套使用,當處理完取到的數據后,需要用 MV_CC_FreeImageBuffer() 接口將pstFrame內的數據指針權限進行釋放。
    b、 MV_CC_GetImageBuffer()MV_CC_GetOneFrameTimeout() 相比,有著更高的效率。且其取流緩存的分配是由sdk內部自動分配的,而 MV_CC_GetOneFrameTimeout() 接口是需要客戶自行分配。

這里我使用方式一的取圖流程。

??1.開始取流。

??2.停止取流。

??3.方式一的取圖方式,采用超時機制獲取一幀圖片,SDK內部等待直到有數據時返回。

所獲取的幀屬于裸數據,數據保存在pData,并無圖像格式(具體數據格式可以提前設定)。pFrameInfo表示輸出幀的信息。

??可以通過函數MV_CC_Display(IN void* handle, IN void* hWnd)來實時顯示采集到的圖像。該函數需要在MV_CC_StartGrabbing之后調用,顯示采集到的圖像。如果相機當前采集圖像是JPEG壓縮的格式,則不支持調用該函數接口進行顯示。

??可以通過函數MV_CC_SaveImage(IN&OUT MV_SAVE_IMAGE_PARAM* pSaveParam)將原始圖像數據轉換成圖片格式并保存在指定內存里,再通過函數fwrite寫入文件中。
??也可以通過函數MV_CC_SaveImageEx將原始圖像數據轉換成圖片格式并保存在指定內存中,可支持設置JPEG編碼質量。

??可通過函數memcpy(OUT void* dst, IN void const* src, IN size_t size) 把資源內存(src所指向的內存區域)拷貝到目標內存(dest所指向的內存區域),從而將unsigned char格式的圖像數據轉換為QImage格式的圖像數據,這里要注意輸入數據的格式,代碼中輸入的unsigned char pFrameBuf數據格式分別為Mono8的灰度圖像和RGB8_Packed的彩色圖像。

#include "MvCameraControl.h"void main() {int nRet = -1;void* m_handle = NULL;//枚舉子網內指定的傳輸協議對應的所有設備unsigned int nTLayerType = MV_GIGE_DEVICE | MV_USB_DEVICE;MV_CC_DEVICE_INFO_LIST m_stDevList = {0};int nRet = MV_CC_EnumDevices(nTLayerType, &m_stDevList);if (MV_OK != nRet){printf("error: EnumDevices fail [%x]\n", nRet);return;}int i = 0;if (m_stDevList.nDeviceNum == 0){printf("no camera found!\n");return;}//選擇查找到的第一臺在線設備,創建設備句柄int nDeviceIndex = 0;MV_CC_DEVICE_INFO m_stDevInfo = {0};memcpy(&m_stDevInfo, m_stDevList.pDeviceInfo[nDeviceIndex], sizeof(MV_CC_DEVICE_INFO));nRet = MV_CC_CreateHandle(&m_handle, &m_stDevInfo);if (MV_OK != nRet){printf("error: CreateHandle fail [%x]\n", nRet);return;}//連接設備nRet = MV_CC_OpenDevice(m_handle, nAccessMode, nSwitchoverKey);if (MV_OK != nRet){printf("error: OpenDevice fail [%x]\n", nRet);return;}//...其他處理 //開始采集圖像nRet = MV_CC_StartGrabbing(m_handle);if (MV_OK != nRet){printf("error: StartGrabbing fail [%x]\n", nRet);return;}//獲取一幀數據的大小MVCC_INTVALUE stIntvalue = {0};nRet = MV_CC_GetIntValue(m_handle, "PayloadSize", &stIntvalue);if (nRet != MV_OK){printf("Get PayloadSize failed! nRet [%x]\n", nRet);return;}int nBufSize = stIntvalue.nCurValue; //一幀數據大小unsigned int nTestFrameSize = 0;unsigned char* pFrameBuf = NULL;pFrameBuf = (unsigned char*)malloc(nBufSize);MV_FRAME_OUT_INFO_EX stInfo;memset(&stInfo, 0, sizeof(MV_FRAME_OUT_INFO_EX));//上層應用程序需要根據幀率,控制好調用該接口的頻率//此次代碼僅供參考,實際應用建議另建線程進行圖像幀采集和處理while(1){if (nTestFrameSize > 99) {break;}nRet = MV_CC_GetOneFrameTimeout(m_handle, pFrameBuf, nBufSize, &stInfo, 1000);if (MV_OK != nRet){Sleep(10);}else{//...圖像數據處理nTestFrameSize++;}}//...其他處理//停止采集圖像 nRet = MV_CC_StopGrabbing(m_handle);if (MV_OK != nRet){printf("error: StopGrabbing fail [%x]\n", nRet);return;}//關閉設備,釋放資源nRet = MV_CC_CloseDevice(m_handle);if (MV_OK != nRet){printf("error: CloseDevice fail [%x]\n", nRet);return;}//銷毀句柄,釋放資源nRet = MV_CC_DestroyHandle(m_handle);if (MV_OK != nRet){printf("error: DestroyHandle fail [%x]\n", nRet);return;} }

SDK還提供了回調出流的方法,這里我沒研究,如果大佬采用的這種方式,也可以一起交流,方便我學習。

2.3 設置相機的一些參數

/********************************************************************//*** @~chinese* @brief 設置Enum型屬性值* @param handle [IN] 設備句柄* @param strKey [IN] 屬性鍵值,如獲取像素格式信息則為"PixelFormat"* @param nValue [IN] 想要設置的設備的屬性值* @return 成功,返回MV_OK,失敗,返回錯誤碼* @remarks 連接設備之后調用該接口可以設置Enum類型的指定節點的值。strKey取值可以參考XML節點參數類型列表,表格里面數據類型為“IEnumeration”的節點值都可以通過該接口設置,strKey參數取值對應列表里面的“名稱”一列。 ************************************************************************/ MV_CAMCTRL_API int __stdcall MV_CC_SetEnumValue(IN void* handle,IN const char* strKey,IN unsigned int nValue);/********************************************************************//*** @~chinese* @brief 設置float型屬性值* @param handle [IN] 設備句柄* @param strKey [IN] 屬性鍵值* @param fValue [IN] 想要設置的設備的屬性值* @return 成功,返回MV_OK,失敗,返回錯誤碼* @remarks 連接設備之后調用該接口可以設置float類型的指定節點的值。strKey取值可以參考XML節點參數類型列表,表格里面數據類型為“IFloat”的節點值都可以通過該接口設置,strKey參數取值對應列表里面的“名稱”一列。 ************************************************************************/ MV_CAMCTRL_API int __stdcall MV_CC_SetFloatValue(IN void* handle,IN const char* strKey,IN float fValue);

??關于輸入參數參考相機中的節點。

int setCameraParametMode(const char* str_key, unsigned int val) {// TriggerMode 0: Off 1: On// TriggerSource 0:Line0 1:Line1 7:Software// GainAuto 0: Off 1: Once 2: Continuousint temp_val = MV_CC_SetEnumValue(m_handle, str_key, val);if (temp_val != 0) {return -1;}else {return 0;} }int setCameraParametValue(const char* str_type, float num_val) {// ExposureTime// Gainint temp_value = MV_CC_SetFloatValue(m_handle, str_type, num_val);if (temp_value != 0) {return -1;}else {return 0;} }

??使用:

camera_obj->setCameraParametMode("ExposureAuto", 0); camera_obj->setCameraParametValue("ExposureTime", exposure_time); camera_obj->setCameraParametMode("GainAuto", 0); camera_obj->setCameraParametValue("Gain", gain);

3.將相機抓取到的圖像轉為Mat格式,方便后續使用

/************************************************************************* @fn MV_CAMCTRL_API int __stdcall MV_CC_GetIntValue(IN void* handle,IN const char* strKey,OUT MVCC_INTVALUE *pIntValue);* @brief 獲取Integer屬性值(建議改用MV_CC_GetIntValueEx接口)* @param void* handle [IN] 相機句柄* @param char* strKey [IN] 屬性鍵值,如獲取寬度信息則為"Width"* @param MVCC_INTVALUE* pstValue [IN][OUT] 返回給調用者有關相機屬性結構體指針* @return 成功,返回MV_OK,失敗,返回錯誤碼 ************************************************************************/ MV_CAMCTRL_API int __stdcall MV_CC_GetIntValue(IN void* handle,IN const char* strKey,OUT MVCC_INTVALUE *pIntValue);
  • 相機采集到的圖像格式是buffer,需要將其轉化為Mat類型。
int HikCamera::CameraOneFrameImageToMat(void* dev_handle,const std::string& dev_name, cv::Mat& image) {cv::Mat* getImage = new cv::Mat();unsigned int nRecvBufSize = 0;MVCC_INTVALUE stParam;memset(&stParam, 0, sizeof(MVCC_INTVALUE));int tempValue = MV_CC_GetIntValue(dev_handle, "PayloadSize", &stParam);if (tempValue != 0) {return -1;}nRecvBufSize = stParam.nCurValue;unsigned char* pDate;pDate = (unsigned char*)malloc(nRecvBufSize);MV_FRAME_OUT_INFO_EX stImageInfo = { 0 };tempValue = MV_CC_GetOneFrameTimeout(dev_handle, pDate, nRecvBufSize,&stImageInfo, 500);if (tempValue != 0) {return -1;}m_nBufSizeForSaveImage_ =stImageInfo.nWidth * stImageInfo.nHeight * 3 + 2048;unsigned char* m_pBufForSaveImage;m_pBufForSaveImage = (unsigned char*)malloc(m_nBufSizeForSaveImage_);bool isMono; //判斷是否為黑白圖像switch (stImageInfo.enPixelType) {case PixelType_Gvsp_Mono8:case PixelType_Gvsp_Mono10:case PixelType_Gvsp_Mono10_Packed:case PixelType_Gvsp_Mono12:case PixelType_Gvsp_Mono12_Packed:isMono = true;break;default:isMono = false;break;}if (isMono) {*getImage =cv::Mat(stImageInfo.nHeight, stImageInfo.nWidth, CV_8UC1, pDate);}else {// 轉換圖像格式為BGR8MV_CC_PIXEL_CONVERT_PARAM stConvertParam = { 0 };memset(&stConvertParam, 0, sizeof(MV_CC_PIXEL_CONVERT_PARAM));stConvertParam.nWidth = stImageInfo.nWidth;stConvertParam.nHeight = stImageInfo.nHeight;stConvertParam.pSrcData = pDate;stConvertParam.nSrcDataLen = stImageInfo.nFrameLen; // 輸入數據大小stConvertParam.enSrcPixelType = stImageInfo.enPixelType; // 輸入像素格式stConvertParam.enDstPixelType = PixelType_Gvsp_BGR8_Packed; // 輸出像素格式stConvertParam.pDstBuffer = m_pBufForSaveImage; // 輸出數據緩存stConvertParam.nDstBufferSize = m_nBufSizeForSaveImage_; // 輸出緩存大小MV_CC_ConvertPixelType(dev_handle, &stConvertParam);*getImage = cv::Mat(stImageInfo.nHeight, stImageInfo.nWidth, CV_8UC3, m_pBufForSaveImage);}(*getImage).copyTo(image);(*getImage).release();free(pDate);free(m_pBufForSaveImage);return 0; }

4.將Mat格式圖像轉為QImage格式,用于UI界面上控件的顯示

??轉化為Mat后,通過display_myImage_L再將Mat轉化為QImage類型,進行在控件上顯示。軟觸發的話,就是采集到當前幀圖像,通過display_myImage_L顯示,連續采集的話,通過多線程,將線程對象myThread_camera_L_show發送信號display給主線程,主線程調用display_myImage_L將相機采集到的圖像進行顯示。

void display_myImage_L(const cv::Mat* image_ptr) {cv::Mat rgb;// cv::cvtColor(*imagePrt, rgb, CV_BGR2RGB);//判斷是黑白、彩色圖像QImage QmyImage_L;if (lbl_camera_L_image->channels() > 1) {cv::cvtColor(*image_ptr, rgb, CV_BGR2RGB);QmyImage_L = QImage((const unsigned char*)(rgb.data), rgb.cols,rgb.rows, QImage::Format_RGB888);}else {cv::cvtColor(*image_ptr, rgb, CV_GRAY2RGB);QmyImage_L = QImage((const unsigned char*)(rgb.data), rgb.cols,rgb.rows, QImage::Format_RGB888);}QmyImage_L = (QmyImage_L).scaled(ui.lbl_camera_L->size(), Qt::IgnoreAspectRatio,Qt::SmoothTransformation);ui.lbl_camera_L->setPixmap(QPixmap::fromImage(QmyImage_L)); }

參考博文:
https://cloud.tencent.com/developer/article/1730933
https://blog.csdn.net/weixin_46421489/article/details/116381368
關于相機SDK開發
https://cloud.tencent.com/developer/article/1730940

總結

以上是生活随笔為你收集整理的海康威视工业相机SDK的开发使用笔记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。