跳至內容
測試伺服器
開發伺服器

C++程式設計人員指南#

本主題提供專屬於 Basler blaze 與 Smart blaze 相機的資訊,並未旨在提供 pylon C++ API 的全面性概觀。

如果您是 pylon 的新手,Basler 建議您先閱讀 pylon C++ Programmer's Guide 中的 Getting Started 章節,以熟悉 pylon C++ API。

資訊

本主題中的所有資訊均適用於所有 blaze 和 Smart blaze 相機型號。為求簡潔,文中以「blaze」統稱所有型號。

C++ Programming Samples#

To open the folder containing the programming samples for blaze cameras, press the Win key, go to the Basler folder, and choose blaze Samples. A File Explorer window opens. The C++ programming samples are located in the cpp folder.

The C++ samples are located in the /opt/pylon/share/pylon/Samples/blaze/cpp folder.

建置範例的前置作業#

  • CMake 3.3 or above
  • Optional: Aravis

On an Ubuntu system, you can install the prerequisites by issuing the following command:

    sudo apt -y install build-essential cmake libopencv-dev libpcl-dev libboost-all-dev

Info

There is no Debian package available for the Aravis library. Aravis must be built from sources instead.

如何建置範例#

資訊

在建置範例之前,請將包含範例的資料夾複製到您具有讀寫權限的任意位置。

CMake 用作構建 C++ 範例的構建系統。

Windows#

  1. Start Visual Studio.
  2. On the start page, choose the Open Folder or Open a local folder option, and navigate to the folder you copied the samples to.
  3. Open the cpp subfolder and click the Select Folder button.

Visual Studio runs CMake in the background. It will take a moment until you can build the samples by selecting Build All in the Build menu.

When you don't want to use Visual Studio's CMake integration, you can use the cmake-gui tool to generate Visual Studio solution and project files that you can open with Visual Studio.

If there is no CMake >= 3.3 installed, download a CMake Windows installer from the CMake website. Launch the .msi installer and follow the instructions.

To generate Visual Studio project and solution files for the blaze samples:

  1. Start cmake-gui.
  2. Click the Browse Source… button, and navigate to the folder you copied the samples to.
  3. Open the cpp folder by clicking the Select folder button.
  4. Specify a folder where the binaries will be built by clicking the Browse Build… button and choosing or creating a folder of your choice.
    Basler advises against choosing the root folder of the source tree, i.e., the folder this document is located in. Common practice is to create a subfolder (e.g., named build).
  5. Click the Configure button.
    A dialog opens.
  6. Choose the desired Visual Studio version and platform.
    Make sure that the selected platform (x86 or x64) matches the architecture that the OpenCV and PCL libraries are built for.
  7. Click the Finish button to close the dialog.
    The configuration procedure starts.
  8. Once the configuration procedure has succeeded, click the Generate button to create the Visual Studio project and solution files.
    The files will be generated in the build folder that you specified earlier.
  9. Navigate to that build folder and open the .sln file.

Now, you can build the samples by selecting Build All in the Build menu.

如果您在構建和運行範例時遇到問題,請參閱 Troubleshooting 主題。

Linux#

若要構建範例,請打開 Shell,導航至您複製範例的資料夾。然後,切換至 cpp 子資料夾並執行以下命令:

mkdir build
cd build
cmake ..
make -j$(nproc)

如果 CMake 未能找到 pylon SDK,請檢查是否已正確安裝 pylon SDK 與 pylon Supplementary Package for blaze。

如果您將軟體安裝在 /opt/pylon 以外的位置,請確保將 PYLON_ROOT 環境變數設置為您安裝 pylon 及補充套件的資料夾。

範例:

PYLON_ROOT=$HOME/pylon cmake ..

如果 CMake 未能找到 OpenCV 庫或 PCL,請確保已安裝 OpenCV 庫和 PCL 的開發套件。

如果您在構建和運行範例時遇到問題,請參閱 Troubleshooting 主題。

安裝 OpenCV Library#

Windows#

您可以從 GitHub 下載 OpenCV。

請確保下載與您將要使用的 Visual Studio 版本相容的 OpenCV 庫版本。如果沒有合適的預構建版本可用,您必須使用要用於構建應用程式的 Visual Studio 版本從源代碼構建 OpenCV。

如果 CMake 未能找到 OpenCV,請將 OpenCV_DIR 變數設置為包含 OpenCVConfig.cmake 檔案的資料夾。

範例

  1. Open the CMakeSettings.json file (CMake -> Change CMake Settings -> blazeCppSamples).
  2. Add the following to the cmakeCommandArgs list:
    -DOpenCV_DIR=\"C:\\Program Files\\OpenCV\\build\\x64\\vc16\\lib\"
  "configurations": [
    {
      "name": "x64-Debug",
      ...
      "cmakeCommandArgs": "-DOpenCV_DIR=\"C:\\Program Files\\OpenCV\\build\\x64\\vc16\\lib\"",
      ...
    },
    {
      "name": "x64-Release",
      ...
      "cmakeCommandArgs": "-DOpenCV_DIR=\"C:\\Program Files\\OpenCV\\build\\x64\\vc16\\lib\"",
      ...
    }
  ]
  1. Open the CMake Settings dialog (Project -> CMakeSettings for blazeCppSamples).
  2. Enter the following in the CMake command arguments field:
    -DOpenCV_DIR="C:\Program Files\OpenCV\build\x64\vc16\lib"
  3. Press Ctrl S to save the changes.

Before you can access the OpenCV_DIR in the CMake GUI, make sure that the Grouped check box is deselected in the CMake GUI.

cmake -DOpenCV_DIR="C:\Program Files\OpenCV\build\x64\vc16\lib" ..
將 OpenCV 新增至 PATH 環境變數#

