【相机驱动】埃科相机驱动开发流程

一、安装相机驱动

安装相应相机对应相机厂家软件

标题二、查看相机连接是否正常

使用相机厂家软件连接相机,更改相应配置,可查看软件使用说明书,gige需要更改网口IP配置
在这里插入图片描述

标题三、找到相机sdk库,sdk调用示例代码

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

四、代码示例–网口线阵相机

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "afxmt.h"
#include "afxwin.h"

#include <vector>
using namespace std;
#include "IKapC.h"
#pragma comment (lib, "../Include/IKapC.lib")
class IKap_Gige{

public:
char Camera_Name[260];
public:
ITKDEVICE  m_CameraHandle;
ITKSTREAM  m_ITKSTREAM;
ITKBUFFER  m_buffer;
}


void IKAPC_CC cbStartOfFrame(uint32_t eventType, void* pContext)
{
	printf("%s,帧开始\r\n", __FUNCTION__);
}

void IKAPC_CC cbEndOfFrame(uint32_t eventType, void* pContext)
{
	printf("%s, 帧结束\r\n", __FUNCTION__);
}

void IKAPC_CC cbEndOfStream(uint32_t eventType, void* pContext)
{
	// qDebug() << "帧结束";
}

// 回调函数
void IKAPC_CC cbOnEndOfFrame(uint32_t eventType, void* pContext)
{
   IKap_Gige *iHandle=(IKap_Gige )*pContext;
	printf("%s,当前采集结束%s \r\n", __FUNCTION__,iHandle->Camera_Name);
	// 处理图像
	iHandle->ProcessImageData(iHandle);
}

void IKAPC_CC cbOnTimeOut(uint32_t eventType, void* pContext)
{
	printf("%s,超时\r\n", __FUNCTION__);
}

void IKAPC_CC cbOnFrameLost(uint32_t eventType, void* pContext)
{
	IKap_Gige iHandle = *(IKap_Gige *)pContext;
	printf("%s, 当前相机%s,出现帧丢失\r\n", __FUNCTION__, iHandle->Camera_Name);
}

