1. 程式人生 > >VS2015+OpenCV+大恆MER-Gx系列工業相機

VS2015+OpenCV+大恆MER-Gx系列工業相機

VS2015+OpenCV+大恆MER-Gx系列工業相機


本人C++和OpenCV基礎比較薄弱,VS2015龐雜的處理介面又讓人應接不暇。之前偶爾使用網路攝像頭,勉強能夠完成基礎操作;偶爾進行離線處理,也還應付的過來。這次專案需求,購買了大恆MER-Gx系列工業相機(GigE網路介面),離我的專業知識跨度很大,因此查了很多資料,在此分享一下。

1.實驗所需

1)VS2015
2)OpenCV,解壓並完成環境變數配置
3)大恆MER-Gx系列工業相機

2.建立C++專案

1)新建Win32控制檯專案,切記,選擇空專案!否則會遇到我也難以解釋的問題…
2)右鍵專案——屬性——VC++目錄——包含目錄,先新增OpenCV的三個目錄(…\include以及其兩個子目錄…\include\opencv,…\include\opencv2),然後新增大恆SDK的\VC SDK 和 \C++ SDK兩個inc目錄。(一共5個目錄)
新增包含目錄

3)同樣在VC++目錄下,點選庫目錄,先新增OpenCV的庫目錄,再新增大恆SDK的\VC SDK 和 \C++ SDK兩個lib目錄。(一共3個目錄)
新增庫目錄
4)回到專案——屬性,我們選擇連結器——輸入 下的“附加依賴項”,手動輸入需要新增的庫檔案。首先是opencv庫目錄下的*d.lib檔案,然後是大恆SDK目錄下的三個.lib檔案。
新增“附加依賴項”

3. 新增原始檔

右鍵原始檔,新增,自己命名吧。

然後複製、執行下列程式碼:
記得執行之前將解決方案改成debug和x64(當然還是根據自己的來)。

#include "GxIAPI.h"  
#include "DxImageProc.h"  
#include <opencv2/core/core.hpp>  
#include <opencv2/imgproc/imgproc.hpp>  
#include <opencv2/highgui/highgui.hpp>  
#include <iostream>  

using namespace std;
using namespace cv;

GX_DEV_HANDLE       m_hDevice;              ///< 裝置控制代碼  
BYTE                *m_pBufferRaw;          ///< 原始影象資料  
BYTE                *m_pBufferRGB;          ///< RGB影象資料,用於顯示和儲存bmp影象  
int64_t             m_nImageHeight;         ///< 原始影象高  
int64_t             m_nImageWidth;          ///< 原始影象寬  
int64_t             m_nPayLoadSize;
int64_t             m_nPixelColorFilter;    ///< Bayer格式  
Mat test;
//影象回撥處理函式  
static void GX_STDC OnFrameCallbackFun(GX_FRAME_CALLBACK_PARAM* pFrame)
{
	//PrepareForShowImg();  
	if (pFrame->status == 0)
	{
		//對影象進行某些操作  
		/*memcpy(m_pBufferRaw, pFrame->pImgBuf, pFrame->nImgSize);
		// 黑白相機需要翻轉資料後顯示
		for (int i = 0; i <m_nImageHeight; i++)      {
		memcpy(m_pImageBuffer + i*m_nImageWidth, m_pBufferRaw + (m_nImageHeight - i - 1)*m_nImageWidth, (size_t)m_nImageWidth);
		}
		IplImage* src;
		src = cvCreateImage(cvSize(m_nImageWidth, m_nImageHeight), 8, 1);
		src->imageData = (char*)m_pImageBuffer;
		cvSaveImage("src.jpg", src);*/
		memcpy(m_pBufferRaw, pFrame->pImgBuf, pFrame->nImgSize);

		// RGB轉換  
		DxRaw8toRGB24(m_pBufferRaw
			, m_pBufferRGB
			, (VxUint32)(m_nImageWidth)
			, (VxUint32)(m_nImageHeight)
			, RAW2RGB_NEIGHBOUR
			, DX_PIXEL_COLOR_FILTER(m_nPixelColorFilter)
			, false);
		//  cv_Image->imageData = (char*)m_pBufferRGB;  

		//  cvSaveImage("./test.bmp", cv_Image);  

		//test.data = m_pBufferRaw;  
		memcpy(test.data, m_pBufferRGB, m_nImageWidth*m_nImageHeight * 3);
		imwrite("./test1.bmp", test);
		namedWindow("test");
		imshow("test", test);
		waitKey(15);

	}
	return;
}