您必須將 OpenCV bin 目錄新增至 PATH 環境變數中。

  1. 按 Win 鍵。
  2. 輸入「environment」。
  3. 按一下 Edit environment variables for your account。
  4. 按一下 Environment Variables… 按鈕。
  5. 在 User variables 區域中,選取 Path。
  6. 按一下 Edit 按鈕。
  7. 按一下 New。
  8. 輸入您的 OpenCV 安裝路徑,例如 C:\Program Files\OpenCV\build\x64\vc16\bin。
  9. 按一下 OK。

Linux#

如果 CMake 未能找到 OpenCV 庫,您必須安裝 libopencv 開發套件,或者從源代碼構建 OpenCV 庫。

在 Ubuntu 系統上,透過執行以下命令可以安裝 libopencv 開發套件:

sudo apt-get -y install libopencv-dev

當您從源代碼構建 OpenCV 庫並将其安裝到非標準位置時, OpenCV_DIR CMake 變數可用於指定 OpenCVConfig.cmake 檔案所在的位置。

範例:

cmake -DOPENCV_DIR=$HOME/OpenCV/lib ..

安裝 Point Cloud Library#

Windows#

您可以從 GitHub 下載適用於 Windows 的 PCL All-in-one Installer。

請確保下載與您即將使用的 Visual Studio 版本相容的 PCL 版本。

如果 CMake 無法找到 PCL,請將 PCL_DIR 變數設定為包含 PCLConfig.cmake 檔案中。

範例

  1. Open the CMakeSettings.json file (CMake -> Change CMake Settings -> blazeCppSamples)
  2. Add the following to the cmakeCommandArgs list:
    -DPCL_DIR=\"C:\\Program Files\\PCL 1.9.1\\cmake\"
  "configurations": [
    {
      "name": "x64-Debug",
      ...
      "cmakeCommandArgs": "-DPCL_DIR=\"C:\\Program Files\\PCL 1.9.1\\cmake\"",
      ...
    },
    {
      "name": "x64-Release",
      ...
      "cmakeCommandArgs": "-DPCL_DIR=\"C:\\Program Files\\PCL 1.9.1\\cmake\"",
      ...
    }
  ]
  1. Open the CMake Settings dialog (Project -> CMakeSettings for blazeCppSamples).
  2. Enter the following in the CMake command arguments field:
    -DPCL_DIR="C:\Program Files\PCL 1.12.1\cmake"
  3. Press Ctrl S to save the changes.
  1. Open the CMake Settings dialog (Project -> CMakeSettings for blazeCppSamples).
  2. Enter the following in the CMake command arguments field:
    -DPCL_DIR="C:\Program Files\PCL 1.14.0\cmake"
  3. Press Ctrl S to save the changes.

Before you can access the PCL_DIR in the CMake GUI, make sure that the Grouped check box is deselected in the CMake GUI.

cmake -DPCL_DIR="C:\Program Files\PCL 1.14.0\cmake" ..

使用 PCL All-in-one Installer 安裝 PCL 時,安裝程式會自動新增 PCL bin 目錄新增至 PATH 環境變數。如果您使用其他安裝方式,則必須自行新增 bin 目錄新增至 PATH 環境變數。

PCL All-in-one Installer 會將 OpenNI2.dll 安裝到 %ProgramFiles%\OpenNI2\Redist 資料夾中。執行階段需要此 DLL。請將此資料夾新增至您的 PATH 環境變數,或將 OpenNI2.dll 至 PCL 二進位檔所在的資料夾,例如 %ProgamFiles%\PCL 1.13.0\bin.

Linux#

如果 CMake 無法找到 PCL 程式庫,您必須安裝 libpcl 開發套件,或是從原始程式碼建置 PCL 程式庫。

在 Ubuntu 系統上,您可以執行下列命令來安裝 libpcl 開發套件:

sudo apt-get -y install libpcl-dev

如果您從原始程式碼建置 PCL 並将其安裝到非標準位置,則會找到 PCL_DIR CMake 變數可用於指定 PCLConfig.cmake 檔案。

範例:

cmake -DPCL_DIR=$HOME/PCL/cmake ..

注意

使用點雲庫 (PCL) 的範例可能會當機,具體取決於您系統上安裝的 PCL 和 VTK 程式庫版本。當機的原因是 PCL 用於 3D 視覺化的 VTK 程式庫中存在錯誤。
來源:https://github.com/PointCloudLibrary/pcl/issues/5237
解決方案:PCL 1.13.1 包含解決 VTK 錯誤的修正。
請更新至 PCL 1.13.1 或更高版本。如有需要,請解除安裝 Linux 發行版提供的 PCL 程式庫,並從原始程式碼建置 PCL 1.13.1 或更高版本(這些版本可以從 GitHub 取得)。

安裝 Boost Libraries#

Windows#

如果您是從原始程式碼建置點雲庫 (PCL),或者如上所述使用 All-in-one 安裝程式進行安裝,則用於建置 PCL 的 Boost 程式庫也將自動用於建置 blaze 範例。

如果沒有可用的 PCL 程式庫,但您想要建置需要 Boost 程式庫的 blaze 範例,則必須從原始程式碼建置 Boost 程式庫或進行安裝,例如使用您可以從 sourceforge.net 下載的預先建置二進位檔。請下載適合您正在使用的 Visual Studio 版本以及應用程式建置架構的安裝程式。

如果 CMake 無法偵測到已安裝的 Boost 程式庫,您必須設定 Boost_DIR CMake 變數。該變數必須指向包含 BoostConfig.cmake 檔案中。