void CreateStreamAndBuffer(ITKDEVICE& _pDevice, ITKSTREAM& _pStream, ITKBUFFER* _itkbuffer)
{
	// 流数量
	uint32_t streamCount = 0;
	// 图像宽
	int64_t  nWidth = 0;
	// 图像高
	int64_t  nHeight = 0;
	// 图像数据类型 - 默认灰度
	uint32_t nFormat = ITKBUFFER_VAL_FORMAT_MONO8;
	// 图像大小
	int64_t	 nImageSize = 0;
	// 图像像素格式
	char	 pixelFormat[16];
	// 图像像素格式大小
	uint32_t pixelFormatLen = 16;
	// 获取当前相机数据流数量
	ITKSTATUS res = ITKSTATUS_OK;
	res = ItkDevGetStreamCount(_pDevice, &streamCount);
	if (ITKSTATUS_OK != res) DEBUGTRACE("%s,获取流数量异常,异常信息为:%d\r\n", __FUNCTION__, res);
	if (streamCount == 0) {
		// 相机信息
		ITKDEV_INFO di;
		// 获取相机信息
		res = ItkManGetDeviceInfo(0, &di);
		if (ITKSTATUS_OK != res) DEBUGTRACE("%s, 相机信息获取异常,异常代码为:%d\r\n", __FUNCTION__, res);
	}
	// 获取图像宽
	res = ItkDevGetInt64(_pDevice, "Width", &nWidth);
	if (ITKSTATUS_OK != res) DEBUGTRACE("%s, 获取图像宽异常,异常代码为:%d\r\n", __FUNCTION__, res);
	// 获取图像高
	res = ItkDevGetInt64(_pDevice, "Height", &nHeight);
	if (ITKSTATUS_OK != res) DEBUGTRACE("%s, 获取图像高异常,异常代码为:%d\r\n", __FUNCTION__, res);
	// 获取图像数据类型
	res = ItkDevToString(_pDevice, "PixelFormat", pixelFormat, &pixelFormatLen);
	if (ITKSTATUS_OK != res) DEBUGTRACE("%s, 获取图像数据类型异常,异常代码为:%d\r\n", __FUNCTION__, res);
	if (strcmp(pixelFormat, "Mono8") == 0)
		nFormat = ITKBUFFER_VAL_FORMAT_MONO8;
	else if (strcmp(pixelFormat, "Mono10") == 0)
		nFormat = ITKBUFFER_VAL_FORMAT_MONO10;
	else if (strcmp(pixelFormat, "Mono10Packed") == 0)
		nFormat = ITKBUFFER_VAL_FORMAT_MONO10PACKED;
	else if (strcmp(pixelFormat, "BayerGR8") == 0)
		nFormat = ITKBUFFER_VAL_FORMAT_BAYER_GR8;
	else if (strcmp(pixelFormat, "BayerRG8") == 0)
		nFormat = ITKBUFFER_VAL_FORMAT_BAYER_RG8;
	else if (strcmp(pixelFormat, "BayerGB8") == 0)
		nFormat = ITKBUFFER_VAL_FORMAT_BAYER_GB8;
	else if (strcmp(pixelFormat, "BayerBG8") == 0)
		nFormat = ITKBUFFER_VAL_FORMAT_BAYER_BG8;
	else {
		printf("%s, 相机不支持的像素类型,错误类型为:%d\r\n", __FUNCTION__, pixelFormat);
	}
	// 该缓冲区作为图像数据的默认传输地址
	ITKBUFFER hBuffer;
	res = ItkBufferNew(nWidth, nHeight, nFormat, &hBuffer);
	if (ITKSTATUS_OK != res) printf("%s,缓冲区初始化异常,异常代码为:%d\r\n", __FUNCTION__, res);
	*_itkbuffer = hBuffer;
	// 获取缓冲区数据大小
	res = ItkBufferGetPrm(hBuffer, ITKBUFFER_PRM_SIZE, &nImageSize);
	if (ITKSTATUS_OK != res) printf("%s,获取图像缓冲区大小异常,异常代码为:%d\r\n", __FUNCTION__, res);
	// 申请内存
	/*char* bufferData = (char*)malloc(nImageSize);
	if (bufferData != nullptr) {
		g_imgBufferList.push_back(bufferData);
	}*/

	// 申请图像数据流资源
	res = ItkDevAllocStream(_pDevice, 0, hBuffer, &_pStream);
	if (ITKSTATUS_OK != res) printf("%s,申请图像数据流资源异常,异常代码为:%d\r\n", __FUNCTION__, res);

	// 补充其他缓冲区数据
	/*for (int i = 1; i < streamCount; i++) {
		res = ItkBufferNew(nWidth, nHeight, nFormat, &hBuffer);
		CHECK(res, "缓冲区初始化异常,异常代码为:%1");
		res = ItkStreamAddBuffer(_pStream, hBuffer);
		CHECK(res, "流绑定缓冲区异常,异常代码为:%1");
		g_bufferList.push_back(hBuffer);
	}*/
}

