最近項目中要用到一款IDS的相機,型號是UI-3060CP ,這是一款USB3.0相機。IDS官網提供了不同操作系統的開發包,有相當詳細開發說明。註冊後便可以下載,鏈接爲:https://en.ids-imaging.com/download-ueye-win32.html
首先下載了windows下的開發包,默認安裝後可以正常打相機,然後開始嘗試利用vs2010+opencv進行二次開發。
1.配置環境,ids的軟件包默認安裝目錄爲C:\Program Files\IDS\uEye
2.新建工程文件並配置鏈接庫,vs2010下配置過程類似於opencv的配置
①【配置屬性】 ->【C/C++】 ->【常規】->【附加包含目錄】
添加路徑 C:\Program Files\IDS\uEye\Develop\include;②【鏈接器】 ->【常規】 ->【附加庫目錄】中
添加路徑 C:\Program Files\IDS\uEye\Develop\Lib;③鏈接庫的附加依賴項的配置:【鏈接器】 ->【輸入】 ->【附加依賴項】中
添加
kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib
ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ueye_api.lib
3.主體程序部分,相機的使用主要包括以下部分
至此開發環境配置完成。
爲方便相機的調用創建了一個Idscam的C++類。。。。。
其頭文件如下:
#include "ueye.h"
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
class Idscam{
public:
Idscam();
INT InitCamera (HIDS *hCam, HWND hWnd); //初始化相機 hWnd指向顯示圖像窗口的指針,若用DIB模式可以令hWnd=NULL
bool OpenCamera();
void ExitCamera();
int InitDisplayMode();
void GetMaxImageSize(INT *pnSizeX, INT *pnSizeY);//查詢相機支持的圖像格式
void SaveImage( );
bool GetiplImgFormMem(); //從視頻數據流中將圖像數據拷貝給IplImage
// uEye varibles
HIDS m_hCam; // 相機句柄
HWND m_hWndDisplay; // window顯示句柄
INT m_nColorMode; // Y8/RGB16/RGB24/REG32
INT m_nBitsPerPixel; // 圖像位深
INT m_nSizeX; // 圖像寬度
INT m_nSizeY; // 圖像高度
INT m_nPosX; // 圖像左偏移
INT m_nPosY; // 圖像右偏移
cv::Mat CamMat;
IplImage *iplImg;
char *m_pLastBuffer;
private:
// 使用位圖模式進行實時顯示需要的內存
INT m_lMemoryId; // camera memory - buffer ID
char* m_pcImageMemory; // camera memory - pointer to buffer
SENSORINFO m_sInfo; // sensor information struct
INT m_nRenderMode; // render mode
INT m_nFlipHor; // 水平翻轉標誌
INT m_nFlipVert; // 垂直翻轉標誌
};
對應實現爲:
#include"Idscam.h"
#include <string>
#include <iostream>
using namespace std;
Idscam::Idscam(){
m_pcImageMemory = NULL;
m_lMemoryId = 0;
m_hCam = 0; //初始化相機句柄爲0
m_nRenderMode = IS_RENDER_FIT_TO_WINDOW; //設置顯示模式爲適應窗口大小
m_nPosX = 0;
m_nPosY = 0;
m_nFlipHor = 0;
m_nFlipVert = 0;
iplImg=cvCreateImageHeader( cvSize(1936,1216),8,4 );
OpenCamera();
}
bool Idscam::OpenCamera(){
INT nRet = IS_NO_SUCCESS;
ExitCamera();
m_hCam = (HIDS) 0;
nRet = InitCamera(&m_hCam, m_hWndDisplay); // 1.初始化相機
if (nRet == IS_SUCCESS){ // 打開相機成功
// 查詢相機所用傳感器的類型
is_GetSensorInfo(m_hCam, &m_sInfo); //2.查詢信息
GetMaxImageSize(&m_nSizeX, &m_nSizeY);
nRet = InitDisplayMode(); //3.選擇顯示模式(位圖)
if (nRet == IS_SUCCESS)
{
// 允許接受消息
is_EnableMessage(m_hCam, IS_DEVICE_REMOVED, NULL);
is_EnableMessage(m_hCam, IS_DEVICE_RECONNECTED, NULL);
is_EnableMessage(m_hCam, IS_FRAME, NULL);
is_CaptureVideo( m_hCam, IS_WAIT ); //4.設定捕捉模式:自由運行模式下的實時模式
return true;
}
else{
printf("初始化顯示模式失敗!");
return false;
}
}
else{
printf("沒有發現uEye相機!");
return false;
}
}
void Idscam:: ExitCamera()
{
if( m_hCam != 0 )
{
// 調用 hWnd = NULL函數禁用Windows消息
is_EnableMessage( m_hCam, IS_FRAME, NULL );
// 在曝光未開始時停止實時模式或取消硬件觸發的圖像捕捉
is_StopLiveVideo( m_hCam, IS_WAIT );
// 釋放分配的圖像內存
if( m_pcImageMemory != NULL )
is_FreeImageMem( m_hCam, m_pcImageMemory, m_lMemoryId );
m_pcImageMemory = NULL;
// 關閉相機
is_ExitCamera( m_hCam );
m_hCam = NULL;
}
}
//1.初始化相機
INT Idscam::InitCamera (HIDS *hCam, HWND hWnd)
{
INT nRet = is_InitCamera (hCam, hWnd);
if (nRet == IS_STARTER_FW_UPLOAD_NEEDED)//相機的啓動程序固件和驅動不兼容,需要更新固件版本
{
INT nUploadTime = 25000; //默認更新時間爲25S
is_GetDuration (*hCam, IS_STARTER_FW_UPLOAD, &nUploadTime);
printf("This camera requires a new firmware !\n");
printf("The upload will take about %f seconds. Please wait ...\n",nUploadTime/1000);
//再次打開相機並自動更新固件
*hCam = (HIDS) (((INT)*hCam) | IS_ALLOW_STARTER_FW_UPLOAD);
nRet = is_InitCamera (hCam, NULL);
}
printf("初始化相機成功 !\n");
return nRet;
}
int Idscam::InitDisplayMode()
{
INT nRet = IS_NO_SUCCESS;
if (m_hCam == NULL)
return IS_NO_SUCCESS;
if (m_pcImageMemory != NULL) //釋放通過 is_AllocImageMem() 函數分配的圖像內存
{
is_FreeImageMem( m_hCam, m_pcImageMemory, m_lMemoryId );
//如果圖像內存不是通過SDK分配,則需調用 is_FreeImageMem() 函數。否則驅動會繼續嘗試訪問該內存。
//但是這並不能釋放內存。因此,必須確保可再次釋放內存。
}
m_pcImageMemory = NULL;
// 設置位圖模式
nRet = is_SetDisplayMode(m_hCam, IS_SET_DM_DIB);
if (m_sInfo.nColorMode == IS_COLORMODE_BAYER)
{
// 如果是拜耳色 則設置位深爲當前窗口的設置,linux 下不可以這麼設置
// 用於檢索當前Windows桌面的顏色設置並返回每像素位深及相匹配的uEye色彩模式
is_GetColorDepth(m_hCam, &m_nBitsPerPixel, &m_nColorMode);
}
else if (m_sInfo.nColorMode == IS_COLORMODE_CBYCRY)
{
m_nColorMode = IS_CM_BGRA8_PACKED;
m_nBitsPerPixel = 32;
}
else
{
m_nColorMode = IS_CM_MONO8;
m_nBitsPerPixel = 8;
}
// 分配圖像內存,圖像尺寸有 m_nSizeX和m_nSizeY確定,色彩位深由m_nBitsPerPixel確定,m_pcImageMemory返回起始地址,m_lMemoryId 返回已分配內存的ID
if (is_AllocImageMem(m_hCam, m_nSizeX, m_nSizeY, m_nBitsPerPixel, &m_pcImageMemory, &m_lMemoryId ) != IS_SUCCESS)
{
printf("相機內存分配出錯!");
}
else
is_SetImageMem( m_hCam, m_pcImageMemory, m_lMemoryId );
/* INT is_SetImageMem (HIDS hCam, char* pcImgMem, INT id)用於將指定的圖像內存變爲活動內存。
只有活動圖像內存可以接收圖像數據。
在調用 is_FreezeVideo() 時,捕捉的圖像會存儲在 pcImgMem 和 id 指定的圖像緩衝區中。
捕捉的圖像會存儲在 pcImgMem 和 id 指定的圖像緩衝區中。對於 pcImgMem,
您必須傳遞 is_AllocImageMem() 創建的指針,傳遞任何其他指針均會發出錯誤信息。
您可以多次傳遞同樣的指針。 */
if (nRet == IS_SUCCESS)
{
// 設置顯卡在保存或顯示圖像數據時所使用的色彩模
is_SetColorMode(m_hCam, m_nColorMode);
// set the image size to capture
IS_SIZE_2D imageSize;
imageSize.s32Width = m_nSizeX;
imageSize.s32Height = m_nSizeY;
//設置圖像感興趣區域(AOI)的大小和位置
is_AOI(m_hCam, IS_AOI_IMAGE_SET_SIZE, (void*)&imageSize, sizeof(imageSize));
}
return nRet;
}
void Idscam::GetMaxImageSize(INT *pnSizeX, INT *pnSizeY)
{
INT nAOISupported = 0;
BOOL bAOISupported = TRUE;
if (is_ImageFormat(m_hCam,
IMGFRMT_CMD_GET_ARBITRARY_AOI_SUPPORTED,
(void*)&nAOISupported,
sizeof(nAOISupported)) == IS_SUCCESS)
{
bAOISupported = (nAOISupported != 0);
}
if (bAOISupported)
{
// All other sensors
// Get maximum image size
SENSORINFO sInfo;
is_GetSensorInfo (m_hCam, &sInfo);
*pnSizeX = sInfo.nMaxWidth;
*pnSizeY = sInfo.nMaxHeight;
}
else
{
// Only ueye xs
// Get image size of the current format
IS_SIZE_2D imageSize;
is_AOI(m_hCam, IS_AOI_IMAGE_GET_SIZE, (void*)&imageSize, sizeof(imageSize));
*pnSizeX = imageSize.s32Width;
*pnSizeY = imageSize.s32Height;
}
}
bool Idscam::GetiplImgFormMem(){ //實時獲取圖像時需要不斷刷新此函數
if(!m_hCam) return false;
char *pLast = NULL, *pMem = NULL;
INT dummy = 0;
//確定當前用於捕捉圖像的圖像內存 pMem,最後一個用於捕捉圖像的圖像內存pLast
is_GetActSeqBuf (m_hCam, &dummy, &pMem, &pLast);
m_pLastBuffer = pLast;
if (m_pLastBuffer)
{
iplImg->imageData = m_pLastBuffer; //將圖像首地址傳給iplImg
return true;
}
else
return false;
}
void Idscam::SaveImage( ){
IMAGE_FILE_PARAMS ImageFileParams;
ImageFileParams.pwchFileName = NULL;
ImageFileParams.pnImageID = NULL;
ImageFileParams.ppcImageMem = NULL;
ImageFileParams.nQuality = 0;
ImageFileParams.nFileType = IS_IMG_BMP;
INT nRet = is_ImageFile(m_hCam, IS_IMAGE_FILE_CMD_SAVE, (void*)&ImageFileParams,
sizeof(ImageFileParams));
//保存活動內存中的jpeg圖像,圖像畫質爲100
ImageFileParams.pwchFileName = L"CamIds.jpg";
ImageFileParams.nFileType = IS_IMG_JPG; //待保存文件的類型
ImageFileParams.nQuality = 100; //100爲最佳圖像畫質(無壓縮)
nRet = is_ImageFile(m_hCam, IS_IMAGE_FILE_CMD_SAVE, (void*)&ImageFileParams,
sizeof(ImageFileParams));
}
在主程序中創建一個Idscam類,默認初始化會直接打開相機,調用函數GetiplImgFormMem()和變量iplImg即可得到相機獲取的圖片。
這裏並沒有創建線程一直刷新相機,所以獲取只能獲取初始捕捉到的畫面。
主程序爲:
#include <cv.h>
#include <highgui.h>
#include"Idscam.h"
char* window_name = "Source Video";
int main()
{
Idscam *mycam;
mycam = new Idscam();
if(mycam->GetiplImgFormMem())
cvShowImage(window_name,mycam->iplImg);
cvWaitKey(3000);
return 0;
}
成功打開相機並得到相機畫面。
由於項目環境是linux,故對windows下的開發並未做過多研究。