700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 基于MFC的Basler工业相机SDK开发

基于MFC的Basler工业相机SDK开发

时间:2024-02-18 10:25:24

相关推荐

基于MFC的Basler工业相机SDK开发

一、软、硬件准备

VSopencv3.4.6相机:Basler acA2500-14gm驱动:pylon

二、软硬件配置

下载安装pylon,到basler官方网站下载适合自己相机的pylon版本(我的是pylon 5.0),安装的时候注意选择安装开发者模式(开发者模式才含有SDK)。搜索相机IP并改成固定IP,使系统和相机利用路由器连接在同一个局域网内。

打开Pylon View,在左边找到basler,右键选择pylon IP configurator,出现下面的窗口,查看IP地址和子网掩码,

然后配置电脑的IP地址和子网掩码。

打开VS,配置包含目录和库目录。

1)包含目录

D:\Basler\pylon 6\Development\include(一定要根据自己安装目录来配置,不要复制)

2) 库目录

三、Basler实时采集图像

相机界面

基于MFC的对话框,创建自己的界面,并修改每个控件的ID

头文件以及命名空间

#include "pch.h"#include "framework.h"#include "basler_basedemo.h"#include "basler_basedemoDlg.h"#include "afxdialogex.h"#include "opencv2/opencv.hpp"using namespace cv;using namespace std;#include "pylon/PylonIncludes.h"#include "pylon/gige/BaslerGigEInstantCamera.h"typedef Pylon::CBaslerGigEInstantCamera Camera_t;using namespace Pylon;using namespace Basler_GigECameraParams;using namespace GenApi;

设置静态全局变量

Mat background;//逻辑标志bool Open_device = false;bool acquire = false;bool grab_image = false;static Mat g_srcImage;static int ImgNum = 0;static Mat frame;// 创建一个Pylonlmage后续将用来创建OpenCV imagesCPylonImage pylonImage;CImageFormatConverter formatConverter;static CRect rect;static CInstantCamera camera;static CGrabResultPtr ptrGrabResult;

将Opencv窗口与MFC的picture control窗口连接

// TODO: 在此添加额外的初始化代码background = imread("仪器科学与光电工程学院.png");namedWindow("Basler", WINDOW_AUTOSIZE);HWND hWnd = (HWND)cvGetWindowHandle("Basler");HWND hParent = ::GetParent(hWnd);::SetParent(hWnd, GetDlgItem(IDC_STATIC_DEVICE)->m_hWnd);::ShowWindow(hParent, SW_HIDE);imshow("Basler", background);namedWindow("SHOW", WINDOW_AUTOSIZE);hWnd = (HWND)cvGetWindowHandle("SHOW");hParent = ::GetParent(hWnd);::SetParent(hWnd, GetDlgItem(IDC_STATIC_GRAB)->m_hWnd);::ShowWindow(hParent, SW_HIDE);imshow("SHOW", background);

“开启设备”对应相应函数

加载设备,并将其初始化与连接到对应的camera变量控制

// TODO: 在此添加控件通知处理程序代码Open_device = TRUE;formatConverter.OutputPixelFormat = PixelType_BGR8packed;PylonInitialize();camera.Attach(CTlFactory::GetInstance().CreateFirstDevice());camera.Open();camera.MaxNumBuffer = 5;

“开始采集“对应相应函数

开始之后,先采集第一帧,并利用定时器一直采集并显示。

// TODO: 在此添加控件通知处理程序代码if (Open_device == false) {MessageBox(_T("未打开设备!!!"));return;}acquire = TRUE;static const uint32_t c_countOfImagesToGrab = 100;camera.StartGrabbing(c_countOfImagesToGrab);if (camera.IsGrabbing()){camera.RetrieveResult(5000, ptrGrabResult, TimeoutHandling_ThrowException);if (ptrGrabResult->GrabSucceeded()){formatConverter.Convert(pylonImage, ptrGrabResult);frame = cv::Mat(ptrGrabResult->GetHeight(), ptrGrabResult->GetWidth(), CV_8UC3, (uint8_t *)pylonImage.GetBuffer());imshow("Basler", frame);}}SetTimer(1, 1002, NULL); //定时器,定时时间和帧率一致

时间触发器函数

这里使用SetTimer函数,需要添加计时器以实现循环。应用定时器实现动态显示相机采集到的图片

添加计时器:类向导-消息-WM-TIMER,双击添加OnTimer函数,如下