void ConfigureStream(ITKSTREAM _phStream, void* _iCameraHandle)
{
	ITKSTATUS res = ITKSTATUS_OK;
	// 异步传输图像模式 -- 同步保护模式,如果下一块缓冲区为空则传输到下一块缓冲区中,否则丢弃图像数据
	uint32_t xferMode = ITKSTREAM_VAL_TRANSFER_MODE_SYNCHRONOUS_WITH_PROTECT;
	// 非阻塞式启动图像采集
	uint32_t startMode = ITKSTREAM_VAL_START_MODE_NON_BLOCK;
	// 图像传输超时时间
	uint32_t timeOut = INFINITE;
	// 相机索引
	IKap_Gige * pi = (IKap_Gige *)_iCameraHandle;
	int* time = new int;
	*time = 999999999;

	/* Set block mode which means the grab will not be stopped before an entire image
	come into buffer. */
	res = ItkStreamSetPrm(_phStream, ITKSTREAM_PRM_START_MODE, &startMode);
	if (ITKSTATUS_OK != res) printf("%s, 启动图像采集设定异常,异常代码为:%d\r\n", __FUNCTION__, res);
	// 异步传输图像模式
	res = ItkStreamSetPrm(_phStream, ITKSTREAM_PRM_TRANSFER_MODE, &xferMode);
	if (ITKSTATUS_OK != res) printf("%s,异步传输图像模式设定异常,异常代码为:%d\r\n", __FUNCTION__, res);
	// 设置超时时间
	res = ItkStreamSetPrm(_phStream, ITKSTREAM_PRM_TIME_OUT, &timeOut);
	if (ITKSTATUS_OK != res) printf("%s, 流超时时间设定异常,异常代码为:%d\r\n", __FUNCTION__, res);
	// 设置流时间
	res = ItkStreamSetPrm(_phStream, ITKSTREAM_PRM_GV_PACKET_INTER_TIMEOUT, (void*)time);
	if (ITKSTATUS_OK != res) printf("%s,ITKSTREAM_PRM_GV_PACKET_INTER_TIMEOUT设定异常,异常代码为:%d\r\n", __FUNCTION__, res);
	/* Register callback which will be called at the begin of stream. */
	// 注册开始采集事件
	res = ItkStreamRegisterCallback(_phStream, ITKSTREAM_VAL_EVENT_TYPE_START_OF_FRAME, cbStartOfFrame, (void*)pi);
	if (ITKSTATUS_OK != res) printf("%s,帧开始事件注册异常,异常代码为:%d\r\n", __FUNCTION__, res);
	res = ItkStreamRegisterCallback(_phStream, ITKSTREAM_VAL_EVENT_TYPE_END_OF_FRAME, cbEndOfFrame, (void*)pi);
	if (ITKSTATUS_OK != res) printf("%s,帧结束事件注册异常,异常代码为:%d\r\n", __FUNCTION__, res);

	/* Register callback which will be called at the end of stream. */
	// 注册结束采集事件
	// res = ItkStreamRegisterCallback(_phStream, ITKSTREAM_VAL_EVENT_TYPE_END_OF_STREAM, cbEndOfStream, (void*)pi);
	// CHECK(res);

	/* Register callback which will be called at the end of one image completely. */
	// 注册一帧结束事件----回调注册函数
	res = ItkStreamRegisterCallback(_phStream, ITKSTREAM_VAL_EVENT_TYPE_END_OF_FRAME, cbOnEndOfFrame, (void*)pi);
	if (ITKSTATUS_OK != res) printf("%s,图像采集回调注册异常,异常代码为:%d\r\n", __FUNCTION__, res);
	// 注册超时事件
	res = ItkStreamRegisterCallback(_phStream, ITKSTREAM_VAL_EVENT_TYPE_TIME_OUT, cbOnTimeOut, (void*)pi);
	if (ITKSTATUS_OK != res) printf("%s,超时时间回调注册异常,异常代码为:%d\r\n", __FUNCTION__, res);
	// 注册图像丢失事件
	res = ItkStreamRegisterCallback(_phStream, ITKSTREAM_VAL_EVENT_TYPE_FRAME_LOST, cbOnFrameLost, (void*)pi);
	if (ITKSTATUS_OK != res) printf("%s,图像丢失回调注册异常,异常代码为:%d\r\n", __FUNCTION__, res);
}

