Quellcode durchsuchen

海康USB相机支持自动曝光模式

niujiuru vor 4 Monaten
Ursprung
Commit
da78a0075a
4 geänderte Dateien mit 77 neuen und 8 gelöschten Zeilen
  1. 7 1
      mvs_takephoto/bridge.go
  2. 66 6
      mvs_takephoto/takephoto.c
  3. 3 0
      mvs_takephoto/takephoto.h
  4. 1 1
      mvs_takephoto/takephoto_test.c

+ 7 - 1
mvs_takephoto/bridge.go

@@ -1,7 +1,7 @@
 // Author: NiuJiuRu
 // Email: niujiuru@qq.com
 
-package mvs_takephoto
+package mvs_u_takephoto
 
 /*
 #include "takephoto.h"
@@ -39,6 +39,12 @@ func setSysUsbfsMemSize(val int) int {
 	return ret
 }
 
+// 获取当前连接在USB口上的相机数, 失败返回: <0值, 成功返回: >=0
+func GetUsbCameraCount() int {
+	ret := int(C.GetUsbCameraCount())
+	return ret
+}
+
 // 单次执行相机拍照, 并保存到文件, 成功返回: 本次拍照图像的水印信息, 失败返回: 错误原因和空的水印信息
 // 参数说明:
 // "imgType"         - 图像保存类型: 1-".bmp", 2-".jpg"

+ 66 - 6
mvs_takephoto/takephoto.c

@@ -12,16 +12,20 @@ typedef struct
   HANDLE      hCam;
   EImgType    saveImgType;
   const char *saveImgFilename;
-  HANDLE      hESig; // 任务结束的通知
-  int         rCode; // 任务结束返回值
+  bool        isExposureAuto; // 自动曝光:是/否
+  struct timespec expTime0;   // 曝光开始的时间
+  float       lastExpTime;    // 上次的曝光时长
+  HANDLE      hESig;          // 任务结束的通知
+  int         rCode;          // 任务结束返回值
 } PthotoProcCtx;
 
 static int PhotoProc(unsigned long wParam, unsigned long lParam) // 线程回调函数,执行一次拍照任务
 {
-  PthotoProcCtx *ctx = (PthotoProcCtx *)wParam; MV_FRAME_OUT frame = { 0 };
+  PthotoProcCtx *ctx = (PthotoProcCtx *)wParam; MV_FRAME_OUT frame = { 0 }; int ret;
 
   // 1, 触发一次拍照
-  int ret = MV_CC_SetCommandValue(ctx->hCam, "TriggerSoftware");
+getp:
+  ret = MV_CC_SetCommandValue(ctx->hCam, "TriggerSoftware");
 
   // 2, 等待获取图像
   if(MV_OK == ret)
@@ -36,6 +40,25 @@ static int PhotoProc(unsigned long wParam, unsigned long lParam) // 线程回调
     sw_log_debug("[%s] +++GetOneFrame+++, Width[%d], Height[%d], FrameNum[%d], FrameLen[%d], PixelType[0x%08X]", MODULE_NAME, \
                   frame.stFrameInfo.nWidth, frame.stFrameInfo.nHeight, frame.stFrameInfo.nFrameNum, frame.stFrameInfo.nFrameLen, \
                   (unsigned int)frame.stFrameInfo.enPixelType);
+
+    if(ctx->isExposureAuto)
+    { // 自动曝光模式下, 等待曝光稳定或超时
+      MVCC_FLOATVALUE stExposureTime = { 0 }; float curExpTime = 0;
+      ret = MV_CC_GetExposureTime(ctx->hCam, &stExposureTime);
+      if(MV_OK == ret) curExpTime = stExposureTime.fCurValue;
+
+      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);
+      sw_log_debug("[%s] +++GetOneFrame+++, 等待曝光完成, ExposureTime = %.2fus, ElapsedTime = %ldms", MODULE_NAME, curExpTime, elapsed);
+
+      if((curExpTime != ctx->lastExpTime) && elapsed < 3*60*1000)
+      {
+        MV_CC_FreeImageBuffer(ctx->hCam, &frame);
+        ctx->lastExpTime = curExpTime;
+        goto getp; // 继续取图像
+      }
+    }
+
     ret = SavePhoto(ctx->hCam, &frame, ctx->saveImgType, ctx->saveImgFilename);
     MV_CC_FreeImageBuffer(ctx->hCam, &frame);
   }
@@ -64,7 +87,7 @@ int TakePhoto(EImgType imgType, const char *saveImgFilename, int timeout, SImgMa
 {
   int fd; char runDir[MAX_PATH_CHARS] = { 0 }, lockFile[MAX_PATH_CHARS+32] = { 0 };
   int ret; SImgMark imgMark = { 0 }; HANDLE hCam = NULL; PthotoProcCtx ctx = { 0 };
-  MV_CC_DEVICE_INFO_LIST devList = { 0 }; MV_CC_DEVICE_INFO *pDevInfo = NULL;
+  MV_CC_DEVICE_INFO_LIST devList = { 0 }; MV_CC_DEVICE_INFO *pDevInfo = NULL; MVCC_ENUMVALUE exposureMode =  { 0 };
 
   // 1, 占用锁定, 避免同时间拍照
   xGetSelfRunningInfo(runDir, NULL);
@@ -86,7 +109,7 @@ int TakePhoto(EImgType imgType, const char *saveImgFilename, int timeout, SImgMa
     goto end_p;
   }
 
-  ret = MV_CC_EnumDevices(MV_USB_DEVICE, &devList); // 目前只枚举USB连接的相机
+  ret = MV_CC_EnumDevices(MV_USB_DEVICE, &devList);
   if(MV_OK != ret)
   {
     sw_log_error("[%s] USB口枚举相机失败, errCode=0x%x!!", MODULE_NAME, ret);
@@ -128,6 +151,15 @@ int TakePhoto(EImgType imgType, const char *saveImgFilename, int timeout, SImgMa
   }
 
   // 4, 开始拍照, 等待完成后输出
+  ret =  MV_CC_GetExposureAutoMode(hCam, &exposureMode);
+  if(MV_OK != ret)
+  {
+    sw_log_error("[%s] 获取-曝光模式失败, errCode=0x%x!!", MODULE_NAME, ret);
+    goto end_p;
+  }
+  if(exposureMode.nCurValue != MV_EXPOSURE_AUTO_MODE_OFF) { ctx.isExposureAuto = true; clock_gettime(CLOCK_MONOTONIC, &ctx.expTime0); }
+  else ctx.isExposureAuto = false;
+
   ret = MV_CC_StartGrabbing(hCam);
   if(MV_OK != ret)
   {
@@ -279,3 +311,31 @@ int SetSysUsbfsMemSize(int val)
   if(val >= 0 && sw_file_update(usbfsFile, "w", buf, strlen(buf)) == strlen(buf)) return 0;
   else return -1;
 }
+
+// 获取当前连接在USB口上的相机数, 失败返回: <0值, 成功返回: >=0
+int GetUsbCameraCount()
+{
+  MV_CC_DEVICE_INFO_LIST devList = { 0 };
+  int ret;
+
+  ret = MV_CC_Initialize();
+  if(MV_OK != ret)
+  {
+    sw_log_error("[%s] 相机SDK初始化失败, errCode=0x%x!!", MODULE_NAME, ret);
+    goto end_p;
+  }
+
+  ret = MV_CC_EnumDevices(MV_USB_DEVICE, &devList);
+  if(MV_OK != ret)
+  {
+    sw_log_error("[%s] USB口枚举相机失败, errCode=0x%x!!", MODULE_NAME, ret);
+    goto end_p;
+  }
+
+  ret = devList.nDeviceNum;
+
+end_p:
+  MV_CC_Finalize();
+
+  return ret;
+}

+ 3 - 0
mvs_takephoto/takephoto.h

@@ -33,6 +33,9 @@ int GetSysUsbfsMemCurrentSize();
 // 设置系统新的USBFS内存大小(MB), 成功返回: 0值, 失败返回: -1值
 int SetSysUsbfsMemSize(int val);
 
+// 获取当前连接在USB口上的相机数, 失败返回: <0值, 成功返回: >=0
+int GetUsbCameraCount();
+
 // 单次执行相机拍照, 并保存到文件, 成功返回: 0值, 失败返回:非0值
 // "imgType"         - 获取图像类型
 // "saveImgFilename" - 保存的文件名

+ 1 - 1
mvs_takephoto/takephoto_test.c

@@ -13,7 +13,7 @@ static void coreMemCheck(const char *filename, int line, const char *ptr, int si
 int main(int argc,char *argv[])
 {
   int ret = 0; unsigned long stime, wtime, etime;
-  char filename[MAX_PATH_CHARS] = { 0 }; int timeout = 60;
+  char filename[MAX_PATH_CHARS] = { 0 }; int timeout = 300;
 
   if(!sw_heap_init(coreBuf, sizeof(coreBuf), 4)) goto end_p;