範例

  1. Open the CMakeSettings.json file (CMake -> Change CMake Settings -> blazeCppSamples).
  2. Add the following to the cmakeCommandArgs list:
    -DBoost_DIR=\"C:\\local\\boost_1_84_0\\lib64-msvc-14.1\\cmake\\Boost-1.84.0\"
  "configurations": [
    {
      "name": "x64-Debug",
      ...
      "cmakeCommandArgs": "-DBoost_DIR=\"C:\\local\\boost_1_84_0\\lib64-msvc-14.1\\cmake\\Boost-1.84.0\"",
      ...
    },
    {
      "name": "x64-Release",
      ...
      "cmakeCommandArgs": "-DBoost_DIR=\"C:\\local\\boost_1_84_0\\lib64-msvc-14.1\\cmake\\Boost-1.84.0\"",
      ...
    }
  ]
  1. Open the CMake Settings dialog (Project -> CMakeSettings for blazeCppSamples).
  2. Enter the following in the CMake command arguments field:
    -DBoost_DIR="C:\local\boost_1_84_0\lib64-msvc-14.2\cmake\Boost-1.84.0"
  3. Press Ctrl S to save the changes.
  1. Open the CMake Settings dialog (Project -> CMakeSettings for blazeCppSamples).
  2. Enter the following in the CMake command arguments field:
    -DBoost_DIR="C:\local\boost_1_84_0\lib64-msvc-14.3\cmake\Boost-1.84.0"
  3. Press Ctrl S to save the changes.

Before you can access the Boost_DIR in the CMake GUI, make sure that the Advanced check box is selected and the Grouped check box is deselected in the CMake GUI.

cmake -DOpenCV_DIR="C:\Program Files\OpenCV\build\x64\vc16\lib" ..

Linux#

如果 CMake 無法找到 Boost 程式庫,您必須安裝 libboost 開發套件,或是從原始程式碼建置 Boost 程式庫。

在 Ubuntu 系統上,您可以執行下列命令來安裝 libboost 開發套件:

sudo apt-get -y install libboost-dev

範例清單#

  • FirstSample: 提供 blaze 相機操作導覽,並著重於如何擷取 3D 點雲資料。請參閱以下 pylon C++ 範例套件中的範例,以深入了解使用 pylon 實作擷取迴圈的不同方式:
    • Grab_Strategies
    • Grab_UsingBufferFactory
    • Grab_UsingGrabLoopThread
  • ParametrizeCamera:說明如何存取相機參數。
  • DeviceRemovalHandling:說明如何偵測與處理裝置移除。
  • GrabDepthMap:說明如何擷取並解譯以灰階影像表示 3D 資訊的深度圖。
  • ConvertPointCloud2DepthMap:如果您想要同時處理 3D 點雲與深度圖,請參閱說明如何從 3D 點雲擷取深度圖的範例。此範例亦說明如何對深度圖套用彩虹色彩對應。
  • ShowPointCloud_PCL:說明如何使用點雲庫 (PCL) 來視覺化透過 Basler blaze 相機擷取的點雲。
  • ConvertAndFilter_PCL:類似於 ShowPointCloud。說明如何對 3D 點雲套用 PCL 濾波器。
  • SavePointCloud:說明 GrabSingleImage 便利方法,以及如何將點雲儲存至 .pcd 文字檔。
  • SaveAndLoadPointCloudUsingPCL:說明如何使用 PCL 更有效率地將點雲儲存至檔案。此範例亦展示如何從檔案載入點雲。
  • FeatureDumper:列出所有相機參數及其 Property。作為如何使用 GenApi 的進階範例。
  • DistortionCorrection:說明如何停用 Distortion Correction 以使用您自己的校正資料。
  • ExtrinsicTransformation:說明如何在點雲中偵測主平面,以及如何計算外部轉換並將其傳遞至相機。
  • MultiCam/ColorAndDepth/ColorAndDepthPtp:說明如何從 Basler blaze 與 Basler GigE 彩色相機擷取影像,以及如何存取影像與深度資料。相機使用 PTP 與 Synchronous Free Run 功能進行同步。
  • MultiCam/ColorAndDepth/Calibration:說明如何校正由 Basler GigE 彩色相機和 Basler blaze 相機組成的系統。
  • MultiCam/ColorAndDepth/ColorAndDepthFusion:說明如何將來自 Basler GigE 彩色相機和 Basler blaze 的資料融合為彩色的點雲。
  • MultiCam/ColorAndDepth/RgbdCamera: 類似於 ColorAndDepthFusion,此範例說明如何將來自 Basler blaze 與 Basler GigE 彩色相機的資料融合為彩色的點雲。此範例運用 RgbdCamera 類別,可讓您結合 2D 彩色相機與 blaze,並將兩部相機介面化為單一 RGB-D 相機。這兩部結合的相機使用 PTP (IEEE1588) 與 Synchronous Free Run 功能進行同步觸發。 RgbdCamera 類別的原始程式碼位於同一資料夾中。若要在您自己的應用程式中使用 RgbdCamera 類別,請將 RgbdCamera.h 和 RgbdCamera.cpp 檔案新增至您的專案中。此外,您還必須新增來自 Multicam/MultiCamHelper 資料夾的 .h 和 .cpp 檔案。
  • MultiCam/DepthFusion/Calibration:說明如何校正由多部 Basler blaze 相機組成的系統。
  • MultiCam/DepthFusion/DepthFusion:說明如何合併深度資料,以顯示來自任意數量相機的融合點雲。
  • MultiCam/MultiChannel/MultiChannelFreeRun: 說明如何同時操作多台 blaze 相機,且彼此的光源不會互相干擾。相機於 Free Run 模式下運作。
  • MultiCam/MultiChannel/MultiChannelSwTrigger: 說明如何同時操作多台 blaze 相機,且彼此的光源不會互相干擾。相機透過軟體觸發進行觸發。
  • MultiCam/SynchronousFreeRun/SynchronousFreeRun: 說明如何使用 PTP 時鐘同步以及 Synchronous Free Run 功能,以同時操作多台 blaze 相機,且彼此的光源不會互相干擾。
  • MultiCam/MultiCamHelper: 此函式庫提供便利的類別,可輕鬆使用 PTP (IEEE1588) 同步多台相機的時鐘,並從多台相機同步擷取影像。所有使用 Synchronous Free Run 功能從多台相機擷取影像的範例都會使用此函式庫。若要將此函式庫新增至您的專案中,只需將此資料夾中的 .h 與 .cpp 檔案新增至您的專案即可。
  • Aravis/BasicSample: (僅限 Linux) 說明如何使用開源的 Aravis 函式庫來設定 blaze 相機並從中擷取資料。
  • Aravis/PointCloudSample: (僅限 Linux) 說明如何從使用 Aravis 函式庫擷取的資料計算 3D 座標 (即點雲)。此範例亦說明如何使用 OpenCV 儲存與視覺化點雲。