void UnRegisterCallback(ITKSTREAM _phStream)
{
	// ITKSTATUS	res = ITKSTATUS_OK;
	ItkStreamUnregisterCallback(_phStream, ITKSTREAM_VAL_EVENT_TYPE_START_OF_STREAM);
	ItkStreamUnregisterCallback(_phStream, ITKSTREAM_VAL_EVENT_TYPE_END_OF_STREAM);
	ItkStreamUnregisterCallback(_phStream, ITKSTREAM_VAL_EVENT_TYPE_END_OF_FRAME);
	ItkStreamUnregisterCallback(_phStream, ITKSTREAM_VAL_EVENT_TYPE_TIME_OUT);
	ItkStreamUnregisterCallback(_phStream, ITKSTREAM_VAL_EVENT_TYPE_FRAME_LOST);
}

void SetFrameTrigger(ITKDEVICE _phanle)
{
	ITKSTATUS res = ITKSTATUS_OK;

	// Turn off line trigger
	res = ItkDevFromString(_phanle, "TriggerSelector", "LineStart");
	
	res = ItkDevFromString(_phanle, "TriggerMode", "Off");


	// Trigger selector
	res = ItkDevFromString(_phanle, "TriggerSelector", "FrameStart");

	// Set trigger mode
	res = ItkDevFromString(_phanle, "TriggerMode", "Off");
	

	// Select trigger source(Line3、Software)
	res = ItkDevFromString(_phanle, "TriggerSource", "Line3");
	
	// Set Trigger Frames Count(once)
	res = ItkDevSetInt64(_phanle, "TriggerFrameCount", 1);
	
}

bool IKap_Gige ::Init_Camera()
{
	bool bRet;

	int i;
	int nIndex;
	int nSnap_Number;
	unsigned int unVer;

	HANDLE hThread;
	unsigned m_nThreadID;

	const char* szMsg;
	
	bRet = false;
	szServer_Name[0x00] = 0x00;

	bRet = Device_User_Camera_Initial(Camera_Name);
	
	return bRet;
}

