项目所需全部环境:
- OpenCV
- Spinnaker
上述环境是以我自己的代码可以运行为前提而配置的。
OpenCV
VS2017配置OpenCV可以参考这篇帖子:VS2017配置OpenCV-超详细教程 按照这个帖子来,可以成功配置OpenCV,但有几处可以精简。
1.环境变量
如图,加入 "D:\opencv\build\x64\vc15\bin"即可。
2.进入VS2017进行项目环境配置
原作者写的过于繁杂,在此精简,步骤为:
项目(P) 你自己的项目名 属性(P) VC++目录
VC++目录下只需要更改两个地方:包含目录、库目录。
包含目录
包含目录中需要存放的是 你下载的OpenCV文件夹中的include文件夹的位置,下面两张图可以很好地指明。
将include文件夹下的"D:\opencv\build\include\opencv"和"D:\opencv\build\include\opencv"都加入包含目录中。(不清楚为啥会有opencv和opencv2两个文件夹,保险起见都加进去吧)。至此包含目录配置完成。
库目录
库目录话不多说,直接上图。
按照图中的路径定位到你自己电脑上相应的位置,在x64文件夹下会有vc14和vc15两个文件夹,因为我们用的是VS2017,所以选用vc15(新版本的VS,比如VS2019,VS2022,下载的就是更新版本的OpenCV了,找好相应的版本就行)。
VC++相关的内容已经配置好了,下一步进入"链接器"。
链接器
链接器 输入 附加依赖项
在此处添加"opencv_world341d.lib",如图所示:
至此,环境配置全部结束。在原作者的帖子里,第六步“勾选微软符号服务器(此步为可选项)”就不要去配置了,百害而无一利。可以根据原帖的最后一步检测自己的OpenCV是否装好,如果没有图片显示出来,逛逛这个帖子下的评论区,可以解决,因为99%的概率是配环境的过程中哪里不小心搞错了,要耐心去排查。
Spinnaker
Spinnaker和OpenCV一样,都是让我们程序运行起来的工具,所以它的配置和上述的OpenCV几乎一样,只需要配置VC++目录下的包含目录、库目录,以及链接器中的附加依赖项就可以了,是不是很熟悉!我也放入以下三图供大家参考。贴心的一批!
检验下自己的Spinnaker有没有装好,复制这段代码运行,会出现Spinnaker版本库的版本号
#include<stdio.h>
#include<tchar.h>
#include "Spinnaker.h"
#include <iostream>
#include "SpinGenApi/SpinnakerGenApi.h"
using namespace Spinnaker;
using namespace Spinnaker::GenApi;
using namespace Spinnaker::GenICam;
using namespace std;
int main()
{
SystemPtr system = System::GetInstance();
LibraryVersion lv = system->GetLibraryVersion();
const LibraryVersion spinnakerLibraryVersion = system->GetLibraryVersion();
cout << "Spinnaker library version: " << spinnakerLibraryVersion.major << "." << spinnakerLibraryVersion.minor
<< "." << spinnakerLibraryVersion.type << "." << spinnakerLibraryVersion.build << endl
<< endl;
return 0;
}
运行结果如下:
在这里,有一个大坑。我之前安装的Spinnaker版本是3.x.x.xxx,而我的代码中有一句死活都报错,凭我多年的经验,我感觉是版本的问题,于是下载了比较低的版本(2.0.0.147),代码就一路绿灯了。
运行代码
// 测试用例 -- 两部相机正常调用
#include <iostream>
#include<sstream>
#include "Spinnaker.h"
#include "SpinGenApi/SpinnakerGenApi.h"
#include "opencv2/opencv.hpp"
using namespace Spinnaker;
using namespace Spinnaker::GenApi;
using namespace Spinnaker::GenICam;
using namespace cv;
using namespace std;
#define IMG_WIDTH 640
#define IMG_HEIGHT 480
// 传入参数类型为CameraList
void RunCameras(CameraList camList)
{
// 创建一个OpenCV的图像对象
cv::Size img_size(IMG_WIDTH, IMG_HEIGHT);
// 循环遍历相机列表 camlist 中所有相机
for (int i = 0; i < camList.GetSize(); ++i)
{
// 获取索引为i的相机,并赋值给 pCam 相机指针
CameraPtr pCam = camList.GetByIndex(i);
// 获取相机的设备映射点
INodeMap& nodeMapTLDevice = pCam->GetTLDeviceNodeMap();
// 初始化相机
pCam->Init();
// 获取相机的节点映射
INodeMap& nodeMap = pCam->GetNodeMap();
// 从相机的节点映射中获取了名为 "AcquisitionMode" 的节点
// 并将其赋值给名为 ptrAcquisitionMode 的枚举指针。
CEnumerationPtr ptrAcquisitionMode = nodeMap.GetNode("AcquisitionMode");
// 从"AcquisitionMode"节点的枚举值中获取了名为"Continuous"的枚举条目
// 并赋值给"ptrAcquisitionModeContinuous"枚举条目指针
CEnumEntryPtr ptrAcquisitionModeContinuous = ptrAcquisitionMode->GetEntryByName("Continuous");
// 获取"Continuous"的值,并赋值给acquisitionModeContinuous
const int64_t acquisitionModeContinuous = ptrAcquisitionModeContinuous->GetValue();
// 将相机的采集模式设置为连续模式
ptrAcquisitionMode->SetIntValue(acquisitionModeContinuous);
// 开始相机的图像采集过程,从此开始相机会持续获取图像。
pCam->BeginAcquisition();
}
char q; // 接收用户键入
while (true)
{
Mat l_img, r_img; // 定义2个OpenCV图像对象,用于存储左、右相机的图像
for (int i = 0; i < camList.GetSize(); ++i)
{
CameraPtr pCam = camList.GetByIndex(i);
// 从相机中获取下一帧图像,最多等待1秒钟,将结果保存在pResultImage中
ImagePtr pResultImage = pCam->GetNextImage(1000);
// 获取图像的宽度和高度
const size_t width = pResultImage->GetWidth();
const size_t height = pResultImage->GetHeight();
// 将获取到的图像转换为RGB8格式
ImagePtr convertedImage = pResultImage->Convert(PixelFormat_RGB8, NEAREST_NEIGHBOR);
// 将转换后的图像数据转为OpenCV的Mat格式
// Mat cvimg = cv::Mat(height, width, CV_8UC3, pResultImage->GetData(), pResultImage->GetStride());
Mat cvimg = cv::Mat(height, width, CV_8UC3, convertedImage->GetData(), convertedImage->GetStride());
// 将左右相机的图像进行尺寸调整,并存储在l_img和r_img中
if (i == 0) {
cv::resize(cvimg, l_img, img_size);
}
else {
cv::resize(cvimg, r_img, img_size);
}
pResultImage->Release(); // 释放获取到的图像资源
}
// 显示图像
cv::imshow("camera_1", l_img);
cv::imshow("camera_2", r_img);
// 等待用户键入
q = cv::waitKey(1);
if (q == 'q') break; // 结束图像采集过程
}
for (int i = 0; i < camList.GetSize(); ++i)
{
CameraPtr pCam = camList.GetByIndex(i);
pCam->EndAcquisition(); // 结束相机的图像采集
pCam->DeInit(); // 对相机进行反初始化,可能是释放资源等操作
}
}
int main()
{
// InitRecorreParams();
// 获取一个系统实例,用于初始化和管理相机
SystemPtr system = System::GetInstance();
// 获取Spinnaker库的版本信息,并输出至控制台
const LibraryVersion spinnakerLibraryVersion = system->GetLibraryVersion();
cout << "Spinnaker library version: " << spinnakerLibraryVersion.major << "." << spinnakerLibraryVersion.minor
<< "." << spinnakerLibraryVersion.type << "." << spinnakerLibraryVersion.build << endl
<< endl;
// 获取了相机列表,即检测到的所有连接至计算机的相机
CameraList camList = system->GetCameras();
// 获取相机数量并输出至控制台
const unsigned int numCameras = camList.GetSize();
cout << "Number of cameras detected: " << numCameras << endl << endl;
if (numCameras == 0)
{
std::cout << "no cameras..." << std::endl;
return 1;
}
CameraPtr pCam = nullptr;
int result = 0;
// 创建2个窗口,分别用于显示左右相机的图像
cv::namedWindow("camera_1", cv::WINDOW_NORMAL);
cv::namedWindow("camera_2", cv::WINDOW_NORMAL);
RunCameras(camList); // 采集相机图像并在窗口中显示
// 清理操作:将相机指针置为空指针;清空相机列表;释放相机系统实例。
pCam = nullptr;
camList.Clear();
system->ReleaseInstance();
// 等待用户按下Enter键,然后返回result
cout << endl << "Done! Press Enter to exit..." << endl;
getchar();
return result;
}
在电脑上接入2部相机,在此用的是Point Grey相机,只需要将相机的USB接口插入电脑就行了。不需要其他软件(比如Spin View)。看看最终的运行结果吧!