// main.cpp /* @brief:本示例向用户演示如何运用IKapC库和IKapBoard库,通过IKapWaitOneFrameReady接口和采集卡连接的相机连续采集图像。 * * @brief:This example shows users how to use IKapC and IKapBoard libraries to * grab images continuously with grabber linked camera and IKapWaitOneFrameReady api. */ #include #include #include #include #include #include #include "../GeneralConfigureCamera/ConfigureCamera.h" #include "../GeneralGrabWithGrabber/GeneralGrabWithGrabber.h" #pragma comment(lib, "IKapBoard.lib") #pragma comment(lib, "IKapC.lib") #pragma comment(lib, "shlwapi.lib") // 指示是否退出程序 // // indicate whether exit the program or not bool g_bExit = false; /* @brief:注册回调函数。 * * @brief:Register callback functions. */ void RegisterCallbackWithGrabber(pItkCamera pCam); /* @brief:清除回调函数。 * * @brief:Unregister callback functions. */ void UnRegisterCallbackWithGrabber(pItkCamera pCam); /* @brief:本函数被注册为一个回调函数。当图像采集开始时,函数被调用。 * @param[in] pContext:输入参数。 * * @brief:This function is registered as a callback function. When starting * grabbing images, the function will be called. * @param[in] pContext:Input parameter. */ void CALLBACK OnGrabStart(void* pContext); /* @brief:本函数被注册为一个回调函数。当图像采集超时时,函数被调用。 * @param[in] pContext:输入参数。 * * @brief:This function is registered as a callback function. When grabbing * images time out, the function will be called. * @param[in] pContext:Input parameter. */ void CALLBACK OnTimeout(void* pContext); /* @brief:本函数被注册为一个回调函数。当采集丢帧时,函数被调用。 * @param[in] pContext:输入参数。 * * @brief:This function is registered as a callback function. When grabbing * frame lost, the function will be called. * @param[in] pContext:Input parameter. */ void CALLBACK OnFrameLost(void* pContext); /* @brief:本函数被注册为一个回调函数。当图像采集停止时,函数被调用。 * @param[in] pContext:输入参数。 * * @brief:This function is registered as a callback function. When stopping * grabbing images, the function will be called. * @param[in] pContext:Input parameter. */ void CALLBACK OnGrabStop(void* pContext); /* @brief:本函数是工作线程的执行函数,用于采集图像。 * @param[in] pUser:输入参数。 * * @brief:This function is the execution function of the work thread for image acquisition. * @param[in] pUser:Input parameter. */ unsigned int __stdcall WorkThread(void* pUser); int main() { /// \~chinese IKapC 函数返回值 \~english Return value of IKapC functions ITKSTATUS res = ITKSTATUS_OK; /// \~chinese IKapBoard 函数返回值 \~english Return value of IKapBoard functions int ret = IK_RTN_OK; /// \~chinese 初始化 IKapC 运行环境 \~english Initialize IKapC runtime environment res = ItkManInitialize(); CHECK_IKAPC(res); ItkCamera cam; cam.g_bufferCount = 10; sprintf_s(cam.g_saveFileName, "D:\\CImage.tif"); cam.g_SerialNumber = NULL; cam.g_bSoftTriggerUsed = 1; cam.g_bLoadGrabberConfig = 1; uint32_t numDevices = 0; res = ItkManGetDeviceCount(&numDevices); CHECK(res); // 当没有连接的设备时。 // // When there is no connected devices. if (numDevices == 0) { fprintf(stderr, "No device.\n"); ItkManTerminate(); pressEnterToExit(); exit(EXIT_FAILURE); } printCameraInfo(numDevices); /// \~chinese 打开序号为0的相机并配置相机设备 \~english Open camera with 0 index and configure camera device int tmpIndex = -1; fprintf(stderr, "total device count: %d, the index of which you want to open is:", numDevices); fflush(stderr); int scanTmp = scanf_s("%u", &tmpIndex); if (scanTmp != 1) { fprintf(stderr, "Invalid input. Expect an integer.\n"); ItkManTerminate(); pressEnterToExit(); exit(EXIT_FAILURE); } if (tmpIndex >= numDevices) { fprintf(stderr, "index: %d is more than %d.\n", tmpIndex, numDevices - 1); ItkManTerminate(); pressEnterToExit(); exit(EXIT_FAILURE); } { int getCharTmp = getchar(); } ConfigureCamera(&cam, tmpIndex); if (cam.g_hBoard == INVALID_HANDLE_VALUE) { fprintf(stderr, "Please select camera with grabber.\n"); ItkManTerminate(); pressEnterToExit(); exit(EXIT_FAILURE); } /// \~chinese 配置采集卡设备 \~english Configure frame grabber device ConfigureFrameGrabber(&cam); /// \~chinese 注册回调函数 \~english Register callback functions. RegisterCallbackWithGrabber(&cam); /// \~chinese 配置相机触发方式 \~english Configure trigger method of the camera SetSoftTriggerWithGrabber(&cam); /// \~chinese 开始图像采集 \~english Start grabbing images StartGrabImage(&cam); /// \~chinese 创建工作线程用于获取图像 \~english Create a worker thread that is used to acquire the images unsigned int nThreadID = 0; void* hThreadHandle = (void*)_beginthreadex(NULL, 0, WorkThread, &cam, 0, &nThreadID); if (NULL == hThreadHandle) { printf("fail to create workThread to grab image.\n"); ItkManTerminate(); pressEnterToExit(); exit(EXIT_FAILURE); } if (cam.g_bSoftTriggerUsed) { printf("Please intput t to softTrigger a frame and input e to exit: "); while (true) { char T = 0; int scanTmp = scanf_s("%c", &T, (unsigned)sizeof(T)); if (T == 't') { if (strcmp(cam.g_devInfo.DeviceClass, "CoaXPress") == 0 || strcmp(cam.g_devInfo.DeviceClass, "CameraLink") == 0) { ret = IKapSetInfo(cam.g_hBoard, IKP_SOFTWARE_TRIGGER_START, 1); } else { res = ItkDevExecuteCommand(cam.g_hCamera, "TriggerSoftware"); } CHECK_IKAPBOARD(ret); } else if (T == 'e') { break; } else if (T != '\n') { printf("Please intput t to softTrigger a frame and input e to exit: "); } } } /// \~chinese 等待图像采集结束 \~english Wait for grabbing images finished { int getCharTmp = getchar(); } g_bExit = true; /// \~chinese 停止工作线程 \~english stop workThread WaitForSingleObject(hThreadHandle, INFINITE); CloseHandle(hThreadHandle); /// \~chinese 停止图像采集 \~english Stop grabbing images ret = IKapStopGrab(cam.g_hBoard); CHECK_IKAPBOARD(ret); /// \~chinese 清除回调函数 \~english Unregister callback functions UnRegisterCallbackWithGrabber(&cam); /// \~chinese 关闭采集卡设备 \~english Close frame grabber device ret = IKapClose(cam.g_hBoard); CHECK_IKAPBOARD(ret); /// \~chinese 关闭相机设备 \~english Close camera device res = ItkDevClose(cam.g_hCamera); CHECK_IKAPC(res); /// \~chinese 释放用户申请的用于设置Buffer地址的内存 \~english Release the memory that the user requests for setting the Buffer address /*if (cam.g_user_buffer!=NULL) free(cam.g_user_buffer);*/ /// \~chinese 释放 IKapC 运行环境 \~english Release IKapC runtime environment ItkManTerminate(); pressEnterToExit(); return 0; } void RegisterCallbackWithGrabber(pItkCamera pCam) { int ret = IK_RTN_OK; ret = IKapRegisterCallback(pCam->g_hBoard, IKEvent_GrabStart, OnGrabStart, pCam); CHECK_IKAPBOARD(ret); ret = IKapRegisterCallback(pCam->g_hBoard, IKEvent_FrameLost, OnFrameLost, pCam); CHECK_IKAPBOARD(ret); ret = IKapRegisterCallback(pCam->g_hBoard, IKEvent_TimeOut, OnTimeout, pCam); CHECK_IKAPBOARD(ret); ret = IKapRegisterCallback(pCam->g_hBoard, IKEvent_GrabStop, OnGrabStop, pCam); CHECK_IKAPBOARD(ret); } void UnRegisterCallbackWithGrabber(pItkCamera pCam) { int ret = IK_RTN_OK; ret = IKapUnRegisterCallback(pCam->g_hBoard, IKEvent_GrabStart); CHECK_IKAPBOARD(ret); ret = IKapUnRegisterCallback(pCam->g_hBoard, IKEvent_FrameLost); CHECK_IKAPBOARD(ret); ret = IKapUnRegisterCallback(pCam->g_hBoard, IKEvent_TimeOut); CHECK_IKAPBOARD(ret); ret = IKapUnRegisterCallback(pCam->g_hBoard, IKEvent_GrabStop); CHECK_IKAPBOARD(ret); } void CALLBACK OnGrabStart(void* pContext) { printf("Start grabbing image.\n"); } unsigned int __stdcall WorkThread(void* pUser) { ITKSTATUS res = ITKSTATUS_OK; int ret = IK_RTN_OK; unsigned char* pUserBuffer = NULL; int64_t nFrameSize = 0; int nFrameCount = 0; int nFrameIndex = 0; IKAPBUFFERSTATUS status; pItkCamera cam = (pItkCamera)pUser; if (NULL == cam) { return 0; } do { /// \~chinese timeout_ms 需要大于相机实际帧周期,此处需要根据实际情况修改 \~english timeout_ms needs to be greater than the actual camera frame period, which needs to be modified according to the actual situation res = IKapWaitOneFrameReady(cam->g_hBoard, &nFrameIndex, 5000); if (g_bExit) { break; } CHECK_IKAPBOARD(ret); printf("Grab frame ready of camera with serialNumber:%s.\n", cam->g_devInfo.SerialNumber); ret = IKapGetInfo(cam->g_hBoard, IKP_FRAME_COUNT, &nFrameCount); CHECK_IKAPBOARD(ret); ret = IKapGetBufferStatus(cam->g_hBoard, nFrameIndex, &status); CHECK_IKAPBOARD(ret); /// \~chinese 当图像缓冲区满时 \~english When the buffer is full if (status.uFull == 1) { /// \~chinese 获取一帧图像的大小 \~english Get the size of a frame of image ret = IKapGetInfo64(cam->g_hBoard, IKP_FRAME_SIZE, &nFrameSize); CHECK_IKAPBOARD(ret); /// \~chinese 如果相机的MultiExposureTimeCount特征值大于1并且采集卡的IKP_MULTIPLE_LIGHT_COUNT参数设置为与MultiExposureTimeCount相同的值则开启了多重曝光功能,采集到的图像均分为N种曝光时间,[0~1*Height/N-1]行对应ExposureSelect为1时的ExposureTime,[1*Height/N~2*Height/N-1]行对应ExposureSelect为2时的ExposureTime,...,[(N-1)*Height/N~Height-1]行对应ExposureSelect为N时的ExposureTime. \~english If the MultiExposureTimeCount feature value is greater than 1, the multiple exposure function is turned on, The collected images were all divided into N exposure times, line [0~1 * Height / N-1] corresponds to the ExposureTime at a ExposureSelect of 1, line [1 * Height / N~2 * Height / N-1] corresponds to ExposureTime at ExposureSelect 2,..., line [(N-1) * Height / N~Height-1] corresponds to ExposureTime at ExposureSelect N. /// \~chinese 获取缓冲区地址 \~english Get the buffer address ret = IKapGetBufferAddress(cam->g_hBoard, nFrameIndex, (void **)&pUserBuffer); CHECK_IKAPBOARD(ret); /// \~chinese 保存图像 \~english Save image /* ret=IKapSaveBuffer(cam->g_hBoard,nFrameIndex,cam->g_saveFileName,IKP_DEFAULT_COMPRESSION); CHECK_IKAPBOARD(ret); */ } /// \~chinese 释放buffer \~english release buffer ret = IKapReleaseBuffer(cam->g_hBoard,nFrameIndex); CHECK_IKAPBOARD(ret); } while (!g_bExit); return 0; } void CALLBACK OnTimeout(void* pContext) { printf("Grab image timeout.\n"); } void CALLBACK OnFrameLost(void* pContext) { printf("Grab frame lost.\n"); } void CALLBACK OnGrabStop(void* pContext) { printf("Stop grabbing image.\n"); }