Dalsa 相机拍摄图像丢帧(模糊)解决办法

Dalsa相机图像丢帧可能存在的原因

1、硬件原因

(1)硬件主要涉及网线和网卡的选择,Dalsa相机最好选择千兆网线千兆网卡。若一台PC需要连接多个相机,最好添加对应个数的网卡;

(2)网卡配置:对应网卡需要进行配置,配置方法如下所示:

①打开“网络连接”,选择对应网卡,右键选择“属性”;

Dalsa 相机拍摄图像丢帧(模糊)解决办法_第1张图片

②选择“配置”

Dalsa 相机拍摄图像丢帧(模糊)解决办法_第2张图片

③选择“高级”,配置“巨帧数据包”,选择最大(9014字节);“速度和双工”,选择最大(1.0 Gbps全双工)。

Dalsa 相机拍摄图像丢帧(模糊)解决办法_第3张图片 Dalsa 相机拍摄图像丢帧(模糊)解决办法_第4张图片

至此,和硬件相关的配置已经结束,如果能解决图像丢帧的问题,即可忽略第二步。若还没有解决,可能还与软件(代码)有关,代码主要在于抓图方式和取图方式。

2、软件原因

本人使用的是官方MFC-SDK,需要实现的功能为:当收到触发信号时,获取相机当前帧图像,并对该图像进行图像处理操作。最开始使用的方法为,开启软件后,持续获取流数据,即调用Grab()函数开始抓图,当收到触发信号时,直接从缓冲区(m_Buffers)中取数据转换为Mat图像,然后进行后续处理,结果发现,此方法会存在丢帧的情况。

后通过查看相机文档及相关资料得知,当相机得到一帧完整数据时,会自动调用回调函数(XferCallback),回调函数结束时,说明获取了一张完整的图像,故选用单张抓图Snap()+回调函数内获取图像的方式,最终解决了图像丢帧的问题。

主要代码部分展示:

头文件主要变量及函数定义:

CImageExWnd m_ImageWnd;
SapAcqDevice	*m_AcqDevice;
SapBuffer		*m_Buffers;
SapTransfer		*m_Xfer;
SapView        *m_View;
static void XferCallback(SapXferCallbackInfo *pInfo);

初始化OnInitDialog()函数部分代码:

	//OnInitDialog()函数中
        //Select acquisition server from dialog
	//Only the servers that support "AcqDevice" resource are listed
	CAcqConfigDlg dlg(this, CAcqConfigDlg::ServerAcqDevice);
	if (dlg.DoModal() != IDOK)
	{
		MessageBox(_T("未发现或选中相机"), _T("错误"), MB_ICONHAND);
		EndDialog(TRUE);
		return FALSE;
	}

	// Define objects(important!)
	m_AcqDevice = new SapAcqDevice(dlg.GetLocation(), dlg.GetConfigFile());
	m_Buffers = new SapBufferWithTrash(1, m_AcqDevice); //1个垃圾缓冲区,如果获取多帧图像,为防止丢帧最好设置至少2个以上的缓冲区,因为此处使用单张抓图,所以1个缓冲区即可。
	m_Xfer = new SapAcqDeviceToBuf(m_AcqDevice, m_Buffers, XferCallback, this);
	m_View = new SapView(m_Buffers);

	//// Attach sapview to image viewer
	m_ImageWnd.AttachSapView(m_View);

	// Create all objects
	if (!CreateObjects()) { EndDialog(TRUE); return FALSE; }

	m_ImageWnd.AttachEventHandler(this);
	m_ImageWnd.CenterImage();
	m_ImageWnd.Reset();

回调XferCallback()函数:

void CGigeCameraDemoDlg::XferCallback(SapXferCallbackInfo *pInfo)
{
	CGigeCameraDemoDlg *pDlg = (CGigeCameraDemoDlg *)pInfo->GetContext();

	int staticCount = 0;
	BYTE pData;
	void* pDataAddr = &pData;
	pDlg->m_Buffers->GetAddress(staticCount, &pDataAddr);
	int width = pDlg->m_Buffers->GetWidth();
	int height = pDlg->m_Buffers->GetHeight();
	Mat img = Mat::zeros(cv::Size(width, height), CV_8U);
	memcpy(img.data, pDataAddr, width*height);
	img.copyTo(global_source_image);  //global_source_image为全局Mat

	callback_flag = true;  //自定义全局变量
}

某函数中抓取图像:

//m_Xfer->Snap()即为单张抓图,此处选用单张抓图
//m_Xfer->Grab()即为获取视频流,持续抓图
if (m_Xfer->Snap())
{
    UpdateMenu(); //更新按钮状态
}

//当callback_flag为true时,可以使用图像
while(callback_flag == true)
{
    //使用global_source_image进行一系列图像操作
    //操作结束退出循环,并将callback_flag置为false.
}

 

你可能感兴趣的:(c++)