bool IKap_Gige ::Device_User_Camera_Initial(char* szServer_Name)
{
	bool bRet;

	bRet = false;

	ItkManInitialize();
	// 枚举所有相机时,必须先调用该函数ItkManGetDeviceCount()
	ITKSTATUS res = ItkManGetDeviceCount(&m_numCameras);
	// 调用失败0
	if (ITKSTATUS_OK != res) {
		return false;
	}
	// 数量为0,找不到相机
	if (m_numCameras == 0) {
		DEBUGTRACE("%s, %s 没有找到相机,\r\n", __FUNCTION__, szServer_Name);
		ItkManTerminate();
		return false;
	}

	for (int i = 0; i < m_numCameras; i++) {
		// 打开一个相机
		ITKDEVICE device = nullptr;
		// 数据流
		ITKSTREAM stream = nullptr;
		// 相机信息
		ITKDEV_INFO di;
		// 获取相机信息  YT2259987317031
		ITKSTATUS res = ITKSTATUS_OK;
		res = ItkManGetDeviceInfo(i, &di);
		if (res != ITKSTATUS_OK) {
			printf("%s,SerialNumber为:%d -- 获取相机信息失败,错误代码为:%d,\r\n", __FUNCTION__, di.SerialNumber,res);
			return false;
		}
		// 根据SerialNumber来配置启动相机
		//if (strcmp(di.DeviceClass, "GigEVision") == 0 && strcmp(di.SerialNumber, "") != 0 && strcmp(di.UserDefinedName, strDeviceID.toLocal8Bit().data()) == 0)
		if (strstr(szServer_Name, (char*)di.SerialNumber)
		{
			// 打开相机
			res = ItkDevOpen(i, ITKDEV_VAL_ACCESS_MODE_EXCLUSIVE, &device);
			if (res != ITKSTATUS_OK) {
				printf("%s,SerialNumber为:%d -- 打开失败,错误代码为:%d,\r\n", __FUNCTION__, di.SerialNumber, res);
				return false;
			}
			// 打开成功
			printf("%s,SerialNumber = %s -- 打开成功\r\n", __FUNCTION__, di.SerialNumber);
			// 创建缓存
			CreateStreamAndBuffer(device, stream, &m_buffer);
			// 注册回调函数
			int indxe=0;
			ConfigureStream(stream, this);

			// 存储相机以及流数据
			m_CameraHandle = device;
			m_ITKSTREAM = stream;

			///采集测试
			
			
			/* Stop grab image. */
			//ItkStreamStop(m_ITKSTREAM);
			//UnRegisterCallback(m_ITKSTREAM);
			
			// 
			SetFrameTrigger(m_CameraHandle);
			//ItkStreamStart(m_ITKSTREAM, ITKSTREAM_CONTINUOUS);
			//res = ItkStreamStart(m_ITKSTREAM, 1);
			//Sleep(5000);
			// 获取Gige信息
			/*ITKGIGEDEV_INFO gvInfo;
			res = ItkManGetGigEDeviceInfo(0, &gvInfo);
			if (res != ITKSTATUS_OK) {
				qDebug() << QString("SerialNumber = %1 -- 打开失败,ErrorCode == %2").arg(di.SerialNumber).arg(res);
				flag &= false;
			}*/
			return true;
		}
	}
	// 打开失败
	return false;
}

int IKap_Gige::CloseDevice()
{
	// 停止采集
	Grab_Stop();
	Sleep(100);

	ItkDevClose(m_CameraHandle);
	// 结束
	ItkManTerminate();
	return true;
}


// The user clicked on continuous grab.
void IKap_Gige ::OnStartGrabbing()
{
	//开始采集
	// 开启采图 -- 连续模式
	int iRet = ItkStreamStart(m_ITKSTREAM, ITKSTREAM_CONTINUOUS);
	if (ITKSTATUS_OK != iRet) {
		printf("%s, start grab camera error:%d\r\n", __FUNCTION__, iRet);
		return;
	}
	DEBUGTRACE("%s, start grab camera\r\n", __FUNCTION__);
}


// The user clicked on stop grab.
void IKap_Gige ::OnStopGrab()
{
	//结束采集
	// 开启采图 -- 连续模式
	int iRet = ItkStreamStop(m_ITKSTREAM);
	if (ITKSTATUS_OK != iRet) {
		printf("%s, stop grab camera error:%d\r\n", __FUNCTION__, iRet);
		return;
	}
	printf("%s, stop grab camera\r\n", __FUNCTION__);

	//grabberUnique->stop();
}

///回调图像采集函数
void IKap_Gige ::ProcessImageData(void* _iHandle)
{
	Image_Full_Msg strImage_Full_Msg;
	Image_Extend_Msg strImage_Extend_Msg;

	DWORD dwStart = GetTickCount64();		// 回调开始时刻

	printf("%s, 当前相机%d采集完一帧\r\n", __FUNCTION__, 0);

	ITKSTATUS res = ITKSTATUS_OK;
	// 缓存状态
	unsigned bufferStatus = 0;
	// 数据buffer
	IKap_Gige * pDevice = (IKap_Gige *)_iHandle;
	ITKBUFFER hBuffer = pDevice->m_buffer;
	// 获取采集结果
	res = ItkBufferGetPrm(hBuffer, ITKBUFFER_PRM_STATE, &bufferStatus);
	if (ITKSTATUS_OK != res)   printf("%s, 获取采集结果异常,异常代码为:%d\r\n", __FUNCTION__, res);
	if (res != ITKSTATUS_OK) {
		return;
	}
	// 判断是否已经采图结束
	if (bufferStatus == ITKBUFFER_VAL_STATE_FULL || bufferStatus == ITKBUFFER_VAL_STATE_UNCOMPLETED) {
		// 图像大小
		int64_t  nWidth = 0, nHeight = 0, nReadyLines = 0, nImageSize = 0;
		// 图像个数
		// 句柄
		ITKDEVICE device = m_CameraHandle;
		//ITKBUFFER hBuffer;// = g_bufferList[_iHandleIndex];

		// 获取图像的信息
		res = ItkDevGetInt64(device, "Width", &nWidth);
		if (ITKSTATUS_OK != res)   printf("%s, 拆分图像时,获取图像宽度异常,异常代码为:%d\r\n", __FUNCTION__, res);

		if (res != ITKSTATUS_OK) return;
		res = ItkDevGetInt64(device, "Height", &nHeight);
		if (ITKSTATUS_OK != res)   printf("%s, 拆分图像时,获取图像高度异常,异常代码为:%d\r\n", __FUNCTION__, res);
		if (res != ITKSTATUS_OK) return;
		// 单帧变长时的有效行数
		res = ItkBufferGetPrm(hBuffer, ITKBUFFER_PRM_READY_LINES, &nReadyLines);
		if (ITKSTATUS_OK != res)   printf("%s, 获取有效行数异常,异常代码为:%d\r\n", __FUNCTION__, res);
		if (nReadyLines == 0) return;

		// 存储有效高度
		g_imgValidHeightList[_iHandleIndex] += nReadyLines;

		// 读取buffer数据
		res = ItkBufferGetPrm(hBuffer, ITKBUFFER_PRM_SIZE, &nImageSize);
		if (ITKSTATUS_OK != res)   printf("%s, 获取图像缓存异常,异常代码为:%d\r\n", __FUNCTION__, res);
		if (res != ITKSTATUS_OK) return;
		int64_t nSize = nWidth * nHeight;
		uint8_t* srcData = new uint8_t[nSize];
		// 将数据读取到申请的内存中---读取图像数据
		res = ItkBufferRead(hBuffer, 0, srcData, (uint32_t)nImageSize);
		if (ITKSTATUS_OK != res)   printf("%s, 读取数据异常,异常代码为:%d\r\n", __FUNCTION__, res);
		if (res != ITKSTATUS_OK) return;

		// 图像搬运
		uint8_t* dstData = new uint8_t[nSize];
		memcpy(dstData, srcData, nSize);
		// 存储数据
		usigned char* byData = (uint8_t*)dstData;//图像数据
		int  Width = nWidth;//宽
		int  Height = nHeight;//高

		free(strImage_Full_Msg.byData);
	}
}
埃科线扫相机是一种常用于扫描文档和照片的设备。它通过传感器和透镜系统,可以迅速获取图像并将其保存为数字文件。埃科线扫相机取图demo是该设备的演示程序,用于展示其图像采集和处理的功能。 在这个demo中,用户可以通过简单的操作来进行图像扫描。首先,用户需将要扫描的物体放置在扫描平台上,并启动demo程序。接下来,使用者可以选择扫描的参数,例如分辨率、扫描模式和输出格式等。一旦参数设置完成,点击开始扫描按钮,埃科线扫相机即开始工作。 当扫描开始后,埃科线扫相机会沿着物体表面移动,并使用线性传感器逐渐记录下每个扫描线上的图像信息。这些信息随即经过处理和优化,最终生成一幅完整的数字图像。扫描过程中,用户可以观察进度条,以了解扫描的进展。 完成扫描后,demo程序会将生成的数字图像保存在指定的文件夹中。用户可以对其进行预览,并选择是否进行后续的编辑和处理操作。此外,demo还提供了一些额外的功能,如自动裁剪、旋转和调整图像的亮度和对比度等。 通过埃科线扫相机取图demo,用户可以快速、方便地获取高质量的数字图像。这一演示程序不仅展示了埃科线扫相机的强大功能,也为用户提供了一种简单、直观的方式来操作并控制这一设备。无论是用于个人文档扫描还是商业用途,埃科线扫相机取图demo都能满足用户的需求,并带来高效便捷的图像处理体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值