如何建置應用程式#

Windows#

使用 Visual Studio 方案#

Refer to the Common Settings for Building Applications with pylon section of the pylon C++ Programmer's Guide to learn how to set up a project for building applications using pylon.

Refer to the Common Settings for Building Applications with pylon section of the pylon C++ Programmer's Guide to learn how to set up a project for building applications using pylon.

使用 CMake#

pylon Supplementary Package for blaze 包含一個 Findpylon.cmake 模組,用於決定 pylon 以及 pylon Supplementary Package for blaze 的安裝位置。尋找模組會匯出 pylon::pylon CMake 目標。請將此目標做為引數傳遞給 target_link_libraries,CMake 將會處理設定包含路徑、函式庫路徑等。

一個基本的 CMakeLists.txt CMake 檔案看起來可能如下:

project (hello)

# Locate the CMake find module for pylon ...
# for Unix system. All other OS PYLON_ROOT will be empty
list(APPEND CMAKE_PREFIX_PATH $ENV{PYLON_ROOT})
# for Windows system. All other OS PYLON_DEV_DIR will be empty
list(APPEND CMAKE_PREFIX_PATH $ENV{PYLON_DEV_DIR})

find_package(pylon 7.1 REQUIRED)

add_executable(hello helloworld.cpp)
target_link_libraries(hello pylon::pylon)
project (hello)

# Locate the CMake find module for pylon ...
find_path(pylon_cmake Findpylon.cmake
    HINTS "$ENV{PYLON_DEV_DIR}/lib/cmake"
          "$ENV{ProgramFiles}/Basler/pylon 7/Development/lib/cmake"
          "$ENV{ProgramFiles}/Basler/pylon 6/Development/lib/cmake"
)
# ... and extend the CMake module path accordingly.
list(APPEND CMAKE_MODULE_PATH ${pylon_cmake})
# Locate pylon.
find_package(pylon 6.2 REQUIRED)

add_executable(hello helloworld.cpp)
target_link_libraries(hello pylon::pylon)

Linux#

使用 CMake#

project (hello)

# Locate the CMake find module for pylon ...
# for Unix system. All other OS PYLON_ROOT will be empty
list(APPEND CMAKE_PREFIX_PATH $ENV{PYLON_ROOT})
# for Windows system. All other OS PYLON_DEV_DIR will be empty
list(APPEND CMAKE_PREFIX_PATH $ENV{PYLON_DEV_DIR})

find_package(pylon 7.1 REQUIRED)

add_executable(hello helloworld.cpp)
target_link_libraries(hello pylon::pylon)
project (hello)

# Locate the CMake find module for pylon ...
find_path(pylon_cmake Findpylon.cmake
    HINTS "/opt/pylon/lib/cmake"
)
# ... and extend the CMake module path accordingly.
list(APPEND CMAKE_MODULE_PATH ${pylon_cmake})
# Locate pylon.
find_package(pylon 6.2 REQUIRED)

add_executable(hello helloworld.cpp)
target_link_libraries(hello pylon::pylon)

使用 Make 檔案#

請參閱 Common Settings for Building Applications with pylon 一節中的 pylon C++ Programmer's Guide,以了解如何調整編譯器與連結器設定,以建構包含 pylon 的應用程式。

針對 blaze 相機的 Instant Camera 類別#

pylon 提供不同類型的類別來存取相機裝置。除了低階的 IPylon 裝置外,還有所謂的 Instant Camera 類別,可為相機提供便利的高階 API。

影像 Pylon::CInstantCamera 類別提供對所有 Basler 相機 (包含 blaze 相機) 的通用存取。

影像 Pylon::CBaslerUniversalInstantCamera 類別透過參數存取器物件擴充了通用的 Pylon::CInstantCamera 類別,讓您能夠使用 IntelliSense/代碼自動完成功能輕鬆設定與取得相機參數。

影像 Pylon::CBaslerUniversalInstantCamera 類別並未提供每個 blaze 相機功能的參數存取器。因此,pylon Supplementary Package for blaze 包含了 Pylon::CBlazeInstantCamera 類別。Basler 建議改為將該類別與 Basler blaze 相機搭配使用。

如果您選擇 CBaslerUniversalInstantCamera 類別而非 CBlazeInstantCamera 類別,您仍然可以設定與取得 blaze 相機所提供的所有相機參數。如果沒有 CBaslerUniversalInstantCamera 類別所提供的存取器物件,請使用所謂的 通用 Property 存取 用於透過名稱存取 Property,詳見 通用 Property 存取 部分,位於 pylon C++ Programmer's Guide.

範例:

using namespace Pylon;
GenApi::INodeMap& nodemap = camera.GetNodeMap();
CIntegerParameter filterStrength(nodemap, "FilterStrength" );
std::cout << "Filter strength: " << filterStrength.GetValue() << std::endl;

開啟並存取blaze相機#

建立並開啟 blaze 相機物件需要三個步驟:

  1. 為您要存取的相機建立相機物件。
    通常,您應該建立 Pylon::CBlazeInstantCamera 類別的執行個體。
  2. 註冊套用預設組態的 blaze 專屬 Pylon::CBlazeDefaultConfiguration 組態事件處理常式。
    請參閱 註冊相機組態處理常式 章節以取得關於 blaze 組態事件處理常式類別的更多詳細資訊。
  3. 在您的應用程式中呼叫 Open() 方法來建立與相機裝置的連線。

以下範例說明這三個步驟:

#include <pylon/PylonIncludes.h>
using namespace Pylon;

// ....

