OpenCV结构光三维重建类cv::structured_light::GrayCodePattern

  • 操作系统:ubuntu22.04
  • OpenCV版本:OpenCV4.9
  • IDE:Visual Studio Code
  • 编程语言:C++11

算法描述

cv::structured_light::GrayCodePattern 是 OpenCV 库中用于结构光三维重建 的一个类,属于 OpenCV 的 structured_light 模块。

它用于生成和解码 格雷码(Gray Code) 图案,广泛应用于 3D 扫描、深度重建、物体表面形状获取等领域。

主要功能

  • 生成一组黑白格雷码图像(水平 + 垂直)
  • 对相机拍摄的变形格雷码图像进行解码
  • 输出每个像素的"水平"和"垂直"编码值(即像素在投影图案中的唯一编码)
  • 可用于计算相机与投影仪之间的像素对应关系(correspondence)

常用成员函数

函数 说明
static Ptr create(Size size); 创建一个格雷码图案生成器,size 是投影图像的分辨率(如 1024x768)
bool generate(std::vector& pattern); 生成格雷码图案序列,输出为一组二值图像(黑白)
bool decode(InputArrayOfArrays patternImages, OutputArray disparity, InputArrayOfArrays whiteImages=noArray(), InputArrayOfArrays blackImages=noArray(), InputArray mask=noArray()); 解码拍摄的格雷码图像序列,输出视差图(disparity)或编码图
int getWidth() const; 获取图案宽度
int getHeight() const; 获取图案高度

使用流程(典型结构光系统)

一个典型的 结构光 3D 扫描系统 包括:

  • 一台 投影仪(Projector):投射格雷码图案
  • 一台 相机(Camera):拍摄被物体变形后的图案
  • 一台 计算机:运行 OpenCV 处理图像

步骤:

  • 生成格雷码图案
cpp 复制代码
cv::Ptr<cv::structured_light::GrayCodePattern> grayPattern = 
    cv::structured_light::GrayCodePattern::create(cv::Size(1024, 768));

std::vector<cv::Mat> patternImages;
grayPattern->generate(patternImages);  // 生成 ~20 张黑白图像
  • 依次投影图案,并用相机拍摄

    • 投影第 i 张图 → 相机拍摄第 i 张变形图 → 存入 capturedImages[i]
  • 解码拍摄的图像

cv::Mat disparity;

bool success = grayPattern->decode(capturedImages, disparity);

if (success) {

// disparity 包含每个像素的水平编码值(可用于 3D 重建)

}

  • 结合相机标定、投影仪标定,计算三维点云

📌 注意事项

  • disparity 图实际上是 水平方向的编码值,类似于"相位",可用于匹配相机和投影仪的像素。
  • 通常还需要配合 正弦条纹(Phase Shift) 方法进行亚像素级精度提升。
  • structured_light 模块在 OpenCV 3.0+ 引入,需编译时启用 opencv_contrib 模块。
  • 必须安装 opencv-contrib,否则无法使用该类!

应用场景

  • 工业零件三维扫描
  • 人脸识别与建模
  • 医疗三维成像
  • 虚拟现实内容生成

示例代码

cpp 复制代码
#include <opencv2/opencv.hpp>
#include <opencv2/structured_light.hpp>

int main()
{
    int width    = 1024;
    int height   = 768;
    auto pattern = cv::structured_light::GrayCodePattern::create( width, height );

    std::vector< cv::Mat > images;
    pattern->generate( images );

    // 保存所有图案
    for ( size_t i = 0; i < images.size(); ++i )
    {
        cv::imwrite( "pattern_" + std::to_string( i ) + ".png", images[ i ] );
    }

    return 0;
}

运行结果