int main(int argc, char* argv[])
{
	GX_STATUS emStatus = GX_STATUS_SUCCESS;
	GX_OPEN_PARAM openParam;
	uint32_t      nDeviceNum = 0;
	openParam.accessMode = GX_ACCESS_EXCLUSIVE;
	openParam.openMode = GX_OPEN_INDEX;
	openParam.pszContent = "1";
	// 初始化庫   
	emStatus = GXInitLib();
	if (emStatus != GX_STATUS_SUCCESS)
	{
		return 0;
	}
	// 列舉裝置列表  
	emStatus = GXUpdateDeviceList(&nDeviceNum, 1000);
	if ((emStatus != GX_STATUS_SUCCESS) || (nDeviceNum <= 0))
	{
		return 0;
	}
	//開啟裝置  
	emStatus = GXOpenDevice(&openParam, &m_hDevice);
	//設定採集模式連續採集  
	emStatus = GXSetEnum(m_hDevice, GX_ENUM_ACQUISITION_MODE, GX_ACQ_MODE_CONTINUOUS);
	emStatus = GXSetInt(m_hDevice, GX_INT_ACQUISITION_SPEED_LEVEL, 1);
	emStatus = GXSetEnum(m_hDevice, GX_ENUM_BALANCE_WHITE_AUTO, GX_BALANCE_WHITE_AUTO_CONTINUOUS);
	bool      bColorFliter = false;
	// 獲取影象大小  
	emStatus = GXGetInt(m_hDevice, GX_INT_PAYLOAD_SIZE, &m_nPayLoadSize);
	// 獲取寬度  
	emStatus = GXGetInt(m_hDevice, GX_INT_WIDTH, &m_nImageWidth);
	// 獲取高度  
	emStatus = GXGetInt(m_hDevice, GX_INT_HEIGHT, &m_nImageHeight);
	test.create(m_nImageHeight, m_nImageWidth, CV_8UC3);
	//判斷相機是否支援bayer格式  
	bool m_bColorFilter;
	emStatus = GXIsImplemented(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_bColorFilter);
	if (m_bColorFilter)
	{
		emStatus = GXGetEnum(m_hDevice, GX_ENUM_PIXEL_COLOR_FILTER, &m_nPixelColorFilter);
	}
	m_pBufferRGB = new BYTE[(size_t)(m_nImageWidth * m_nImageHeight * 3)];
	if (m_pBufferRGB == NULL)
	{
		return false;
	}
	//為儲存原始影象資料申請空間  
	m_pBufferRaw = new BYTE[(size_t)m_nPayLoadSize];
	if (m_pBufferRaw == NULL)
	{
		delete[]m_pBufferRGB;
		m_pBufferRGB = NULL;
		return false;
	}
	//註冊影象處理回撥函式  
	emStatus = GXRegisterCaptureCallback(m_hDevice, NULL, OnFrameCallbackFun);
	//傳送開採命令  
	emStatus = GXSendCommand(m_hDevice, GX_COMMAND_ACQUISITION_START);
	//---------------------  
	//  
	//在這個區間影象會通過OnFrameCallbackFun介面返給使用者  
	Sleep(100000);
	//  
	//---------------------  
	//傳送停採命令  
	emStatus = GXSendCommand(m_hDevice, GX_COMMAND_ACQUISITION_STOP);
	//登出採集回撥  
	emStatus = GXUnregisterCaptureCallback(m_hDevice);
	if (m_pBufferRGB != NULL)
	{
		delete[]m_pBufferRGB;
		m_pBufferRGB = NULL;
	}
	if (m_pBufferRaw != NULL)
	{
		delete[]m_pBufferRaw;
		m_pBufferRaw = NULL;
	}
	emStatus = GXCloseDevice(m_hDevice);
	emStatus = GXCloseLib();
	return 0;
}

對了,執行程式碼時會提示DxImageProc.h檔案裡有一行執行不了,具體是打不開“stdafx.h”,我遮蔽了就好了。應該是沒有適配VS2015的問題。

4.感言

現在終於可以聯合使用OpevCV與大恆SDK,成功打開了大恆相機!接下來,讀懂程式碼,在合適的地方做修改就好了!