当前位置:   article > 正文

Dalsa线扫相机-二次开发-QT-C++ 可用Demo(一)_dalsa开发

dalsa开发

 效果展示

       Dalsa线扫描相机的二次开发,因为官方只有MFC和命令行版本的,我需要使用QT进行开发,于是自己花时间研究,然后写了一个,效果如下:

        可能GIF动图有点模糊,在图片中,上面为实时画面,我使用的是4096*128分辨率,然后使用手机的闪光灯在相机旁边摇晃,加上没有调焦调距,效果确实是如此。下面是实时拼接的图,将结果缩小旋转90度,然后依次拼接起来,就是下面拼接图片的效果。

        拼接图的右边那个黑框是截图时候参数没有设置好,后面已经改好了。

经验汇总

1. 大家参考的时候,记得对应自己的相机参数,包括:品牌、灰度/彩色、相机实际分辨率、网口/采集卡相机、软件版本等信息。

2. 我的版本是:

        相机:HL-FM 采集卡版本灰度相机

        SDK版本为:SaperaLTSDKSetup_8.60、

        采集卡驱动为:xtium2-clhs_fx8lc_110010122、

        QT版本:5.12

        编译器:MSVC 2017 64bit

        当然,实际只要版本差不多就行,我后面会提供我这个版本的软件驱动。

3. 我自己开发的步骤为:

  • 安装相机驱动和SDK 
  • 打开官方的 “Sapera CamExpert” 软件
  • 根据压缩包里面的 “HL-FM相机使用说明” 文件,进行相关配置,记得分辨率要调为自己的分辨率,不要完全按照文档来。点击 grab,拿着灯光在相机前晃,如果可以显示画面就正常。
  • 如上所示,就表示正常,因为我是灰度相机,就选择第一个了。
  • 点击这个软件的左上角 “file”  “save  as ” ,然后保存,如下图所示:
  • 上面的路径要记住,如果记不住,就点击 “Select Custom Directory”,自己保存在其他位置。这个很重要!!! 因为程序会使用这个配置文件,你必须记住路径,或者放在容易找到的路径才行!!!
  • 关闭软件(一定要关闭,因为会占用端口),打开 “ C:\Program Files\Teledyne DALSA\Sapera” ,这个是官方软件路径。会发现这么多文件夹。下面是解释:
  • 如果是MFC开发者,那爽了,直接参考和复制Demos文件夹的代码即可。如果是QT的开发者,一般来说,开发起来就很有难度了,因为里面有很多很多的坑,至少我之前在其他地方下载的代码还没跑起来过,要么就需要配置opencv,那样太麻烦了。
  • (想偷懒的,下面的步骤可以不看,直接去看我的代码即可)
  • 我自己首先是参考了'Examples'文件夹的 'Class' 的 'GrabConsole' 示例,记得需要使用 VS2017和2017之前的版本,之后的版本很容易出问题。
  • 在官方软件路径的CamFiles文件夹里面新建User,将刚刚保存的配置文件放进去。
  • 看一下 'Examples'文件夹的“Binaries”文件夹里面的 “GrabCPP.exe”,运行一下,看一下官方案例的效果。需要依次输入1、 1 、1,就会弹出窗口,实时显示画面。
  • 我最开始运行官方的Demo,发现跑不起来,重装了一次就可以了。然后移植到QT,发现一样的代码,就是跑不起来,经过多次修改,测试需要MSVC 2017编译器。这里面坑很多,想尝试的可以自己去踩一遍这些坑,但是呢,我把很多需要的坑已经踩完了,大家也可以直接参考后面的代码即可。

