赞
踩
Dalsa线扫描相机的二次开发,因为官方只有MFC和命令行版本的,我需要使用QT进行开发,于是自己花时间研究,然后写了一个,效果如下:
可能GIF动图有点模糊,在图片中,上面为实时画面,我使用的是4096*128分辨率,然后使用手机的闪光灯在相机旁边摇晃,加上没有调焦调距,效果确实是如此。下面是实时拼接的图,将结果缩小旋转90度,然后依次拼接起来,就是下面拼接图片的效果。
拼接图的右边那个黑框是截图时候参数没有设置好,后面已经改好了。
相机:HL-FM 采集卡版本灰度相机
SDK版本为:SaperaLTSDKSetup_8.60、
采集卡驱动为:xtium2-clhs_fx8lc_110010122、
QT版本:5.12
编译器:MSVC 2017 64bit
当然,实际只要版本差不多就行,我后面会提供我这个版本的软件驱动。
- QT += core gui
-
- greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
-
- CONFIG += c++11
-
- # The following define makes your compiler emit warnings if you use
- # any Qt feature that has been marked deprecated (the exact warnings
- # depend on your compiler). Please consult the documentation of the
- # deprecated API in order to know how to port your code away from it.
- DEFINES += QT_DEPRECATED_WARNINGS
- #DEFINES += SAPERA_DOT_NET
- DEFINES += COR_WIN64
-
- #QMAKE_CXXFLAGS += -fno-case-insensitive
- QMAKE_CXXFLAGS += -fno-code-hoisting
-
- # You can also make your code fail to compile if it uses deprecated APIs.
- # In order to do so, uncomment the following line.
- # You can also select to disable deprecated APIs only up to a certain version of Qt.
- #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
-
- SOURCES += \
- main.cpp
-
-
-
- # Default rules for deployment.
- qnx: target.path = /tmp/$${TARGET}/bin
- else: unix:!android: target.path = /opt/$${TARGET}/bin
- !isEmpty(target.path): INSTALLS += target
-
-
- win32: LIBS += -L$$PWD/Lib/Win64/ -lSapClassBasic
- win32: LIBS += -L$$PWD/Lib/Win64/ -lcorapi
-
- INCLUDEPATH += $$PWD/Include
- DEPENDPATH += $$PWD/Include
-
- INCLUDEPATH += $$PWD/Classes/Basic
- DEPENDPATH += $$PWD/Classes/Basic
-
-
- #include <iostream>
- #include"SapClassBasic.h"
- #include <SapBuffer.h>
- #include<conio.h>
- #include <string>
- #include <vector>
- #include <io.h>
- //#include <opencv2/opencv.hpp>
- #include <stdio.h>
- #include <QImage>
- #include <QApplication>
- using namespace std;
-
- SapManager* m_pManager;
- SapAcquisition* m_Acquisition;
- SapBufferWithTrash* m_Buffers;
- SapTransfer* m_Xfer;
- SapView* m_View;
- SapAcqDevice *m_AcqDevice;
- static int framcount = 0;
- BYTE *pData;
-
- static void XferCallBack(SapXferCallbackInfo* pInfo)
- {
- m_View->Show();
- }
- bool initDevice(char* m_serverName, const char*ccfpath)
- {
- printf("Sapera Console Grab Example (C++ version)\n");
-
- SapLocation loc(m_serverName, 0);
-
- if (SapManager::GetResourceCount(m_serverName, SapManager::ResourceAcq) > 0)
- {
- m_Acquisition = new SapAcquisition(loc, ccfpath);
- m_Buffers = new SapBufferWithTrash(2, m_Acquisition);
- m_View = new SapView(m_Buffers, SapHwndAutomatic);
- m_Xfer = new SapAcqToBuf(m_Acquisition, m_Buffers, XferCallBack, m_View);
- }
-
- if (m_Acquisition && !*m_Acquisition && !m_Acquisition->Create()) return FALSE;
-
- if (m_Buffers && !*m_Buffers)
- {
- if (!m_Buffers->Create())
- {
- return FALSE;
- }
- m_Buffers->Clear();
- }
-
- if (m_View && !*m_View && !m_View->Create())
- {
- return FALSE;
- }
-
- // Set next empty with trash cycle mode for transfer
-
- if (m_Xfer && m_Xfer->GetPair(0))
- {
- if (!m_Xfer->GetPair(0)->SetCycleMode(SapXferPair::CycleNextWithTrash))
- {
- return FALSE;
- }
- }
-
- // Create transfer object
- if (m_Xfer && !*m_Xfer && !m_Xfer->Create())
- {
- return FALSE;
- }
- return true;
- }
-
- int main(int argc, char** argv)
- {
- //QApplication a(argc, argv);
-
- char* m_SerName = new char[MAX_PATH];//采集卡名称
- char* configFilename = new char[MAX_PATH];
- SapBuffer sapBuffer;
- int flag = 0;
- string ccf_path = "C:\\Program Files\\Teledyne DALSA\\Sapera\\CamFiles\\User\\FrameGrabber.ccf";
- uchar *imgData = new uchar[150 * 100/1.75*7000];
-
-
- m_pManager->GetServerName(0, SapManager::ResourceAcq, m_SerName);
-
-
- //初始化设备
- if (initDevice(m_SerName, ccf_path.c_str()))
- {
- cout << "Open " << m_SerName << " Success!" << endl;
- }
- else
- {
- printf("m_SerName: %s \n",m_SerName);
- printf("configFilename: %s \n",configFilename);
- cout << "Open " << m_SerName << " Failed!" << endl;
- return 0;
- }
-
-
- //开始采集
- if (!m_Xfer->IsGrabbing())
- {
- m_Xfer->Grab();
- flag = 1;
- m_Buffers->GetAddress((void**)&pData);
- //int width = m_Buffers->GetWidth();
- //int height = m_Buffers->GetHeight();
- }
- while (true)
- {
- if (flag == 1)
- {
- std::cout << "Grab" << std::endl;
- //Sleep(200);
- std::stringstream ss;
- ss << "D:\\test\\bmp\\" << framcount << ".bmp";
- std::string name = ss.str();
- const char* savename = name.c_str();
- QImage image(4096 , 128, QImage::Format_Grayscale8);
- m_Buffers->Clear();
- if (!m_Xfer->IsGrabbing())
- m_Xfer->Grab();
- // 保存文件:
- // m_Buffers->Save(savename, "-format bmp");
- //m_Mats.push_back(m_Mat);
- framcount++;
-
- if (framcount > int(1000))
- {
- framcount = 0;
- cout << "Grab Finished" << endl;//停止采集
- m_Xfer->Freeze();
- break;
- }
-
-
- }
- }
- delete imgData;
- // Destroy transfer object
- if (m_Xfer && *m_Xfer) m_Xfer->Destroy();
- if (m_View && *m_View) m_View->Destroy();
- if (m_Buffers && *m_Buffers) m_Buffers->Destroy();
- if (m_Acquisition && *m_Acquisition) m_Acquisition->Destroy();
-
- //Delete all pointer
- if (m_View) delete m_View;
- if (m_Buffers) delete m_Buffers;
- if (m_Xfer) delete m_Xfer;
- if (m_Acquisition) delete m_Acquisition;
-
-
- //return a.exec();
- return 0;
- }
其中 ccf_path 路径需要配置为自己刚刚保存的路径,然后路径中需要使用两个\ 来分割。m_Buffers->Save(savename, "-format bmp"); 这行代码我注释起来了,因为会保存文件,想看保存文件的,可以打开注释,路径在D盘的test/bmp路径下,记得别跑太长时间,因为几秒钟保存的图片文件就有好几个G那么大了。
1. 新建 SapCameraDev 的类,继承自 Qthread,头文件源码如下:
- #ifndef SAPCAMERADEV_H
- #define SAPCAMERADEV_H
-
- #include "SapClassBasic.h"
-
- #include <QObject>
- #include <QThread>
- #include <iostream>
- #include <conio.h>
- #include <string>
- #include <vector>
- #include <stdio.h>
- #include <QImage>
- #include <io.h>
- #include <SapTransfer.h>
-
- using namespace std;
-
- class SapCameraDev : public QThread
- {
- Q_OBJECT
- public:
- explicit SapCameraDev(QObject *parent = nullptr);
- ~SapCameraDev();
- void setMax(int v);
- static void XferCallBack(SapXferCallbackInfo* pInfo);
- bool initDevice(char* m_serverName, const char*ccfpath);
- void setStopFlag(bool flag);
- void setSaveFlag(bool flag);
- void setFreezeFlag(bool flag);
- void setCcf_path(QString s);
- BYTE *getpData();
- // static SapCameraDev* instance;
- // static SapCameraDev* getSapCameraDevInstance()
- // {
- // if (instance == nullptr)
- // {
- // instance = new SapCameraDev();
- // }
- // return instance;
- // }
-
- signals:
- // void getNewImage(QImage image); // 接受到新信号
- void getNewImage(BYTE *pData);
- void getNewImage_Image(QImage );
- void imageOK(bool flag);
-
- private:
- void run() override;
-
-
- private:
-
- string saveImagePath = string("D:\\test\\bmp\\");
- string ccf_path = string("C:\\Program Files\\Teledyne DALSA\\Sapera\\CamFiles\\User\\FrameGrabber.ccf");
- int max = 1000;
- bool isStop = false;
- bool isSave = false;
- bool isFreeze = false; // 停止
-
- SapManager* m_pManager;
- SapAcquisition* m_Acquisition;
- SapBufferWithTrash* m_Buffers;
- SapTransfer* m_Xfer;
- SapView* m_View = nullptr;
- SapAcqDevice *m_AcqDevice;
- int framcount = 0;
- BYTE *pData;
- uchar *imgData = new uchar[150 * 100/1.75*7000];
- };
-
- #endif // SAPCAMERADEV_H
2. SapCameraDev 的cpp文件源码如下:
- #include "sapCameraDev.h"
-
- //SapCameraDev* SapCameraDev::instance = nullptr;
- //BYTE *temp_pData;
-
- void SapCameraDev::XferCallBack(SapXferCallbackInfo* pInfo)
- {
- // printf("XferCallBack\n");
- // SapCameraDev* temp = getSapCameraDevInstance();
- // if(temp){
- // QImage image(4096 , 128, QImage::Format_Grayscale8);
- // memcpy(image.bits(), temp_pData, 4096 * 128);
- // emit temp->getNewImage_Image(image);
- // }
- }
- bool SapCameraDev::initDevice(char* m_serverName, const char*ccfpath)
- {
- printf("Sapera Console Grab Example (C++ version)\n");
-
- SapLocation loc(m_serverName, 0);
-
- if (SapManager::GetResourceCount(m_serverName, SapManager::ResourceAcq) > 0)
- {
- m_Acquisition = new SapAcquisition(loc, ccfpath);
- m_Buffers = new SapBufferWithTrash(2, m_Acquisition);
- // m_View = new SapView((SapBuffer*)m_Buffers, SapHwndAutomatic);
- m_Xfer = new SapAcqToBuf(m_Acquisition, (SapBuffer*)m_Buffers, SapCameraDev::XferCallBack);
- }
-
- if (m_Acquisition && !*m_Acquisition && !m_Acquisition->Create()) return FALSE;
-
- if (m_Buffers)
- {
- if (!m_Buffers->Create())
- {
- return FALSE;
- }
- m_Buffers->Clear();
- }
-
- if (m_Xfer && m_Xfer->GetPair(0))
- {
- if (!m_Xfer->GetPair(0)->SetCycleMode(SapXferPair::CycleNextWithTrash))
- {
- return FALSE;
- }
- }
-
- // Create transfer object
- if (m_Xfer && !*m_Xfer && !m_Xfer->Create())
- {
- return FALSE;
- }
- return true;
- }
- SapCameraDev::SapCameraDev(QObject *parent)
- :QThread(parent)
- {
-
- }
-
- void SapCameraDev::setStopFlag(bool flag)
- {
- isStop = flag;
- }
-
- void SapCameraDev::setSaveFlag(bool flag)
- {
- isSave = flag;
- }
-
- void SapCameraDev::setFreezeFlag(bool flag)
- {
- isFreeze = flag;
- }
-
- void SapCameraDev::setCcf_path(QString s)
- {
- ccf_path = s.toStdString();
- }
-
- BYTE * SapCameraDev::getpData()
- {
- return pData;
- }
-
-
-
- SapCameraDev::~SapCameraDev()
- {
- delete[] imgData;
- // Destroy transfer object
- if (m_Xfer && *m_Xfer) m_Xfer->Destroy();
- if (m_View && *m_View) m_View->Destroy();
- if (m_Buffers ) m_Buffers->Destroy();
- if (m_Acquisition && *m_Acquisition) m_Acquisition->Destroy();
-
- //Delete all pointer
- if (m_View) delete m_View;
- if (m_Buffers) delete m_Buffers;
- if (m_Xfer) delete m_Xfer;
- if (m_Acquisition) delete m_Acquisition;
- }
-
- void SapCameraDev::setMax(int v)
- {
- max = v;
- }
-
- void SapCameraDev::run()
- {
- char* m_SerName = new char[MAX_PATH];//采集卡名称
- char* configFilename = new char[MAX_PATH];
- int flag = 0;
- //vector<cv::Mat> m_Mats;
-
- // cv::Mat m_Mat_all = cv::Mat::zeros(cv::Size(700,85700), CV_8U);
-
- m_pManager->GetServerName(0, SapManager::ResourceAcq, m_SerName);
-
- //初始化设备
- if (initDevice(m_SerName, ccf_path.c_str()))
- {
- cout << "Open " << m_SerName << " Success!" << endl;
- }
- else
- {
- printf("m_SerName: %s \n",m_SerName);
- printf("configFilename: %s \n",ccf_path.c_str());
- cout << "Open " << m_SerName << " Failed!" << endl;
- return ;
- }
-
-
- //开始采集
- if (!m_Xfer->IsGrabbing())
- {
- m_Xfer->Grab();
- flag = 1;
- m_Buffers->GetAddress((void**)&pData);
- //temp_pData = pData;
- //int width = m_Buffers->GetWidth();
- //int height = m_Buffers->GetHeight();
- }
- std::cout << "Grab" << std::endl;
- while (true)
- {
- if (flag == 1)
- {
- //std::cout << "Grab" << std::endl;
- //Sleep(1);
- std::stringstream ss;
- ss << saveImagePath << framcount << ".bmp";
- std::string name = ss.str();
- const char* savename = name.c_str();
- QImage image(4096 , 128, QImage::Format_Grayscale8);
-
- if (isFreeze)
- {
- m_Xfer->Freeze();
- emit imageOK(false);
- }else{
- //m_Buffers->Clear();
- m_Xfer->Grab();
-
- // 传递QT图片信号
- // memcpy(image.bits(), pData, 4096 * 128);
- // emit getNewImage_Image(image);
-
- emit getNewImage(pData);
- QThread::usleep(1000);
- }
-
- if(isSave){
- m_Buffers->Save(savename, "-format bmp");
- framcount++;
- }
-
- if(isStop){
- framcount = 0;
- cout << "Grab Finished" << endl;//停止采集
- m_Xfer->Freeze();
- break;
- }
-
- if (framcount > max)
- {
- framcount = 0;
- isSave = false;
- cout << "save Finished" << endl;//停止采集
- //m_Xfer->Freeze();
- //break;
- }
- }
- }
- }
-
-
3. 为了更好的展示,我自己新建了一个界面:
4. mainwindow.h 源码:
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
-
- #include <QMainWindow>
- #include <QPushButton>
- #include <QCheckBox>
- #include <QTransform>
- #include <QDebug>
- #include <QPixmap>
- #include <QPainter>
- #include <QImage>
- #include <QRect>
- #include <QTimer>
- #include "sapCameraDev.h"
-
- namespace Ui {
- class MainWindow;
- }
-
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
-
- public:
- explicit MainWindow(QWidget *parent = nullptr);
- ~MainWindow();
-
- private:
- Ui::MainWindow *ui;
- SapCameraDev *sap;
- QImage *sapImage;
- QImage *resultImage;
- //QImage *middleImage;
- QPixmap *pixmap;
- QTimer *showTimer;
- QPainter *painter;
-
- int offset_x = 0;
-
- bool isImageOK = false;
- bool isSplic = false;
- };
-
- #endif // MAINWINDOW_H
5. mainwindow.cpp源码:
- #include "mainwindow.h"
- #include "ui_mainwindow.h"
-
- MainWindow::MainWindow(QWidget *parent) :
- QMainWindow(parent),
- ui(new Ui::MainWindow)
- {
- ui->setupUi(this);
- sap = new SapCameraDev(this);
-
- // 绑定按钮的信号
- connect(ui->pushButton_start,&QPushButton::clicked,this,[=](){
- sap->setStopFlag(false);
- sap->setFreezeFlag(false);
- sap->start();
- });
- connect(ui->pushButton_freeze,&QPushButton::clicked,this,[=](){ //
- sap->setFreezeFlag(true);
- });
- connect(ui->pushButton_stop,&QPushButton::clicked,this,[=](){
- sap->setStopFlag(true);
- });
- connect(ui->pushButton_continue,&QPushButton::clicked,this,[=](){
- sap->setFreezeFlag(false);
- });
- connect(ui->checkBox_saveFile,&QCheckBox::stateChanged,this,[=](int flag){
- sap->setSaveFlag(flag);
- });
- connect(ui->checkBox_splic,&QCheckBox::stateChanged,this,[=](int flag){
- isSplic = flag;
- resultImage->fill(Qt::transparent);
- });
-
- // connect(sap,&SapCameraDev::imageOK,this,[=](bool flag){
- // isImageOK = flag;
- // offset_x = 0;
- // });
-
- // 实时图像:
- sapImage = new QImage(4096, 128, QImage::Format_Grayscale8);
- // 拼接图像:
- resultImage = new QImage(1024,256,QImage::Format_Grayscale8);
- resultImage->fill(Qt::transparent); // 透明色
- painter = new QPainter(resultImage);
-
- ui->label->setScaledContents(true); // 允许自动缩放
- ui->label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // 水平方向上自动伸展,垂直方向上保持固定高度
-
- ui->label_2->setScaledContents(true); // 允许自动缩放
- ui->label_2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // 水平方向上自动伸展,垂直方向上保持固定高度
- ui->label_2->setPixmap(QPixmap::fromImage(*resultImage));
- //ui->label->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); // 忽略大小策略
-
- // 接收线程类发送来的信号进行图片渲染:
- connect(sap,&SapCameraDev::getNewImage,this,[=](BYTE *pData){
- // 显示实时画面:
- memcpy(sapImage->bits(), pData, 4096 * 128);
- ui->label->setPixmap(QPixmap::fromImage(*sapImage));
-
- // 是否拼接:
- if(isSplic){
- // 显示拼接画面:
- // 旋转:
- QImage rotatedImage = sapImage->scaled(256, 8, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
- rotatedImage = rotatedImage.transformed(QTransform().rotate(90));
-
- if(offset_x<1024){
- painter->drawImage(offset_x,0,rotatedImage);
- offset_x += rotatedImage.width();
- ui->label_2->setPixmap(QPixmap::fromImage(*resultImage));
- }else{
- offset_x = 0;
- }
-
- }
-
- });
-
- }
-
- MainWindow::~MainWindow()
- {
- delete ui;
- sap->quit();
- }
OK,撒花完结!!!
其实源码95%都已经给你们放出来了,有能力的自己已经可以做出来了,毕竟当时踩了很多坑,而且当时下载别人的案例,也花了一点小钱,而且他们的还运行不起来,我把我自己的源码放出来,收回一点成本可以吧。不求大富大贵,最起码回本啊,兄弟们,还望理解。
额,不知道为什么,必须设置为免费的,还是0积分,晕死,我先看看如何设置再分享出来。
相关资源链接:
【免费】Dalsa线扫描相机资源分享(一)-安装驱动和配置说明资源-CSDN文库
【免费】Dalsa线扫描相机资源分享(二)-开发文档资源-CSDN文库
【免费】Dalsa线扫描相机资源分享(三)-简单的QT测试程序,未封装类资源-CSDN文库
参考文章:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。