// TODO: 在此添加消息处理程序代码和/或调用默认值if (camera.IsGrabbing()){camera.RetrieveResult(5000, ptrGrabResult, TimeoutHandling_ThrowException);if (ptrGrabResult->GrabSucceeded()){formatConverter.Convert(pylonImage, ptrGrabResult);frame = cv::Mat(ptrGrabResult->GetHeight(), ptrGrabResult->GetWidth(), CV_8UC3, (uint8_t *)pylonImage.GetBuffer());imshow("Basler", frame);}}CDialogEx::OnTimer(WM_TIMER);return;

”停止采集“响应函数

只需要停止采集和断开连接,如果不断开连接,下次就无法再加载设备了。

// TODO: 在此添加控件通知处理程序代码if (Open_device == false) {MessageBox(_T("未打开设备!!!"));return;}acquire = false;Open_device = false;camera.StopGrabbing();PylonTerminate();imshow("Basler", background);

”捕获图像“消息响应函数

// TODO: 在此添加控件通知处理程序代码g_srcImage = frame;ImgNum++;if (acquire == false){MessageBox(_T("摄像头已关闭,无法捕捉图像!!!"));return;}//以下代码是完成图像的显示过程imshow("SHOW", g_srcImage);//图像保存string strSaveName;char buffer[256];sprintf_s(buffer, "D%04d", ImgNum);strSaveName = buffer;string outPutPath = "D:\\Picture\\";//定义保存图像的完整路径string strImgSavePath = outPutPath + "\\" + strSaveName;//定义保存图像的格式strImgSavePath += ".jpeg";strImgSavePath += ".png";//保存操作imwrite(strImgSavePath.c_str(), g_srcImage);

调整曝光时间和增益对应的消息对应函数

这里面利用成员变量来camera_gain和exposure_time来控制相机增益和曝光时间。由于博主的电脑不支持千兆网卡,所以曝光时间增长,降低帧率。

static int64_t Adjust(int64_t val, int64_t minimum, int64_t maximum, int64_t inc){// Check the input parameters.if (inc <= 0){// Negative increments are invalid.throw LOGICAL_ERROR_EXCEPTION("Unexpected increment %d", inc);}if (minimum > maximum){// Minimum must not be bigger than or equal to the maximum.throw LOGICAL_ERROR_EXCEPTION("minimum bigger than maximum.");}// Check the lower bound.if (val < minimum){return minimum;}// Check the upper bound.if (val > maximum){return maximum;}// Check the increment.if (inc == 1){// Special case: all values are valid.return val;}else{// The value must be min + (n * inc).// Due to the integer division, the value will be rounded down.return minimum + (((val - minimum) / inc) * inc);}}//调整曝光时间void CbaslerbasedemoDlg::OnEnChangeEdit2Exposure(){// TODO: 如果该控件是 RICHEDIT 控件,它将不// 发送此通知,除非重写 CDialogEx::OnInitDialog()// 函数并调用 CRichEditCtrl().SetEventMask(),// 同时将 ENM_CHANGE 标志“或”运算到掩码中。// TODO: 在此添加控件通知处理程序代码UpdateData(true);KillTimer(1);SetTimer(1, exposure_time / 1000, NULL);INodeMap& nodemap = camera.GetNodeMap();CIntegerPtr ptrExposureTimeRaw(nodemap.GetNode("ExposureTimeRaw"));if (IsWritable(ptrExposureTimeRaw)){int64_t newExposureTimeRaw = Adjust(exposure_time, ptrExposureTimeRaw->GetMin(), ptrExposureTimeRaw->GetMax(), ptrExposureTimeRaw->GetInc());exposure_time = newExposureTimeRaw;UpdateData(FALSE);ptrExposureTimeRaw->SetValue(newExposureTimeRaw);}}//调整相机增益void CbaslerbasedemoDlg::OnEnChangeEdit1Gain(){// TODO: 如果该控件是 RICHEDIT 控件,它将不// 发送此通知,除非重写 CDialogEx::OnInitDialog()// 函数并调用 CRichEditCtrl().SetEventMask(),// 同时将 ENM_CHANGE 标志“或”运算到掩码中。// TODO: 在此添加控件通知处理程序代码UpdateData(true);INodeMap& nodemap = camera.GetNodeMap();CEnumerationPtr PtrgainAuto(nodemap.GetNode("GainAuto"));if (IsWritable(PtrgainAuto)){PtrgainAuto->FromString("Off");}// Access the GainRaw integer type node.CIntegerPtr PtrgainRaw(nodemap.GetNode("GainRaw"));if (PtrgainRaw.IsValid()){// Make sure the calculated value is valid.int64_t newGainRaw = Adjust(camera_gain, PtrgainRaw->GetMin(), PtrgainRaw->GetMax(), PtrgainRaw->GetInc());camera_gain = newGainRaw;UpdateData(FALSE);PtrgainRaw->SetValue(newGainRaw);}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。