SDK 示例 ================================= 本章将介绍一些 DaoAI AOI 3D Camera SDK 的常用功能示例代码,以帮助您更好地使用。 .. contents:: :local: 前提条件 ----------- - 安装DaoAI AOI 软件 - 遵循环境配置中的步骤,确保环境正确配置 引入库 -------- 在示例中,我们使用了以下几个头文件,其中aoi_ad3dcamera 开头的是用于引入DaoAI AOI 3D Camera SDK的库。 .. code-block:: C++ #include #include #include #include #include #include #include #include #include #include #include #include #include 连接相机 -------------- 使用 DaoAI AOI 3D Camera SDK 连接到指定类型相机。 创建相机对象 camera,并尝试连接 DaoAI::CameraMode::AD类型设备。 相机类型CameraMode分为: - AS: 单目相机,支持型号AS470/AS080 - AD: 双目相机,支持型号AD470/AD080 - AQ: 高精度相机,支持型号AQ060 如果连接失败,会捕获并输出错误信息,并终止程序返回 -1。 以下是代码示例: .. tabs:: .. group-tab:: C++ .. code-block:: C++ std::shared_ptr camera = nullptr; try { camera = std::make_shared(); auto model = DaoAI::CameraMode::AD; camera->connect(model); std::cout << "Connected to camera " << model << std::endl; // we can check the camera is connected or not if (!camera->connected()) { std::cerr << "Camera is not connected" << std::endl; return -1; } } catch (const std::exception& e) { std::cerr << "Failed to connect camera. Cause: " << e.what() << std::endl; return -1; } .. group-tab:: C# .. code-block:: c# 预览 ------------------ 检查相机当前的视野,并调整帧配置以获得理想的图像。 首先,定义了一个 DaoAI::Settings3D::FrameConfig 对象 frame_config,用于设置帧配置参数,其中包括: - 曝光补偿(exposure_stop):设置为 -1 - 亮度(brightness):设置为 3 - 增益(gain):设置为 0 接着,调用 camera->preview(frame_config) 方法,获取相机在当前配置下的预览图像,并将结果存储在 preview_images 向量中。 然后,通过循环遍历 preview_images 向量,将每个图像保存为 PNG 文件。文件名格式为 "ad_3d_preview_" + std::to_string(i) + ".png",其中 i 表示图像的索引。 以下是代码示例: .. tabs:: .. group-tab:: C++ .. code-block:: C++ try { DaoAI::Settings3D::FrameConfig frame_config(-1, 3.0, 0.0); auto preview_images = camera->preview(frame_config); for (size_t i = 0; i < preview_images.size(); i++) { std::filesystem::path frame_path = std::filesystem::current_path() / ("ad_3d_preview" + std::to_string(i) + ".png"); DaoAISample::saveImage(preview_images[i], frame_path); } } catch (const std::exception& e) { std::cerr << "preview Error: " << e.what() << std::endl; std::cout << "Program execution finished, press any key to exit..." << std::endl; std::cin.get(); return -1; } .. group-tab:: C# .. code-block:: c# 2D 拍照 ------------------ 使用相机(或者触发光源)拍照,并调整采集配置以获得理想的图像。 首先,定义了一个 DaoAI::Settings2D 对象 settings_2d,用于设置配置参数,其中包括: - 相机触发模式(trigger_mode):设置为 DaoAI::Settings2D::TriggerMode::Software - 曝光时间(exposure_time):设置为 std::chrono::milliseconds(600) - 增益(gain):设置为 0 接着,调用 camera->capture2D(settings_2d) 方法,获取相机在当前配置下的2D帧数据frame2d,其中包含获取图像数据image()、获取宽高等方法。 然后,通过frame2d.image()获取图像数据,并将图像保存为 PNG 文件。文件名格式为 "ad_2d_image.png"。 以下是代码示例: .. tabs:: .. group-tab:: C++ .. code-block:: C++ try { DaoAI::Settings2D settings_2d(DaoAI::Settings2D::TriggerMode::Software, std::chrono::milliseconds(600), 0); auto frame2d = camera->capture2D(settings_2d); std::filesystem::path frame_path = std::filesystem::current_path() / "ad_2d_image.png"; DaoAISample::saveImage(frame2d.image(), frame_path); } catch (const std::exception& e) { std::cerr << "capture2D Error: " << e.what() << std::endl; std::cout << "Program execution finished, press any key to exit..." << std::endl; std::cin.get(); return -1; } .. group-tab:: C# .. code-block:: c# 3D 拍照 ------------------ 使用相机进行3D拍照,请根据需要调整对应过滤器以获得理想的点云。 首先,定义了一个 DaoAI::Settings3D 对象 settings_3d,不同型号相机支持采集帧数不同,设置失败后会抛出异常,以下是一帧参数定义包括: - 曝光档(exposure_stop):设置为 -1 - 亮度(brightness):设置为 3.0 - 增益(gain):设置为 0.0 设置帧数组到DaoAI::Settings3D对象中 settings_3d.setFrameConfigs(frame_configs); 接着,调用 camera->capture3D(settings_3d) 方法,进行3D采集,采集完成后会返回一个 DaoAI::Frame 对象 frame3d, 可以调用frame3d.getPointCloud()异步获取点云数据。 以下是代码示例: .. tabs:: .. group-tab:: C++ .. code-block:: C++ try { DaoAI::Settings3D settings_3d; DaoAI::Settings3D::FrameConfig frame_config(/*exposure_stop*/-1, /*brightness*/3.0, 0.0); std::vector frame_configs; frame_configs.push_back(frame_config); settings_3d.setFrameConfigs(frame_configs); // set filters //settings_3d.setFilter(DaoAI::Settings3D::FillHole(1.0f, 1.0f)); //settings_3d.setFilter(DaoAI::Settings3D::ContrastDistortion(DaoAI::Settings3D::ContrastDistortion::Treatment::Off)); //settings_3d.setFilter(DaoAI::Settings3D::Median(false)); //settings_3d.setFilter(DaoAI::Settings3D::FaceNormal(false)); //settings_3d.setFilter(DaoAI::Settings3D::Smooth(false)); //settings_3d.setFilter(DaoAI::Settings3D::PhaseQuality(false)); //settings_3d.setFilter(DaoAI::Settings3D::Intensity(3.0f)); //settings_3d.setFilter(DaoAI::Settings3D::Outlier(1.0f)); //settings_3d.setFilter(DaoAI::Settings3D::Gaussian(40)); //settings_3d.setFilter(DaoAI::Settings3D::Cluster(5.0f, 2.0f)); auto frame3d = camera->capture3D(settings_3d); DaoAI::PointCloud point_cloud = frame3d.getPointCloud(); std::cout << "Pointcloud dimension -- #points: " << point_cloud.getSize() << ", width: " << point_cloud.getWidth() << ", height: " << point_cloud.getHeight() << std::endl; } catch (const std::exception& e) { std::cerr << "capture3D Error: " << e.what() << std::endl; std::cout << "Program execution finished, press any key to exit..." << std::endl; std::cin.get(); return -1; } .. group-tab:: C# .. code-block:: c# 点云保存及加载 ------------------ 点云保存支持PLY、PCD、BGRD格式,且支持PLY、PCD的二进制格式保存。 点云加载暂时只支持BGRD格式,可以通过DaoAI::PointCloud::load方法加载到点云对象。 BGRD格式是一种自定义的二进制格式,它极大地减少了点云数据的存储空间,同时保持了数据的完整性。 以下表格展示了各型号相机支持格式: .. list-table:: 相机型号支持格式 :header-rows: 1 * - 型号 - PLY / binary PLY save - PCD / binary PCD save - BGRD save - BGRD load * - AS470 / AS080 - 是 - 是 - 是 - 是 * - AD470 / AD080 - 是 - 是 - 是 - 是 * - AQ060 - 是 - 是 - 否 - 否 通过上面获取的frame3d对象参数保存及加载点云,以下是代码示例: .. tabs:: .. group-tab:: C++ .. code-block:: C++ // Save ply text and binary format file void savePly(DaoAI::Frame& frame) { try { auto start = std::chrono::high_resolution_clock::now(); std::string filename = "ad_3d_pointcloud.ply"; std::filesystem::path frame_path = std::filesystem::current_path() / filename; std::cout << "Saving ply " << frame_path.string() << std::endl; frame.save(frame_path, false); auto end = std::chrono::high_resolution_clock::now(); std::cout << "Save ply time: " << std::chrono::duration_cast(end - start).count() << " ms" << std::endl; filename = "ad_3d_pointcloud-binary.ply"; std::cout << "Saving binary ply" << frame_path.string() << std::endl; start = std::chrono::high_resolution_clock::now(); frame.save(filename); end = std::chrono::high_resolution_clock::now(); std::cout << "Save binary ply time: " << std::chrono::duration_cast(end - start).count() << " ms" << std::endl; } catch (const std::exception& e) { std::cerr << "Error saving ply: " << e.what() << std::endl; } } // Save pcd text and binary format file void savePcd(DaoAI::Frame& frame) { try { auto start = std::chrono::high_resolution_clock::now(); std::string filename = "ad_3d_pointcloud.pcd"; std::filesystem::path frame_path = std::filesystem::current_path() / filename; std::cout << "Saving pcd " << frame_path.string() << std::endl; frame.save(filename, false); auto end = std::chrono::high_resolution_clock::now(); std::cout << "Save pcd time: " << std::chrono::duration_cast(end - start).count() << " ms" << std::endl; filename = "ad_3d_pointcloud-binary.pcd"; std::cout << "Saving binary pcd" << filename << std::endl; start = std::chrono::high_resolution_clock::now(); frame.save(filename); end = std::chrono::high_resolution_clock::now(); std::cout << "Save binary pcd time: " << std::chrono::duration_cast(end - start).count() << " ms" << std::endl; } catch (const std::exception&) { std::cerr << "Error saving pcd" << std::endl; } } // load bgrd format file void loadBgrd(const std::string& filename, const std::string& to_filename_ply) { std::cout << "Loading frame " << filename << std::endl; DaoAI::Frame frame_bgrd; frame_bgrd.load(filename); std::cout << "Frame loaded" << std::endl; try { std::cout << "Saving to ply " << to_filename_ply << std::endl; frame_bgrd.save(to_filename_ply, false); std::cout << "Frame Saving to ply Ok" << std::endl; } catch (const std::exception& e) { std::cerr << "Error saving ply from bgrd: " << e.what() << std::endl; } } // Save bgrd format file and load, then save to ply, for test void saveBgrd(DaoAI::Frame& frame) { try { auto start = std::chrono::high_resolution_clock::now(); std::string filename = "ad_3d_pointcloud.bgrd"; std::filesystem::path frame_path = std::filesystem::current_path() / filename; std::cout << "Saving bgrd " << frame_path.string() << std::endl; frame.save(frame_path, false); auto end = std::chrono::high_resolution_clock::now(); std::cout << "Save bgrd time: " << std::chrono::duration_cast(end - start).count() << " ms" << std::endl; } catch (const std::exception& e) { std::cerr << "Error saving bgrd: " << e.what() << std::endl; } // load bgrd loadBgrd("ad_3d_pointcloud.bgrd", "ad_3d_pointcloud_bgrd2ply.ply"); } .. group-tab:: C# .. code-block:: c# Settings3D参数 ------------------ Settings3D类,用于设置3D采集的参数,包括采集帧配置、点云过滤器配置等。 它提供了参数的保存和加载功能,可以通过save和load方法将参数保存到文件或从文件加载。 以下是代码示例: .. tabs:: .. group-tab:: C++ .. code-block:: C++ try { DaoAI::Settings3D settings_3d; settings_3d.save("ad_3d_settings.yaml"); settings_3d.load("ad_3d_settings.yaml"); } catch (const std::exception& e) { std::cerr << "Error saving or loading settings: " << e.what() << std::endl; } .. group-tab:: C# .. code-block:: c# 现场校准 ----------- 我们提供了现场校准功能,可以通过现场校准功能对相机进行标定,以提高测量精度。 它需要使用标定板进行标定,需要已知如下参数:标定板的圆行列数、两个圆的圆心距离。 首先,使用captureInfieldCalibrationData方法采集3-5次标定板数据,并将结果保存到std::vector target_result_vector中。 然后,使用infieldCalibration方法对采集到的标定板数据进行校准,校准结果返回百分比改进(范围 0 - 1.0),值越大表示校准效果越好。 最后,使用evaluateAccuracy方法评估校准结果,如果校准效果不好,可以重新采集标定板数据,重新进行校准。 以下是代码示例: .. tabs:: .. group-tab:: C++ .. code-block:: C++ // Adjust each parameter as needed. try { std::vector target_result_vec; // capture infield calibration data for 5 times DaoAI::Settings3D::FrameConfig frame_config_calibration(/*exposure_stop*/-1, /*brightness*/3.0, /*gain*/0.0); int pattern_column = 11; int pattern_row = 9; DaoAI::Size pattern_size(pattern_column, pattern_row); // 11x9 calibration board float center_distance = 2.5f; // Distance between the center of the calibration board circles for (size_t i = 0; i < 5; i++) { auto target_result = camera->captureInfieldCalibrationData(frame_config_calibration, pattern_size); target_result_vec.push_back(target_result); } // save infield calibration data auto percentage_improvement = camera->infieldCalibration(target_result_vec, pattern_size, center_distance); std::cout << "Infield calibration improvement: " << percentage_improvement << "%" << std::endl; // evaluate infield calibration DaoAI::Settings3D settings_3d; DaoAI::Settings3D::FrameConfig frame_config(/*exposure_stop*/-1, /*brightness*/3.0, /*gain*/0.0); std::vector frame_configs; frame_configs.push_back(frame_config); settings_3d.setFrameConfigs(frame_configs); // we can set filters here auto start = std::chrono::high_resolution_clock::now(); auto frame3d = camera->capture3D(settings_3d); DaoAI::PointCloud point_cloud = frame3d.getPointCloud(); // capture preview image of the calibration board DaoAI::Settings3D::FrameConfig frame_config_preview(/*exposure_stop*/-1, /*brightness*/3.0, /*gain*/0.0); auto preview_images = camera->preview(frame_config_preview); DaoAI::AccuracyResult accuracy_result = camera->evaluateAccuracy(point_cloud, preview_images.at(0), pattern_size, center_distance); std::cout << "Infield calibration accuracy max error: " << accuracy_result.max_err_perc << "%" << std::endl; std::cout << "Infield calibration accuracy avg error: " << accuracy_result.avg_err_perc << "%" << std::endl; } catch (const std::exception& e) { std::cerr << "Infield Calibration Error: " << e.what() << std::endl; } .. group-tab:: C# .. code-block:: c#