|
@@ -9,6 +9,17 @@ static unsigned int device_type = MV_GIGE_DEVICE | MV_USB_DEVICE;
|
|
|
// 制造厂商
|
|
// 制造厂商
|
|
|
static const char *manufacturer = "Hikrobot";
|
|
static const char *manufacturer = "Hikrobot";
|
|
|
|
|
|
|
|
|
|
+// 触发模式
|
|
|
|
|
+static MV_CAM_TRIGGER_MODE setTriggerMode = MV_TRIGGER_MODE_ON; /// 默认: 打开
|
|
|
|
|
+
|
|
|
|
|
+// 网口相机
|
|
|
|
|
+#define GIGE_CAMERA_ANY_VENDOR 1 // 支持任意厂商的网口相机, 否则只支持海康机器人
|
|
|
|
|
+
|
|
|
|
|
+// 曝光取图
|
|
|
|
|
+#define AE_WAIT_MAX_MS 180000 // 最大曝光稳定等待的时间, 默认3分钟, 单位: ms
|
|
|
|
|
+#define AE_EXP_TIME_EPS_US 50 // 曝光时间稳定判定的误差, 防抖&区间, 单位: us
|
|
|
|
|
+#define AE_EXP_STABLE_FRAMES 4 // 相机处于自动曝光模式时, 累计曝光值稳定的帧数
|
|
|
|
|
+
|
|
|
// 保存照片
|
|
// 保存照片
|
|
|
static int SavePhoto(HANDLE hCam, MV_FRAME_OUT *pFrame, EImgType imgType, const char *imgFile);
|
|
static int SavePhoto(HANDLE hCam, MV_FRAME_OUT *pFrame, EImgType imgType, const char *imgFile);
|
|
|
|
|
|
|
@@ -20,7 +31,8 @@ typedef struct
|
|
|
const char *saveImgPath;
|
|
const char *saveImgPath;
|
|
|
bool isExposureAuto; // 自动曝光:是/否
|
|
bool isExposureAuto; // 自动曝光:是/否
|
|
|
struct timespec expTime0; // 曝光开始的时间
|
|
struct timespec expTime0; // 曝光开始的时间
|
|
|
- float lastExpTime; // 上次的曝光时长
|
|
|
|
|
|
|
+ float lastExpTime; // 上次的曝光时长(us)
|
|
|
|
|
+ int expStableCnt; // 连续曝光稳定帧计数
|
|
|
HANDLE hESig; // 任务结束的通知
|
|
HANDLE hESig; // 任务结束的通知
|
|
|
int rCode; // 任务结束返回值
|
|
int rCode; // 任务结束返回值
|
|
|
} PthotoProcCtx;
|
|
} PthotoProcCtx;
|
|
@@ -31,7 +43,7 @@ static int PhotoProc(unsigned long wParam, unsigned long lParam) // 线程回调
|
|
|
|
|
|
|
|
// 1, 触发一次拍照
|
|
// 1, 触发一次拍照
|
|
|
getp:
|
|
getp:
|
|
|
- ret = MV_CC_SetCommandValue(ctx->hCam, "TriggerSoftware");
|
|
|
|
|
|
|
+ ret = (setTriggerMode == MV_TRIGGER_MODE_ON) ? MV_CC_SetCommandValue(ctx->hCam, "TriggerSoftware") : MV_OK;
|
|
|
|
|
|
|
|
// 2, 等待获取图像
|
|
// 2, 等待获取图像
|
|
|
if(MV_OK == ret)
|
|
if(MV_OK == ret)
|
|
@@ -54,14 +66,17 @@ getp:
|
|
|
if(MV_OK == ret) curExpTime = stExposureTime.fCurValue;
|
|
if(MV_OK == ret) curExpTime = stExposureTime.fCurValue;
|
|
|
|
|
|
|
|
struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now);
|
|
struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now);
|
|
|
- long elapsed = (now.tv_sec - ctx->expTime0.tv_sec)*1000 + (now.tv_nsec-ctx->expTime0.tv_nsec)/(1000*1000);
|
|
|
|
|
|
|
+ long elapsed = (now.tv_sec - ctx->expTime0.tv_sec)*1000 + (now.tv_nsec-ctx->expTime0.tv_nsec)/(1000*1000); // 计算时间差, 单位: ms
|
|
|
sw_log_debug("[%s] +++GetOneFrame+++, 等待曝光完成, ExposureTime = %.2fus, ElapsedTime = %ldms", MODULE_NAME, curExpTime, elapsed);
|
|
sw_log_debug("[%s] +++GetOneFrame+++, 等待曝光完成, ExposureTime = %.2fus, ElapsedTime = %ldms", MODULE_NAME, curExpTime, elapsed);
|
|
|
|
|
|
|
|
- if((curExpTime != ctx->lastExpTime) && elapsed < 3*60*1000)
|
|
|
|
|
|
|
+ if(fabsf(curExpTime - ctx->lastExpTime) <= AE_EXP_TIME_EPS_US) ctx->expStableCnt++;
|
|
|
|
|
+ else ctx->expStableCnt = 0;
|
|
|
|
|
+
|
|
|
|
|
+ if(ctx->expStableCnt < AE_EXP_STABLE_FRAMES && elapsed < AE_WAIT_MAX_MS)
|
|
|
{
|
|
{
|
|
|
MV_CC_FreeImageBuffer(ctx->hCam, &frame);
|
|
MV_CC_FreeImageBuffer(ctx->hCam, &frame);
|
|
|
- ctx->lastExpTime = curExpTime;
|
|
|
|
|
- goto getp; // 继续取图像
|
|
|
|
|
|
|
+ ctx->lastExpTime = curExpTime; if(0 == ctx->expStableCnt) ctx->expStableCnt = 1;
|
|
|
|
|
+ sw_thrd_delay(1); goto getp; // 继续取图像
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -73,6 +88,7 @@ getp:
|
|
|
switch(ret)
|
|
switch(ret)
|
|
|
{
|
|
{
|
|
|
case MV_E_NODATA: // 无数据时, 线程继续运行
|
|
case MV_E_NODATA: // 无数据时, 线程继续运行
|
|
|
|
|
+ sw_log_debug("[%s] +++GetOneFrame+++, 无数据, 继续等待...", MODULE_NAME);
|
|
|
ret = 1; break;
|
|
ret = 1; break;
|
|
|
default: // 成功或发生其他错误,线程结束运行
|
|
default: // 成功或发生其他错误,线程结束运行
|
|
|
ctx->rCode = ret; sw_signal_give(ctx->hESig); ret = -1; break;
|
|
ctx->rCode = ret; sw_signal_give(ctx->hESig); ret = -1; break;
|
|
@@ -150,6 +166,11 @@ findp:
|
|
|
strcpy(name, (const char *)pDevInfo->SpecialInfo.stGigEInfo.chManufacturerName);
|
|
strcpy(name, (const char *)pDevInfo->SpecialInfo.stGigEInfo.chManufacturerName);
|
|
|
strcpy(imgMark.camModelName, (const char *)pDevInfo->SpecialInfo.stGigEInfo.chModelName);
|
|
strcpy(imgMark.camModelName, (const char *)pDevInfo->SpecialInfo.stGigEInfo.chModelName);
|
|
|
strcpy(imgMark.camSerialNum, (const char *)pDevInfo->SpecialInfo.stGigEInfo.chSerialNumber);
|
|
strcpy(imgMark.camSerialNum, (const char *)pDevInfo->SpecialInfo.stGigEInfo.chSerialNumber);
|
|
|
|
|
+ if(GIGE_CAMERA_ANY_VENDOR && 0 != strcmp(name, manufacturer))
|
|
|
|
|
+ {
|
|
|
|
|
+ sw_log_debug("[%s] 发现 \"%s\" 厂商的网口相机", MODULE_NAME, name);
|
|
|
|
|
+ setTriggerMode = MV_TRIGGER_MODE_OFF; strcpy(name, manufacturer); // 关闭触发模式, 视为海康的网口相机
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if(xstrcasecmp(name, manufacturer) != 0)
|
|
if(xstrcasecmp(name, manufacturer) != 0)
|
|
@@ -179,8 +200,8 @@ findp:
|
|
|
goto end_p;
|
|
goto end_p;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- ret = MV_CC_SetEnumValue(hCam, "TriggerMode", 1); // 允许触发模式
|
|
|
|
|
- if(MV_OK == ret) ret = MV_CC_SetEnumValue(hCam, "TriggerSource", MV_TRIGGER_SOURCE_SOFTWARE); // 设置软件触发
|
|
|
|
|
|
|
+ ret = MV_CC_SetEnumValue(hCam, "TriggerMode", setTriggerMode); // 设置触发模式
|
|
|
|
|
+ if(MV_OK == ret && setTriggerMode == MV_TRIGGER_MODE_ON) ret = MV_CC_SetEnumValue(hCam, "TriggerSource", MV_TRIGGER_SOURCE_SOFTWARE); // 设置软件触发
|
|
|
if(MV_OK != ret)
|
|
if(MV_OK != ret)
|
|
|
{
|
|
{
|
|
|
sw_log_error("[%s] 设置相机时发生错误, errCode=0x%x!!", MODULE_NAME, ret);
|
|
sw_log_error("[%s] 设置相机时发生错误, errCode=0x%x!!", MODULE_NAME, ret);
|