// Before using any pylon methods, the pylon runtime must be initialized.
PylonInitialize();

try {
  // 1: Create a camera object for the first available blaze camera.
  CBlazeInstantCamera camera(CTlFactory::GetInstance().CreateFirstDevice(
      CDeviceInfo().SetDeviceClass(BaslerGenTlBlazeDeviceClass))
  );

  // 2. Register the default configuration.
  camera.RegisterConfiguration(
    new CBlazeDefaultConfiguration,
    RegistrationMode_ReplaceAll,
    Cleanup_Delete);

  // 3. Open the camera, i.e., establish a connection to the camera device.
  camera.Open();

  // Use the camera.
  std::cout << "Connected to camera "
    << camera.GetDeviceInfo().GetFriendlyName() << std::endl;
  // .....

  // Close the connection.
  camera.Close();
} catch (const GenICam::GenericException& e) {
  std::cerr << "Exception occurred: " << std::endl
    << e.GetDescription() << std::endl;
}

// Releases all pylon resources.
PylonTerminate();

發生錯誤時,將會擲回繼承自 GenICam::GenericException 的例外狀況。

典型錯誤狀況:

  • 找不到 blaze 相機: CreateFirstDevice() 函式會擲回例外狀況。
  • 無法開啟相機(例如因為已被其他應用程式(如 blaze Viewer)開啟): Open() 方法會擲回例外狀況。

以下小節提供關於如何建立和開啟相機物件的更詳細資訊。

為第一個可用的blaze相機建立相機物件#

請使用 Pylon::CTlFactory::CreateFristDevice() 用於為第一個可用相機建立相機物件的方法。您應該一律指定 blaze 相機的 pylon 裝置類別識別碼,以防止 CreateFirstDevice() 為連接到您的系統或可透過網路存取的其他類型相機建立相機類別:

CBlazeInstantCamera camera(CTlFactory::GetInstance().CreateFirstDevice(
    CDeviceInfo().SetDeviceClass(BaslerGenTlBlazeDeviceClass)));
);

如果找不到 blaze 相機,請檢查相機和網路介面卡的 IP 組態設定。請參閱網路組態主題以取得關於設定網路的更多資訊。

為特定的blaze相機建立相機物件#

pylon C++ Programmer's Guide 之進階主題中的建立特定相機章節提供了關於選擇特定相機的資訊。

如果您想要開啟特定的 blaze 相機(例如透過指定其序號),除了將 blaze 相機的 pylon 裝置類別識別碼傳遞至 CreateFirstDevice()之外,您還可以指定其他 Property。

以下程式碼片段說明如何透過序號開啟 blaze 相機。

CBlazeInstantCamera camera(CTlFactory::GetInstance().CreateFirstDevice(
  CDeviceInfo()
  .SetDeviceClass(BaslerGenTlBlazeDeviceClass)
  .SetSerialNumber("23298299")
));

若要透過使用者定義名稱開啟 blaze 相機,請使用下列程式碼行:

CBlazeInstantCamera camera(CTlFactory::GetInstance().CreateFirstDevice(
  CDeviceInfo()
  .SetDeviceClass(BaslerGenTlBlazeDeviceClass)
  .SetUserDefinedName("MyCamera")));

User-Defined Names

您可以使用 DeviceUserID 參數將使用者定義名稱指派給相機。您可以在 blaze Viewer、pylon IP Configurator 或 pylon API 中執行此操作:

camera.DeviceUserID.SetValue("MyCamera");

透過 IP 地址建立裝置

目前,您無法使用 CreateFirstDevice() 函式指定相機 IP 位址。原因在於目前 Pylon::CDeviceInfo() 類別未包含任何關於相機 IP 位址的資訊。

若要建立並開啟具有特定 IP 位址的相機,您必須先列舉所有相機、疊代傳回的清單,並在查詢 IP 位址和其他網路相關資訊之前開啟每台相機。此程序顯示於 Enumerate blaze Cameras 一節中。

如果找不到所需的 blaze 相機,請檢查您是否使用了正確的 Property 值,並檢查相機與網路介面卡的 IP 設定。如需有關設定網路的詳細資訊,請參閱網路組態主題。

列舉 blaze 相機#

以下程式碼片段說明如何擷取所有連接之 blaze 相機的清單。對於清單中的每個元素,都會開啟相機並列印部分相機參數值。

#include <pylon/PylonIncludes.h>
#include <ostream>
using namespace Pylon;

// ....

// Before using any pylon methods, the pylon runtime must be initialized.
PylonInitialize();

// ....