4. 创建QT测试项目

  • 注意:这里的Demo是在main文件里面的,只是一个测试使用的。提供大家以后测试参考
  • 想偷懒的,可以跳过这一步,去看下面已经初步封装好的代码。
  • 将官方软件路径里面的这三个文件夹:Classes、Include、Lib文件夹,直接复制拖进项目文件夹里面来,然后配置好pro路径。
  • pro文件代码参考:就是加入main.cpp和那三个文件夹,其他的测试过程可不加。
    1. QT += core gui
    2. greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    3. CONFIG += c++11
    4. # The following define makes your compiler emit warnings if you use
    5. # any Qt feature that has been marked deprecated (the exact warnings
    6. # depend on your compiler). Please consult the documentation of the
    7. # deprecated API in order to know how to port your code away from it.
    8. DEFINES += QT_DEPRECATED_WARNINGS
    9. #DEFINES += SAPERA_DOT_NET
    10. DEFINES += COR_WIN64
    11. #QMAKE_CXXFLAGS += -fno-case-insensitive
    12. QMAKE_CXXFLAGS += -fno-code-hoisting
    13. # You can also make your code fail to compile if it uses deprecated APIs.
    14. # In order to do so, uncomment the following line.
    15. # You can also select to disable deprecated APIs only up to a certain version of Qt.
    16. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
    17. SOURCES += \
    18. main.cpp
    19. # Default rules for deployment.
    20. qnx: target.path = /tmp/$${TARGET}/bin
    21. else: unix:!android: target.path = /opt/$${TARGET}/bin
    22. !isEmpty(target.path): INSTALLS += target
    23. win32: LIBS += -L$$PWD/Lib/Win64/ -lSapClassBasic
    24. win32: LIBS += -L$$PWD/Lib/Win64/ -lcorapi
    25. INCLUDEPATH += $$PWD/Include
    26. DEPENDPATH += $$PWD/Include
    27. INCLUDEPATH += $$PWD/Classes/Basic
    28. DEPENDPATH += $$PWD/Classes/Basic

  • 测试Demo源码:
    1. #include <iostream>
    2. #include"SapClassBasic.h"
    3. #include <SapBuffer.h>
    4. #include<conio.h>
    5. #include <string>
    6. #include <vector>
    7. #include <io.h>
    8. //#include <opencv2/opencv.hpp>
    9. #include <stdio.h>
    10. #include <QImage>
    11. #include <QApplication>
    12. using namespace std;
    13. SapManager* m_pManager;
    14. SapAcquisition* m_Acquisition;
    15. SapBufferWithTrash* m_Buffers;
    16. SapTransfer* m_Xfer;
    17. SapView* m_View;
    18. SapAcqDevice *m_AcqDevice;
    19. static int framcount = 0;
    20. BYTE *pData;
    21. static void XferCallBack(SapXferCallbackInfo* pInfo)
    22. {
    23. m_View->Show();
    24. }
    25. bool initDevice(char* m_serverName, const char*ccfpath)
    26. {
    27. printf("Sapera Console Grab Example (C++ version)\n");
    28. SapLocation loc(m_serverName, 0);
    29. if (SapManager::GetResourceCount(m_serverName, SapManager::ResourceAcq) > 0)
    30. {
    31. m_Acquisition = new SapAcquisition(loc, ccfpath);
    32. m_Buffers = new SapBufferWithTrash(2, m_Acquisition);
    33. m_View = new SapView(m_Buffers, SapHwndAutomatic);
    34. m_Xfer = new SapAcqToBuf(m_Acquisition, m_Buffers, XferCallBack, m_View);
    35. }
    36. if (m_Acquisition && !*m_Acquisition && !m_Acquisition->Create()) return FALSE;
    37. if (m_Buffers && !*m_Buffers)
    38. {
    39. if (!m_Buffers->Create())
    40. {
    41. return FALSE;
    42. }
    43. m_Buffers->Clear();
    44. }
    45. if (m_View && !*m_View && !m_View->Create())
    46. {
    47. return FALSE;
    48. }
    49. // Set next empty with trash cycle mode for transfer
    50. if (m_Xfer && m_Xfer->GetPair(0))
    51. {
    52. if (!m_Xfer->GetPair(0)->SetCycleMode(SapXferPair::CycleNextWithTrash))
    53. {
    54. return FALSE;
    55. }
    56. }
    57. // Create transfer object
    58. if (m_Xfer && !*m_Xfer && !m_Xfer->Create())
    59. {
    60. return FALSE;
    61. }
    62. return true;
    63. }
    64. int main(int argc, char** argv)
    65. {
    66. //QApplication a(argc, argv);
    67. char* m_SerName = new char[MAX_PATH];//采集卡名称
    68. char* configFilename = new char[MAX_PATH];
    69. SapBuffer sapBuffer;
    70. int flag = 0;
    71. string ccf_path = "C:\\Program Files\\Teledyne DALSA\\Sapera\\CamFiles\\User\\FrameGrabber.ccf";
    72. uchar *imgData = new uchar[150 * 100/1.75*7000];
    73. m_pManager->GetServerName(0, SapManager::ResourceAcq, m_SerName);
    74. //初始化设备
    75. if (initDevice(m_SerName, ccf_path.c_str()))
    76. {
    77. cout << "Open " << m_SerName << " Success!" << endl;
    78. }
    79. else
    80. {
    81. printf("m_SerName: %s \n",m_SerName);
    82. printf("configFilename: %s \n",configFilename);
    83. cout << "Open " << m_SerName << " Failed!" << endl;
    84. return 0;
    85. }
    86. //开始采集
    87. if (!m_Xfer->IsGrabbing())
    88. {
    89. m_Xfer->Grab();
    90. flag = 1;
    91. m_Buffers->GetAddress((void**)&pData);
    92. //int width = m_Buffers->GetWidth();
    93. //int height = m_Buffers->GetHeight();
    94. }
    95. while (true)
    96. {
    97. if (flag == 1)
    98. {
    99. std::cout << "Grab" << std::endl;
    100. //Sleep(200);
    101. std::stringstream ss;
    102. ss << "D:\\test\\bmp\\" << framcount << ".bmp";
    103. std::string name = ss.str();
    104. const char* savename = name.c_str();
    105. QImage image(4096 , 128, QImage::Format_Grayscale8);
    106. m_Buffers->Clear();
    107. if (!m_Xfer->IsGrabbing())
    108. m_Xfer->Grab();
    109. // 保存文件:
    110. // m_Buffers->Save(savename, "-format bmp");
    111. //m_Mats.push_back(m_Mat);
    112. framcount++;
    113. if (framcount > int(1000))
    114. {
    115. framcount = 0;
    116. cout << "Grab Finished" << endl;//停止采集
    117. m_Xfer->Freeze();
    118. break;
    119. }
    120. }
    121. }
    122. delete imgData;
    123. // Destroy transfer object
    124. if (m_Xfer && *m_Xfer) m_Xfer->Destroy();
    125. if (m_View && *m_View) m_View->Destroy();
    126. if (m_Buffers && *m_Buffers) m_Buffers->Destroy();
    127. if (m_Acquisition && *m_Acquisition) m_Acquisition->Destroy();
    128. //Delete all pointer
    129. if (m_View) delete m_View;
    130. if (m_Buffers) delete m_Buffers;
    131. if (m_Xfer) delete m_Xfer;
    132. if (m_Acquisition) delete m_Acquisition;
    133. //return a.exec();
    134. return 0;
    135. }

    其中 ccf_path  路径需要配置为自己刚刚保存的路径,然后路径中需要使用两个\ 来分割。m_Buffers->Save(savename, "-format bmp"); 这行代码我注释起来了,因为会保存文件,想看保存文件的,可以打开注释,路径在D盘的test/bmp路径下,记得别跑太长时间,因为几秒钟保存的图片文件就有好几个G那么大了。

  • 如果可以跑,大家可以使用这个代码来改写为自己的类。下面是我自己初步封装的QT的线程类,大家也可以修改。

