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

一、软、硬件准备
  1. VS2017
  2. opencv3.4.6
  3. 相机:Basler acA2500-14gm
  4. 驱动:pylon
二、软硬件配置
  1. 下载安装pylon,到basler官方网站下载适合自己相机的pylon版本(我的是pylon 5.0),安装的时候注意选择安装开发者模式(开发者模式才含有SDK)。搜索相机IP并改成固定IP,使系统和相机利用路由器连接在同一个局域网内。
    打开Pylon View,在左边找到basler,右键选择pylon IP configurator,出现下面的窗口,查看IP地址和子网掩码,
    在这里插入图片描述
    然后配置电脑的IP地址和子网掩码。
    在这里插入图片描述
  2. 打开VS2017,配置包含目录和库目录。
    1)包含目录
    D:\Basler\pylon 6\Development\include(一定要根据自己安装目录来配置,不要复制)
    在这里插入图片描述
    2) 库目录
    在这里插入图片描述
三、Basler实时采集图像
  1. 相机界面
    基于MFC的对话框,创建自己的界面,并修改每个控件的ID
    在这里插入图片描述
  2. 头文件以及命名空间
#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;
  1. 设置静态全局变量
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 images
CPylonImage pylonImage;
CImageFormatConverter formatConverter;
static CRect rect;
static CInstantCamera camera;
static CGrabResultPtr ptrGrabResult;
  1. 将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);
  1. “开启设备”对应相应函数
    加载设备,并将其初始化与连接到对应的camera变量控制
	// TODO: 在此添加控件通知处理程序代码
	Open_device = TRUE;
	formatConverter.OutputPixelFormat = PixelType_BGR8packed;
	PylonInitialize();
	camera.Attach(CTlFactory::GetInstance().CreateFirstDevice());
	camera.Open();
	camera.MaxNumBuffer = 5;
  1. “开始采集“对应相应函数
    开始之后,先采集第一帧,并利用定时器一直采集并显示。
// 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); //定时器,定时时间和帧率一致
  1. 时间触发器函数
    这里使用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;
  1. ”停止采集“响应函数
    只需要停止采集和断开连接,如果不断开连接,下次就无法再加载设备了。
// TODO: 在此添加控件通知处理程序代码
	if (Open_device == false) {
		MessageBox(_T("未打开设备!!!"));
		return;
	}
	acquire = false;
	Open_device = false;
	camera.StopGrabbing();
	PylonTerminate();
	imshow("Basler", background);
  1. ”捕获图像“消息响应函数
	// 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);
  1. 调整曝光时间和增益对应的消息对应函数
    这里面利用成员变量来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);
	}

}
  • 8
    点赞
  • 53
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
### 回答1: Basler相机SDK开发是通过使用Basler相机开发工具包(SDK)来实现相机控制和图像采集的过程。Basler是一家专注于工业相机制造的公司,他们提供了多种不同型号的相机以满足各种应用需求。 使用Basler相机SDK进行开发,首先需要安装SDK并集成到开发环境中。SDK提供了一套丰富的API函数集,开发人员可以利用这些函数来控制相机功能,如设置曝光时间、增益、图像增强等。此外,SDK还提供了图像采集的功能,开发者可以通过调用相应的函数将图像传输到计算机的内存中,并进行后续处理。 在进行Basler相机SDK开发时,我们需要首先创建一个相机对象并设置相机的连接参数。然后可以调用相机对象的方法来打开相机、开始图像采集,以及停止图像采集。在图像采集过程中,可以通过SDK提供的回调函数来处理图像数据。例如,可以将图像存储到硬盘上,或者实时显示到屏幕上。 此外,Basler相机SDK还提供了对多相机系统的支持,可以同时控制多个相机进行图像采集。开发者可以设置相机的同步模式,确保多个相机之间的图像采集同步,以获得更准确的结果。 总之,Basler相机SDK开发是一项用于控制和采集Basler相机图像的技术,通过使用SDK提供的API函数和功能,开发人员可以方便地实现各种基于相机的应用程序,并满足不同行业的需求。 ### 回答2: Basler相机SDK开发是一种适用于Basler相机的软件开发工具包。它为开发者提供了一系列的API和工具,用于与Basler相机进行交互和控制,实现图像采集、处理和分析等功能。 使用Basler相机SDK开发,我们可以通过编写代码来控制相机的参数设置,如曝光时间、增益、白平衡等,实现对相机的灵活控制。同时,SDK还提供了图像采集的功能,可以利用相机实时采集图像数据,并在开发的应用程序中进行进一步的处理。 此外,Basler相机SDK还支持相机的硬件触发功能,通过控制相机输出的触发信号,可以在特定条件下精确控制图像的采集时机,以确保图像质量和稳定性。 SDK还包含了一系列的示例代码和开发文档,帮助开发者快速上手并实现自己的应用。开发文档详细介绍了SDK的各种功能和API的使用方法,示例代码则提供了一些常见应用场景的实现参考。 总之,Basler相机SDK开发开发者提供了强大的工具和功能,方便实现对Basler相机的控制和图像处理,可以广泛应用于工业自动化、机器视觉等领域,帮助用户快速开发出高性能的图像采集和处理系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值