342 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// main.cpp
/* @brief本示例向用户演示如何运用IKapC库和IKapBoard库通过IKapWaitOneFrameReady接口和采集卡连接的相机连续采集图像。
*
* @briefThis example shows users how to use IKapC and IKapBoard libraries to
* grab images continuously with grabber linked camera and IKapWaitOneFrameReady api. */
#include <malloc.h>
#include <shlwapi.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <process.h>
#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注册回调函数。
*
* @briefRegister callback functions. */
void RegisterCallbackWithGrabber(pItkCamera pCam);
/* @brief清除回调函数。
*
* @briefUnregister callback functions. */
void UnRegisterCallbackWithGrabber(pItkCamera pCam);
/* @brief本函数被注册为一个回调函数。当图像采集开始时函数被调用。
* @param[in] pContext输入参数。
*
* @briefThis function is registered as a callback function. When starting
* grabbing images, the function will be called.
* @param[in] pContextInput parameter. */
void CALLBACK OnGrabStart(void* pContext);
/* @brief本函数被注册为一个回调函数。当图像采集超时时函数被调用。
* @param[in] pContext输入参数。
*
* @briefThis function is registered as a callback function. When grabbing
* images time out, the function will be called.
* @param[in] pContextInput parameter. */
void CALLBACK OnTimeout(void* pContext);
/* @brief本函数被注册为一个回调函数。当采集丢帧时函数被调用。
* @param[in] pContext输入参数。
*
* @briefThis function is registered as a callback function. When grabbing
* frame lost, the function will be called.
* @param[in] pContextInput parameter. */
void CALLBACK OnFrameLost(void* pContext);
/* @brief本函数被注册为一个回调函数。当图像采集停止时函数被调用。
* @param[in] pContext输入参数。
*
* @briefThis function is registered as a callback function. When stopping
* grabbing images, the function will be called.
* @param[in] pContextInput parameter. */
void CALLBACK OnGrabStop(void* pContext);
/* @brief本函数是工作线程的执行函数用于采集图像。
* @param[in] pUser输入参数。
*
* @briefThis function is the execution function of the work thread for image acquisition.
* @param[in] pUserInput 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");
}