// Enumerate all blaze cameras.
CTlFactory& TlFactory = CTlFactory::GetInstance();
DeviceInfoList_t lstDevices;
DeviceInfoList_t filter;
filter.push_back(CDeviceInfo().SetDeviceClass(BaslerGenTlBlazeDeviceClass));
TlFactory.EnumerateDevices(lstDevices, filter);
if (!lstDevices.empty()) {
    DeviceInfoList_t::const_iterator it;
    for (it = lstDevices.begin(); it != lstDevices.end(); ++it) {
        std::cout << it->GetFullName();

    // Open camera, i.e., establish a connection to the camera device.
    CBlazeInstantCamera camera(CTlFactory::GetInstance().CreateDevice(*it));
    camera.RegisterConfiguration(
      new CBlazeDefaultConfiguration,
      RegistrationMode_ReplaceAll, Cleanup_Delete);
    camera.Open();

    // Print out some information.
    std::cout << "Connected to camera "
      << camera.GetDeviceInfo().GetFriendlyName() << std::endl;
    std::cout << "IP Address: "
      << camera.GevCurrentIPAddress.GetValue() << std::endl;
    std::cout << "User-defined name: "
      << camera.DeviceUserID.GetValue() << std::endl;
    std::cout << "Serial Number: "
      << camera.DeviceSerialNumber.GetValue() << std::endl;
}  // The connection will be closed automatically when leaving the scope here.
else {
    std::cerr << "No devices found!" << std::endl;
}

註冊相機組態處理常式#

pylon Instant Camera 類別允許您註冊組態事件處理常式物件,可用於在特定事件發生時套用相機設定,例如當 Open() 方法被呼叫時。

pylon Supplementary Package for blaze 包含 Pylon::CBlazeDefaultConfiguration 類別。Basler 建議務必針對您建立的每個 CBlazeInstantCamera 類別實例註冊此組態。

camera.RegisterConfiguration(
      new CBlazeDefaultConfiguration,
      RegistrationMode_ReplaceAll, Cleanup_Delete);

影像 CBlazeDefaultConfiguration::OnOpened() 方法將資料串流設定為包含深度、強度和信賴度資訊。深度資訊以點雲形式傳送。點雲包含每個感測器像素的 3D 座標。 CBlazeDefaultConfiguration::OnOpened() 方法也會將相機設為所謂的 free run 模式。在 free run 模式下,相機在啟動擷取後會持續串流資料,而不需要軟體或硬體觸發。

如果已註冊預設組態, CBlazeDefaultConfiguration::OnOpened() 方法會由 CBlazeInstantCamera::Open().

影像 CBlazeDefaultConfiguration 自動呼叫。類別是一個僅含標頭檔的類別。您可以透過開啟位於 pylon SDK includes 資料夾中的 BlazeDefaultConfiguration.h 檔案來檢視程式碼:

  • Windows: %Program Files%\pylon\Development\include\pylon
  • Linux: /opt/pylon/include/pylon

您可以註冊多個組態事件處理常式類別。

以下範例說明如何註冊一個套用額外設定的組態事件處理常式:

class MyConfigurationHandler : public CBlazeConfigurationEventHandler
{
public:
    // Sets exposure time to minimum possible value.
    void OnOpened(CBlazeInstantCamera& camera) override
    {
        camera.ExposureTime.SetToMinimum();
    }
};

// ....

// Register the default configuration first.
camera.RegisterConfiguration(
      new CBlazeDefaultConfiguration,
      RegistrationMode_ReplaceAll, Cleanup_Delete);

// Then, register additional configuration event handlers.
camera.RegisterConfiguration(
      new MyConfigurationHandler,
      RegistrationMode_Append, Cleanup_Delete);

// ....

camera.Open(); // Configurations will be applied.

如需有關 pylon 相機事件處理常式類別的詳細資訊,請參閱 pylon C++ Programmer's Guide 的 Instant Camera Event Handler Basics 一節。

您不需要透過提供組態事件處理常式來套用所需的設定。相反地,您可以在呼叫 CBlazeInstantCamera::Open() 方法來建立與相機的連線。

之後隨時設定您想要變更的參數。

連接至相機#

建立相機物件並註冊組態事件處理常式後,透過呼叫 CBlazeInstantCamera::Open() 方法來建立與相機的連線。

連線會保持作用中,直到呼叫 CBlazeInstantCamera::Close() 方法被呼叫時。以下項目的解構函式 CBlazeInstantCamera 會自動呼叫 Close() (如果尚未明確呼叫)。

如果相機未定期收到來自相機的心跳要求,相機將會關閉連線。如果應用程式當機或遭到偵錯工具中斷,就會發生遺漏心跳要求的情況。如需更多詳細資訊,請參閱Debugging Applications and Controlling the GigE Vision Heartbeat章節。

存取Property#

請參閱 pylon C++ Programmer's Guide 的 Accessing Parameters 一節,以熟悉如何使用 pylon API 存取相機參數。

pylon C++ 範例 Parametrize_NativeParameterAccess 與 Parametrize_GenericParameterAccess 說明了使用 pylon 存取相機參數的典型方法。

以下程式碼範例說明如何使用 CBlazeInstantCamera 類別的執行個體。

// Include files to use the pylon API
#include <pylon/PylonIncludes.h>
#include <pylon/BlazeInstantCamera.h>

// Namespaces for using the pylon API and the blaze camera parameters
using namespace Pylon;
using namespace BlazeCameraParams_Params;

// ...

// Set the operating mode of the camera. The choice you make here
// affects the working range of the camera, i.e., the Minimum Working
// Range and Maximum Working Range parameters.
OperatingModeEnums oldOperatingMode = camera.OperatingMode.GetValue();
camera.OperatingMode.SetValue(OperatingMode_LongRange);

// Exposure time of the camera. If the operating mode is changed, the
// exposure time is set to the recommended default value.
camera.ExposureTime.SetValue(750); // us

// Enable and configure image filtering.

// The spatial noise filter uses the values of neighboring pixels to
// filter out noise in an image.
camera.SpatialFilter.SetValue(true);

// The temporal noise filter uses the values of the same pixel at
// different points in time to filter out noise in an image.
camera.TemporalFilter.SetValue(true);
camera.TemporalFilterStrength.SetValue(220);

// The outlier removal removes pixels that differ significantly from
// their local environment.
camera.OutlierRemoval.SetValue(true);

// Some properties have restrictions.
// We use API functions that automatically perform value corrections.
// Alternatively, you can use GetInc() / GetMin() / GetMax() to make sure you
// set a valid value.
camera.ConfidenceThreshold.SetValue(321, IntegerValueCorrection_Nearest);

// Not all functions are available in older cameras.
// Therefore, we must use "Try" functions that only perform the action
// when parameters are writable. Otherwise, we would get an exception.
camera.MultiCameraChannel.TrySetValue(1);

std::cout << "Operating Mode           : "
    << camera.OperatingMode.GetValue() << std::endl;
std::cout << "Exposure Time            : "
    << camera.ExposureTime.GetValue() << std::endl;
std::cout << "Spatial Filter           : "
    << camera.SpatialFilter.GetValue() << std::endl;
std::cout << "Temporal Filter          : "
    << camera.TemporalFilter.GetValue() << std::endl;
std::cout << "Temporal Filter Strength : "
    << camera.TemporalFilterStrength.GetValue() << std::endl;
std::cout << "Outlier Removal          : "
    << camera.OutlierRemoval.GetValue() << std::endl;
std::cout << "Confidence Threshold     : "
    << camera.ConfidenceThreshold.GetValue() << std::endl;
if (camera.MultiCameraChannel.IsReadable())
    std::cout << "Multi-Camera Channel : "
    << camera.MultiCameraChannel.GetValue() << std::endl;

// Restore the old operating mode.
camera.OperatingMode.SetValue(oldOperatingMode);

// Close the camera.
camera.Close();

設定與取得經常使用的 blaze 專屬相機參數。blaze Viewer 提供一個 Documentation 窗格。當您在 Features 窗格中選取相機參數時,Documentation 窗格會顯示所選參數的相關資訊,以及說明如何取得與設定該相機參數值的 C++ 與 C# 程式碼片段。

擷取資料#

請參閱 pylon C++ Programmer's Guide 的 Grabbing Images 一節,以熟悉如何使用 pylon API 擷取資料。

pylon 會將擷取的影像表示為稱為 GrabResults 的資料結構。由 2D 相機擷取的 GrabResults 包含單一灰階或彩色影像。

由 blaze 相機擷取的 GrabResults 包含多個元件。預設情況下,每個 GrabResult 都會儲存強度影像、信心圖和深度資訊。

根據針對 Range component 設定的 Pixel Format,深度資料可以表示為 2D 深度圖或 3D 點雲。根據預設,深度資料會表示為點雲。

若要啟用深度圖,請將 Range component 的 Pixel Format 設定為 PixelFormat_Coord3D_16C:

// Enable depth maps by enabling the Range component and setting the
// appropriate pixel format.
camera.ComponentSelector.SetValue(ComponentSelector_Range);
camera.ComponentEnable.SetValue(true);
camera.PixelFormat.SetValue(PixelFormat_Coord3D_C16);

若要啟用點雲,請將 Range component 的 Pixel Format 設定為 PixelFormat_Coord3D_ABC32f:

// Enable point clouds by enabling the Range component and setting the
// appropriate pixel format.
camera.ComponentSelector.SetValue(ComponentSelector_Range);
camera.ComponentEnable.SetValue(true);
camera.PixelFormat.SetValue(PixelFormat_Coord3D_ABC32f);

如需更多詳細資訊,請參閱 Component Selector 與 Pixel Format 主題。

資訊

無法讓相機同時傳送點雲和深度圖形式的深度資訊。

Processing Measurement Results 主題說明了如何從深度圖計算點雲。

此轉換也顯示在針對 blaze 相機的 GrabDepthMap C++ programming sample 中。

針對 blaze 相機的 ConvertPointCloud2DepthMap C++ programming sample 中展示了如何從點雲擷取深度圖。

擷取迴圈#

pylon 支援用於設定擷取迴圈的不同方法,並提供用於處理 Memory 緩衝區的不同策略。

如需更多詳細資訊,請參閱 pylon C++ Programmer's Guide 的 Grabbing Images 一節。

以下程式碼片段說明了典型的擷取迴圈:

#include <pylon/PylonIncludes.h>
#include <pylon/BlazeInstantCamera.h>

using namespace Pylon;
using namespace BlazeCameraParams_Params;

// ....
PylonInitialize();

CBlazeInstantCamera camera(CTlFactory::GetInstance().CreateFirstDevice(
  CDeviceInfo().SetDeviceClass(BaslerGenTlBlazeDeviceClass)));
camera.RegisterConfiguration(
  new CBlazeDefaultConfiguration, RegistrationMode_ReplaceAll, Cleanup_Delete);
camera.Open();

size_t nBuffersGrabbed= 0;

// This smart pointer will receive the grab result data.
CGrabResultPtr ptrGrabResult;

camera.StartGrabbing();

while (camera.IsGrabbing() && nBuffersGrabbed < 10) {
  // Wait for an image and then retrieve it. A timeout of 1000 ms is used.
  camera.RetrieveResult(1000, ptrGrabResult, TimeoutHandling_ThrowException);

  // Data grabbed successfully?
  if (ptrGrabResult->GrabSucceeded()) {
      nBuffersGrabbed++;
      // Access the data.
      // ....
  } else {
    // Error handling
    std::cerr << "Grab error occurred: " << ptrGrabResult->GetErrorDescription() << std::endl;
  }
}
// Clean-up
camera.StopGrabbing();
camera.Close();

存取元件#

若要存取 GrabResult 的個別元件,您可以使用 Pylon::CPylonDataContainer 和 Pylon::CPylonDataComponent 類別。容器可以容納一個或多個元件。您可以使用容器來查詢元件數量並擷取特定元件。容器中的每個元件都包含實際資料(例如深度值)以及其中繼資料。

請使用 Pylon::CGrabResultData::GetDataContainer() 方法以存取 GrabResult 的 CPylonDataContainer。使用 Pylon::CPylonDataContainer::GetDataComponent() 方法透過指定元件的索引來存取元件。

如需關於 pylon 如何提供對包含多個 component 的 GrabResults 之存取的更多資訊,請參閱 pylon C++ Programmer's Guide 的 Advanced Topics 主題中的 Multi-Component Grab Results 一節。

範例:

#pragma pack(push, 1)
struct Point
{
    float x;
    float y;
    float z;
};
#pragma pack(pop)

// ...

// By registering the CBlazeDefaultConfiguration, depth, intensity, and confidence data will be delivered.
// Depth data is represented as point clouds.
camera.RegisterConfiguration(new CBlazeDefaultConfiguration, RegistrationMode_ReplaceAll, Cleanup_Delete);
camera.Open();

//....

if (ptrGrabResult->GrabSucceeded())
{
  // Get access to the container.
  auto container = ptrGrabResult->GetDataContainer();

  // Access the container's components.
  // Iterate through all components in the container.
  for (size_t i = 0; i < container.GetDataComponentCount(); ++i)
  {
      // Get one component from the container.
      const Pylon::CPylonDataComponent component = container.GetDataComponent(i);
      if ( !component.IsValid() )
          continue;

      // Is this the intensity component?
      if ( component.GetComponentType() == Pylon::ComponentType_Intensity )
      {
          const Pylon::EPixelType pixelType = component.GetPixelType();

          // Get a pointer to the pixel data.
          const void* pPixels = component.GetData();

          // Process intensity values here (pixel data).
          // [...]
      }
  }

  auto rangeComponent = container.GetDataComponent(0);
  auto intensityComponent = container.GetDataComponent(1);
  auto confidenceComponent = container.GetDataComponent(2);

  // Retrieve the 3D coordinates corresponding to the center pixel.
  const auto width = rangeComponent.GetWidth();
  const auto height = rangeComponent.GetHeight();
  const uint32_t u = (int)(0.5 * width);
  const uint32_t v = (int)(0.5 * height);
  auto pPoint =
    reinterpret_cast<const Point*>(rangeComponent.GetData()) + u + v * width;
  uint16_t* pIntensity =
    (uint16_t*)intensityComponent.GetData() +  v * width + u;
  uint16_t* pConfidence
    = (uint16_t*)confidenceComponent.GetData() + v * width + u;
  if (pPoint->z != 0)
      std::cout << "x=" << pPoint->x
        << " y=" << pPoint->y
        << " z=" << pPoint->z << "\n";
  else
      std::cout << "x=   n/a y=   n/a z=   n/a\n";
  std::cout << " intensity=" << *pIntensity
            << " confidence=" << *pConfidence << "\n";
}
else
{
    // Error handling
    std::cerr << "Grab error occurred: " << ptrGrabResult->GetErrorDescription() << std::endl;
}

使用 ComponentSelector 和 ComponentEnable 相機參數,您可以啟用/停用個別 component。對於 blaze 相機,容器中 component 的順序一律如下:

  • Range
  • Intensity
  • Confidence

例如,如果啟用了 Range 與 Confidence component,且停用了 Intensity component,則 container.GetDataComponent(0) 將會擷取 Range component,且 container.GetDataComponent(1) 將會傳回 Confidence component。嘗試存取 container.GetDataComponent(2) 將會導致錯誤,因為停用 Intensity component 後,容器中只有兩個 component。

如果應用程式中處理擷取結果的部分事先不知道預期會有哪些 component,您應該選擇更通用的方式來存取 component,即走訪容器並使用 CPylonDataComponent::GetComponentType() 方法來建立與相機的連線。

範例:

camera.RetrieveResult(1000, ptrGrabResult, TimeoutHandling_ThrowException);
// Data grabbed successfully?
if (ptrGrabResult->GrabSucceeded()) {
  // Access the data.
  auto container = ptrGrabResult->GetDataContainer();

  CPylonDataComponent rangeComponent;
  CPylonDataComponent intensityComponent;
  CPylonDataComponent confidenceComponent;

  // Iterate through all components in the container.
  for (size_t i = 0; i < container.GetDataComponentCount(); ++i) {
      const Pylon::CPylonDataComponent component = container.GetDataComponent(i);
      if (!component.IsValid())
          continue;
      switch (component.GetComponentType())
      {
      case ComponentType_Intensity:
          intensityComponent = component;
          break;
      case ComponentType_Confidence:
          confidenceComponent = component;
          break;
      case ComponentType_Range:
          rangeComponent = component;
          break;
      }
  }
  if (rangeComponent.IsValid()) {
    const auto width = rangeComponent.GetWidth();
    const auto height = rangeComponent.GetHeight();
    // Process depth data.
  }
  if (intensityComponent.IsValid()) {
    // Process intensity image.
  }
  if (confidenceComponent.IsValid())
  {
    // Process confidence data.
  }
}

解讀深度資料#

Processing Measurement Results 主題提供有關儲存在 Range component 中的深度資料格式之資訊。

偵錯應用程式與控制GigE Vision心跳訊號#

像 blaze 相機這樣的 GigE Vision 相機要求應用程式定期存取相機,以便相機檢查控制相機的應用程式是否仍在執行。因此,傳輸層會定期向相機發送網路請求 (心跳)。如果相機在相機的心跳逾時設定所指定的期間內沒有收到這些心跳,它會認為連線已中斷並關閉連線,亦即它將不再接受來自應用程式的任何命令。心跳逾時的預設值為 3000 ms。

當您在偵錯應用程式並遇到中斷點時,偵錯工具會暫停所有執行緒,包括發送心跳的執行緒。為了防止相機在應用程式暫停或對程式碼進行單步執行時關閉連線,傳輸層會自動增加心跳逾時時間 (如果您使用的是 pylon 7.1 或更新版本,則為 1 小時;否則為 5 分鐘)。如果您使用的是 pylon 7.1 或更新版本,當應用程式終止或當機時,與相機的連線將自動關閉。

使用 pylon 7.0 或更舊版本時的重新連線問題

如果應用程式在正常關閉與相機的連線之前終止或當機,相機會保持連線開啟,直到心跳逾時(heartbeat timeout)到期為止。在心跳逾時到期之前,相機會拒絕任何進一步的連線嘗試。當重新啟動您的應用程式或啟動另一個要求存取相機的應用程式時,您將收到一則指出裝置目前正在使用的錯誤。

如果您使用偵錯工具停止應用程式,或者如果您的應用程式非預期地終止,通常會發生這種情況。若要再次開啟相機,您必須等待逾時經過,或者暫時將相機從網路中斷連線。

為了因應這種情況,當應用程式在偵錯工具的控制下執行時,您可以透過將名為 GEV_HEARTBEAT_TIMEOUT 的環境變數設定為所需的毫秒逾時時間,來覆寫心跳逾時的自動調整。或者,您可以使用 pylon API 在應用程式中設定心跳逾時,如 DeviceRemovalHandling sample program。