当前位置: 首页 > news >正文

MFC 调用海康相机进行软触发

初始化相机类文件

#pragma once
#include "MvCameraControl.h"
class CMvCamera
{
public:CMvCamera();~CMvCamera();//初始化相机int InitCamera();int SaveCurrentImage(CString filePath);//关闭相机void CloseCamera();//设置int SetEnumValue(IN const char* strKey, IN unsigned int nValue);// ch:执行一次Command型命令,如 UserSetSaveint CommandExecute(IN const char* strKey);public:int nRet;void* m_hDevHandle; // 初始化设备句柄为空
};
#include "pch.h"
#include "CMvCamera.h"CMvCamera::CMvCamera()
{
}CMvCamera::~CMvCamera()
{CloseCamera();if (m_hDevHandle != NULL){MV_CC_DestroyHandle(m_hDevHandle);m_hDevHandle = NULL;}
}int CMvCamera::InitCamera()
{nRet = MV_OK;m_hDevHandle = NULL;// 初始化SDKnRet = MV_CC_Initialize();if (MV_OK != nRet){AfxMessageBox(_T("初始化失败"));return 0;}// 枚举设备MV_CC_DEVICE_INFO_LIST stDeviceList;memset(&stDeviceList, 0, sizeof(MV_CC_DEVICE_INFO_LIST));nRet = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE, &stDeviceList);if (MV_OK != nRet){AfxMessageBox(_T("枚举设备失败"));return 0;}// 检查是否找到设备if (stDeviceList.nDeviceNum > 0){for (unsigned int i = 0; i < stDeviceList.nDeviceNum; i++){MV_CC_DEVICE_INFO* pDeviceInfo = stDeviceList.pDeviceInfo[i];if (NULL == pDeviceInfo){break;}}}else{AfxMessageBox(_T("没有找到设备"));return 0;}unsigned int nIndex = 0; // 选择第一个设备// 创建设备句柄nRet = MV_CC_CreateHandle(&m_hDevHandle, stDeviceList.pDeviceInfo[nIndex]);if (MV_OK != nRet){AfxMessageBox(_T("创建句柄失败"));return 0;}// 打开设备nRet = MV_CC_OpenDevice(m_hDevHandle);if (MV_OK != nRet){AfxMessageBox(_T("打开设备失败"));return 0;}// 对于GigE相机,设置最佳包大小if (stDeviceList.pDeviceInfo[nIndex]->nTLayerType == MV_GIGE_DEVICE){int nPacketSize = MV_CC_GetOptimalPacketSize(m_hDevHandle);if (nPacketSize > 0){nRet = MV_CC_SetIntValue(m_hDevHandle, "GevSCPSPacketSize", nPacketSize);if (nRet != MV_OK){AfxMessageBox(_T("Warning: Set Packet Size fail"));return 0;}}else{AfxMessageBox(_T("Warning: Get Packet Size fail"));return 0;}}// 设置触发模式为开启nRet = MV_CC_SetEnumValue(m_hDevHandle, "TriggerMode", 1);if (MV_OK != nRet){AfxMessageBox(_T("Set Trigger Mode fail!"));return 0;}// 设置触发源为软件触发nRet = MV_CC_SetEnumValue(m_hDevHandle, "TriggerSource", MV_TRIGGER_SOURCE_SOFTWARE);if (MV_OK != nRet){AfxMessageBox(_T("Set Trigger Source fail!"));return 0;}// 开始取流nRet = MV_CC_StartGrabbing(m_hDevHandle);if (MV_OK != nRet){AfxMessageBox(_T("Start Grabbing fail!"));return 0;}return 1; // 初始化成功}int CMvCamera::SaveCurrentImage(CString filePath) 
{MV_FRAME_OUT stOutFrame = { 0 };nRet = MV_CC_GetImageBuffer(m_hDevHandle, &stOutFrame, 1000);if (nRet != MV_OK) {AfxMessageBox(_T("获取图像失败!"));return -1;}// 分配输出缓冲区unsigned int nBufferSize = stOutFrame.stFrameInfo.nWidth * stOutFrame.stFrameInfo.nHeight * 4 + 2048;unsigned char* pImageBuf = new unsigned char[nBufferSize];MV_SAVE_IMAGE_PARAM_EX stSaveParam = { 0 };stSaveParam.pData = stOutFrame.pBufAddr;stSaveParam.nDataLen = stOutFrame.stFrameInfo.nFrameLen;stSaveParam.enPixelType = stOutFrame.stFrameInfo.enPixelType;stSaveParam.nWidth = stOutFrame.stFrameInfo.nWidth;stSaveParam.nHeight = stOutFrame.stFrameInfo.nHeight;stSaveParam.pImageBuffer = pImageBuf;stSaveParam.nBufferSize = nBufferSize;stSaveParam.enImageType = MV_Image_Jpeg;  // 优先尝试JPEGstSaveParam.nJpgQuality = 95;stSaveParam.iMethodValue = 2;  // 最优插值nRet = MV_CC_SaveImageEx2(m_hDevHandle, &stSaveParam);if (MV_OK != nRet) {delete[] pImageBuf;MV_CC_FreeImageBuffer(m_hDevHandle, &stOutFrame);CString strError;strError.Format(_T("转换失败! 错误码: 0x%X"), nRet);AfxMessageBox(strError);return -2;}// 保存到文件CFile file;if (!file.Open(filePath, CFile::modeCreate | CFile::modeWrite)) {delete[] pImageBuf;MV_CC_FreeImageBuffer(m_hDevHandle, &stOutFrame);AfxMessageBox(_T("创建文件失败!"));return -3;}file.Write(pImageBuf, stSaveParam.nImageLen);file.Close();// 释放资源delete[] pImageBuf;MV_CC_FreeImageBuffer(m_hDevHandle, &stOutFrame);return 0;
}void CMvCamera::CloseCamera()
{// ch:停止取流 | en:Stop grab imagenRet = MV_CC_StopGrabbing(m_hDevHandle);if (MV_OK != nRet){AfxMessageBox(_T("Stop Grabbing fail! \n"));}// ch:关闭设备 | Close devicenRet = MV_CC_CloseDevice(m_hDevHandle);if (MV_OK != nRet){AfxMessageBox(_T("ClosDevice fail\n"));}// ch:销毁句柄 | Destroy handlenRet = MV_CC_DestroyHandle(m_hDevHandle);if (MV_OK != nRet){AfxMessageBox(_T("Destroy Handle fail!\n"));}m_hDevHandle = NULL;}int CMvCamera::SetEnumValue(IN const char * strKey, IN unsigned int nValue)
{return MV_CC_SetEnumValue(m_hDevHandle, strKey, nValue);
}int CMvCamera::CommandExecute(IN const char * strKey)
{return MV_CC_SetCommandValue(m_hDevHandle, strKey);
}

点击按钮进行软触发拍照显示

void CHalconImgTestDlg::OnBnClickedGetimg()
{// 执行软件触发int nRet = m_oMvCamera->CommandExecute("TriggerSoftware");if (MV_OK != nRet){AfxMessageBox(_T("执行软件触发失败"));return;}// 获取图像MV_FRAME_OUT stOutFrame = { 0 };nRet = MV_CC_GetImageBuffer(m_oMvCamera->m_hDevHandle, &stOutFrame, 1000);if (nRet != MV_OK){AfxMessageBox(_T("获取图像失败!"));return;}// 转换为Halcon图像HalconCpp::HObject hImage;nRet = theApp.ConverMono8ToHalcon(&hImage, stOutFrame.stFrameInfo.nHeight,stOutFrame.stFrameInfo.nWidth, stOutFrame.pBufAddr);// 释放图像缓冲区MV_CC_FreeImageBuffer(m_oMvCamera->m_hDevHandle, &stOutFrame);if (nRet != MV_OK){AfxMessageBox(_T("转换到Halcon图像失败!"));return;}// 显示图像HTuple hv_WindowHandle;HWND hWnd = GetDlgItem(IDC_IMG)->m_hWnd;// 检查窗口是否已创建if (!HDevWindowStack::IsOpen()){// 创建新窗口OpenWindow(0, 0, stOutFrame.stFrameInfo.nWidth / 2, stOutFrame.stFrameInfo.nHeight / 2,(Hlong)hWnd, "visible", "", &hv_WindowHandle);HDevWindowStack::Push(hv_WindowHandle);}// 在现有窗口中显示图像if (HDevWindowStack::IsOpen()){DispObj(hImage, HDevWindowStack::GetActive());}
}

在这里插入图片描述

相关文章:

  • 【ROS】将Qt的Pro工程转换到ROS2的colcon
  • 【springcloud学习(dalston.sr1)】使用Feign实现接口调用(八)
  • spark小任务
  • AI产品上市前的“安全通行证“
  • 高防ip支持哪些网络协议
  • HDD 安全擦除:何时以及如何在 Windows PC 上安全擦除硬盘
  • vue3:十三、分类管理-表格--slot插槽详细说明---表格内拼接字段、tag标签
  • 微信小程序学习之搜索框
  • 【工具变量】各省市场化指数-杨兴权版共三个方法(1997-2023年)
  • C++类和对象之相关特性
  • bfs-最小步数问题
  • Leetcode数组day1
  • SpringAI
  • HandlerInterceptor介绍-笔记
  • NC65开发环境(eclipse启动)在企业报表中的报表数据中心里计算某张报表时,一直计算不出数据的解决办法。
  • C++类和对象练习:Date类实现日期的差,比较日期的大小,日期的前置后置++,--,输入输出Date类,对默认函数的练习。
  • uniapp使用全局组件,
  • Django + Celery 打造企业级大模型异步任务管理平台 —— 从需求到完整实践(含全模板源码)
  • VCS X-PROP建模以及在方针中的应用
  • 【MySQL】变更缓冲区:作用、主要配置以及如何查看
  • 退休夫妻月入1.2万负债1.2亿申请破产,律师:“诚实而不幸”系前置条件
  • 比特币价格重返10万美元,哪些因素使然?
  • 秦洪看盘|交易型资金收缩,释放短线压力
  • 河南省平顶山市副市长许红兵主动投案,接受审查调查
  • 98年服装“厂二代”:关税压力下,我仍相信中国供应链|湃客Talk
  • 中华人民共和国和俄罗斯联邦关于全球战略稳定的联合声明