5. 我自己封装的线程类:

        1. 新建 SapCameraDev 的类,继承自 Qthread,头文件源码如下:

  1. #ifndef SAPCAMERADEV_H
  2. #define SAPCAMERADEV_H
  3. #include "SapClassBasic.h"
  4. #include <QObject>
  5. #include <QThread>
  6. #include <iostream>
  7. #include <conio.h>
  8. #include <string>
  9. #include <vector>
  10. #include <stdio.h>
  11. #include <QImage>
  12. #include <io.h>
  13. #include <SapTransfer.h>
  14. using namespace std;
  15. class SapCameraDev : public QThread
  16. {
  17. Q_OBJECT
  18. public:
  19. explicit SapCameraDev(QObject *parent = nullptr);
  20. ~SapCameraDev();
  21. void setMax(int v);
  22. static void XferCallBack(SapXferCallbackInfo* pInfo);
  23. bool initDevice(char* m_serverName, const char*ccfpath);
  24. void setStopFlag(bool flag);
  25. void setSaveFlag(bool flag);
  26. void setFreezeFlag(bool flag);
  27. void setCcf_path(QString s);
  28. BYTE *getpData();
  29. // static SapCameraDev* instance;
  30. // static SapCameraDev* getSapCameraDevInstance()
  31. // {
  32. // if (instance == nullptr)
  33. // {
  34. // instance = new SapCameraDev();
  35. // }
  36. // return instance;
  37. // }
  38. signals:
  39. // void getNewImage(QImage image); // 接受到新信号
  40. void getNewImage(BYTE *pData);
  41. void getNewImage_Image(QImage );
  42. void imageOK(bool flag);
  43. private:
  44. void run() override;
  45. private:
  46. string saveImagePath = string("D:\\test\\bmp\\");
  47. string ccf_path = string("C:\\Program Files\\Teledyne DALSA\\Sapera\\CamFiles\\User\\FrameGrabber.ccf");
  48. int max = 1000;
  49. bool isStop = false;
  50. bool isSave = false;
  51. bool isFreeze = false; // 停止
  52. SapManager* m_pManager;
  53. SapAcquisition* m_Acquisition;
  54. SapBufferWithTrash* m_Buffers;
  55. SapTransfer* m_Xfer;
  56. SapView* m_View = nullptr;
  57. SapAcqDevice *m_AcqDevice;
  58. int framcount = 0;
  59. BYTE *pData;
  60. uchar *imgData = new uchar[150 * 100/1.75*7000];
  61. };
  62. #endif // SAPCAMERADEV_H

        2. SapCameraDev 的cpp文件源码如下:

  1. #include "sapCameraDev.h"
  2. //SapCameraDev* SapCameraDev::instance = nullptr;
  3. //BYTE *temp_pData;
  4. void SapCameraDev::XferCallBack(SapXferCallbackInfo* pInfo)
  5. {
  6. // printf("XferCallBack\n");
  7. // SapCameraDev* temp = getSapCameraDevInstance();
  8. // if(temp){
  9. // QImage image(4096 , 128, QImage::Format_Grayscale8);
  10. // memcpy(image.bits(), temp_pData, 4096 * 128);
  11. // emit temp->getNewImage_Image(image);
  12. // }
  13. }
  14. bool SapCameraDev::initDevice(char* m_serverName, const char*ccfpath)
  15. {
  16. printf("Sapera Console Grab Example (C++ version)\n");
  17. SapLocation loc(m_serverName, 0);
  18. if (SapManager::GetResourceCount(m_serverName, SapManager::ResourceAcq) > 0)
  19. {
  20. m_Acquisition = new SapAcquisition(loc, ccfpath);
  21. m_Buffers = new SapBufferWithTrash(2, m_Acquisition);
  22. // m_View = new SapView((SapBuffer*)m_Buffers, SapHwndAutomatic);
  23. m_Xfer = new SapAcqToBuf(m_Acquisition, (SapBuffer*)m_Buffers, SapCameraDev::XferCallBack);
  24. }
  25. if (m_Acquisition && !*m_Acquisition && !m_Acquisition->Create()) return FALSE;
  26. if (m_Buffers)
  27. {
  28. if (!m_Buffers->Create())
  29. {
  30. return FALSE;
  31. }
  32. m_Buffers->Clear();
  33. }
  34. if (m_Xfer && m_Xfer->GetPair(0))
  35. {
  36. if (!m_Xfer->GetPair(0)->SetCycleMode(SapXferPair::CycleNextWithTrash))
  37. {
  38. return FALSE;
  39. }
  40. }
  41. // Create transfer object
  42. if (m_Xfer && !*m_Xfer && !m_Xfer->Create())
  43. {
  44. return FALSE;
  45. }
  46. return true;
  47. }
  48. SapCameraDev::SapCameraDev(QObject *parent)
  49. :QThread(parent)
  50. {
  51. }
  52. void SapCameraDev::setStopFlag(bool flag)
  53. {
  54. isStop = flag;
  55. }
  56. void SapCameraDev::setSaveFlag(bool flag)
  57. {
  58. isSave = flag;
  59. }
  60. void SapCameraDev::setFreezeFlag(bool flag)
  61. {
  62. isFreeze = flag;
  63. }
  64. void SapCameraDev::setCcf_path(QString s)
  65. {
  66. ccf_path = s.toStdString();
  67. }
  68. BYTE * SapCameraDev::getpData()
  69. {
  70. return pData;
  71. }
  72. SapCameraDev::~SapCameraDev()
  73. {
  74. delete[] imgData;
  75. // Destroy transfer object
  76. if (m_Xfer && *m_Xfer) m_Xfer->Destroy();
  77. if (m_View && *m_View) m_View->Destroy();
  78. if (m_Buffers ) m_Buffers->Destroy();
  79. if (m_Acquisition && *m_Acquisition) m_Acquisition->Destroy();
  80. //Delete all pointer
  81. if (m_View) delete m_View;
  82. if (m_Buffers) delete m_Buffers;
  83. if (m_Xfer) delete m_Xfer;
  84. if (m_Acquisition) delete m_Acquisition;
  85. }
  86. void SapCameraDev::setMax(int v)
  87. {
  88. max = v;
  89. }
  90. void SapCameraDev::run()
  91. {
  92. char* m_SerName = new char[MAX_PATH];//采集卡名称
  93. char* configFilename = new char[MAX_PATH];
  94. int flag = 0;
  95. //vector<cv::Mat> m_Mats;
  96. // cv::Mat m_Mat_all = cv::Mat::zeros(cv::Size(700,85700), CV_8U);
  97. m_pManager->GetServerName(0, SapManager::ResourceAcq, m_SerName);
  98. //初始化设备
  99. if (initDevice(m_SerName, ccf_path.c_str()))
  100. {
  101. cout << "Open " << m_SerName << " Success!" << endl;
  102. }
  103. else
  104. {
  105. printf("m_SerName: %s \n",m_SerName);
  106. printf("configFilename: %s \n",ccf_path.c_str());
  107. cout << "Open " << m_SerName << " Failed!" << endl;
  108. return ;
  109. }
  110. //开始采集
  111. if (!m_Xfer->IsGrabbing())
  112. {
  113. m_Xfer->Grab();
  114. flag = 1;
  115. m_Buffers->GetAddress((void**)&pData);
  116. //temp_pData = pData;
  117. //int width = m_Buffers->GetWidth();
  118. //int height = m_Buffers->GetHeight();
  119. }
  120. std::cout << "Grab" << std::endl;
  121. while (true)
  122. {
  123. if (flag == 1)
  124. {
  125. //std::cout << "Grab" << std::endl;
  126. //Sleep(1);
  127. std::stringstream ss;
  128. ss << saveImagePath << framcount << ".bmp";
  129. std::string name = ss.str();
  130. const char* savename = name.c_str();
  131. QImage image(4096 , 128, QImage::Format_Grayscale8);
  132. if (isFreeze)
  133. {
  134. m_Xfer->Freeze();
  135. emit imageOK(false);
  136. }else{
  137. //m_Buffers->Clear();
  138. m_Xfer->Grab();
  139. // 传递QT图片信号
  140. // memcpy(image.bits(), pData, 4096 * 128);
  141. // emit getNewImage_Image(image);
  142. emit getNewImage(pData);
  143. QThread::usleep(1000);
  144. }
  145. if(isSave){
  146. m_Buffers->Save(savename, "-format bmp");
  147. framcount++;
  148. }
  149. if(isStop){
  150. framcount = 0;
  151. cout << "Grab Finished" << endl;//停止采集
  152. m_Xfer->Freeze();
  153. break;
  154. }
  155. if (framcount > max)
  156. {
  157. framcount = 0;
  158. isSave = false;
  159. cout << "save Finished" << endl;//停止采集
  160. //m_Xfer->Freeze();
  161. //break;
  162. }
  163. }
  164. }
  165. }

        3. 为了更好的展示,我自己新建了一个界面:

        4. mainwindow.h 源码:

  1. #ifndef MAINWINDOW_H
  2. #define MAINWINDOW_H
  3. #include <QMainWindow>
  4. #include <QPushButton>
  5. #include <QCheckBox>
  6. #include <QTransform>
  7. #include <QDebug>
  8. #include <QPixmap>
  9. #include <QPainter>
  10. #include <QImage>
  11. #include <QRect>
  12. #include <QTimer>
  13. #include "sapCameraDev.h"
  14. namespace Ui {
  15. class MainWindow;
  16. }
  17. class MainWindow : public QMainWindow
  18. {
  19. Q_OBJECT
  20. public:
  21. explicit MainWindow(QWidget *parent = nullptr);
  22. ~MainWindow();
  23. private:
  24. Ui::MainWindow *ui;
  25. SapCameraDev *sap;
  26. QImage *sapImage;
  27. QImage *resultImage;
  28. //QImage *middleImage;
  29. QPixmap *pixmap;
  30. QTimer *showTimer;
  31. QPainter *painter;
  32. int offset_x = 0;
  33. bool isImageOK = false;
  34. bool isSplic = false;
  35. };
  36. #endif // MAINWINDOW_H

        5. mainwindow.cpp源码:

  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. MainWindow::MainWindow(QWidget *parent) :
  4. QMainWindow(parent),
  5. ui(new Ui::MainWindow)
  6. {
  7. ui->setupUi(this);
  8. sap = new SapCameraDev(this);
  9. // 绑定按钮的信号
  10. connect(ui->pushButton_start,&QPushButton::clicked,this,[=](){
  11. sap->setStopFlag(false);
  12. sap->setFreezeFlag(false);
  13. sap->start();
  14. });
  15. connect(ui->pushButton_freeze,&QPushButton::clicked,this,[=](){ //
  16. sap->setFreezeFlag(true);
  17. });
  18. connect(ui->pushButton_stop,&QPushButton::clicked,this,[=](){
  19. sap->setStopFlag(true);
  20. });
  21. connect(ui->pushButton_continue,&QPushButton::clicked,this,[=](){
  22. sap->setFreezeFlag(false);
  23. });
  24. connect(ui->checkBox_saveFile,&QCheckBox::stateChanged,this,[=](int flag){
  25. sap->setSaveFlag(flag);
  26. });
  27. connect(ui->checkBox_splic,&QCheckBox::stateChanged,this,[=](int flag){
  28. isSplic = flag;
  29. resultImage->fill(Qt::transparent);
  30. });
  31. // connect(sap,&SapCameraDev::imageOK,this,[=](bool flag){
  32. // isImageOK = flag;
  33. // offset_x = 0;
  34. // });
  35. // 实时图像:
  36. sapImage = new QImage(4096, 128, QImage::Format_Grayscale8);
  37. // 拼接图像:
  38. resultImage = new QImage(1024,256,QImage::Format_Grayscale8);
  39. resultImage->fill(Qt::transparent); // 透明色
  40. painter = new QPainter(resultImage);
  41. ui->label->setScaledContents(true); // 允许自动缩放
  42. ui->label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // 水平方向上自动伸展,垂直方向上保持固定高度
  43. ui->label_2->setScaledContents(true); // 允许自动缩放
  44. ui->label_2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // 水平方向上自动伸展,垂直方向上保持固定高度
  45. ui->label_2->setPixmap(QPixmap::fromImage(*resultImage));
  46. //ui->label->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored); // 忽略大小策略
  47. // 接收线程类发送来的信号进行图片渲染:
  48. connect(sap,&SapCameraDev::getNewImage,this,[=](BYTE *pData){
  49. // 显示实时画面:
  50. memcpy(sapImage->bits(), pData, 4096 * 128);
  51. ui->label->setPixmap(QPixmap::fromImage(*sapImage));
  52. // 是否拼接:
  53. if(isSplic){
  54. // 显示拼接画面:
  55. // 旋转:
  56. QImage rotatedImage = sapImage->scaled(256, 8, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
  57. rotatedImage = rotatedImage.transformed(QTransform().rotate(90));
  58. if(offset_x<1024){
  59. painter->drawImage(offset_x,0,rotatedImage);
  60. offset_x += rotatedImage.width();
  61. ui->label_2->setPixmap(QPixmap::fromImage(*resultImage));
  62. }else{
  63. offset_x = 0;
  64. }
  65. }
  66. });
  67. }
  68. MainWindow::~MainWindow()
  69. {
  70. delete ui;
  71. sap->quit();
  72. }

        OK,撒花完结!!!

        其实源码95%都已经给你们放出来了,有能力的自己已经可以做出来了,毕竟当时踩了很多坑,而且当时下载别人的案例,也花了一点小钱,而且他们的还运行不起来,我把我自己的源码放出来,收回一点成本可以吧。不求大富大贵,最起码回本啊,兄弟们,还望理解。

        

        额,不知道为什么,必须设置为免费的,还是0积分,晕死,我先看看如何设置再分享出来。

相关资源链接:

【免费】Dalsa线扫描相机资源分享(一)-安装驱动和配置说明资源-CSDN文库

【免费】Dalsa线扫描相机资源分享(二)-开发文档资源-CSDN文库

【免费】Dalsa线扫描相机资源分享(三)-简单的QT测试程序,未封装类资源-CSDN文库

参考文章:

Dalsa线扫相机SDK二次开发_dalsa相机二次开发-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/356974
推荐阅读
相关标签
  

闽ICP备14008679号