【互补格雷码+相移】小白解码思路全过程(附部分代码c++)

   记录一下c++零基础入门3D结构光投影,这是初步的12步相移+7副格雷码(4副4位格雷码+一副互补+两张黑白)解码全过程,解码的图片也都是网上找的。

  之前没学过c++,也没有任何语言基础,所以写的时候就是按照公式推导的思路来完成。

总的来说,格雷码就是解出来级次:K=1、2、3、...N,相移解出对应级次的包裹相位,结合二者得出绝对相位。

目录

一、生成格雷码和互补格雷码

二、生成格雷码投影图像

三、生成相移投影图像

四、建立格雷码映射关系

五、解格雷码

六、求包裹相位

七、求绝对相位(解包裹)


一、生成格雷码和互补格雷码

  首先根据需求选择需要投影的格雷码张数,这里我用的4副格雷码(既n=4),周期为2^n为16,生成格雷码原理这里不赘述,网上生成格雷码的代码很多。

   生成的格雷码为:{0000、0001、0011、0010......1000}

 将格雷码转成4*16的矩阵,矩阵的每一行代表所生成的格雷码图片(0代表黑色,1代表白色)

如果只使用格雷码来解包裹相位,会出现边缘跳变的问题,因为格雷码边缘部分对应了相位的边缘部分,为了解决这个问题,我们引入互补格雷码,使互补格雷码稳定的那一部分对应相位出现跳变的那一部分:

 我生成互补格雷码的方式就是在格雷码后面加上0、1、1、0这样循环后缀,代码如下:(没学过,写的都是流水账)

vector<string>hbgraycode;
    for (int i = 0; i < 8; i++) {
        string hbgraycodes1 = grayCodes[2 * i] + to_string(0);   //由于互补格雷码的特点是 0110循环
        hbgraycode.push_back(hbgraycodes1);
        string hbgraycodes2 = grayCodes[2 * i] + to_string(1);    //2i和2i+1其实就是第一个和第二个格雷码
        hbgraycode.push_back(hbgraycodes2);
        string hbgraycodes3 = grayCodes[2 * i + 1] + to_string(1);   //给第一个和第二个格雷码后面分别加0或者1,
        hbgraycode.push_back(hbgraycodes3);
        string hbgraycodes4 = grayCodes[2 * i + 1] + to_string(0);   //等同生成四个五位格雷码
        hbgraycode.push_back(hbgraycodes4);
    }

二、生成格雷码投影图像

  我用的投影光机为DLP3010,需要投影的图像为8bit且大小为1*1280,所以在生成投影图案时,将格雷码与互补格雷码生成1*1280的矩阵,除80是因为图像宽度为1280,周期为16,所以每一个条纹间隔宽度为80,互补格雷码生成原理一样。

Mat patternMat(4, 16, CV_8UC1);
projImg[i].at<uchar>(y, x) = patternMat.at<uchar>(i, x / 80);

三、生成相移投影图像

  这个原理网上一大堆更详细,不赘述,自己理解原理写,我这里用的12步相移图

四、建立格雷码映射关系

  如果给你投影相移条纹图片,你怎么能找到它的位置它是哪根条纹呢,这时候就需要投影的格雷码来辅助了,投影的格雷码条纹图其实就是让你遍历每一个像素点,让其还原成对应的格雷码,比如说我投影了四张格雷码,在(0,0)这个位置点,第一张图像素点为黑色(0),第二张为黑色(0),第三张第四张都为黑色(0),那么在(0,0)这个位置点对应的格雷码就为{0000},转为十进制为0,以此类推每一个像素点,公式为:

 其实就是转成8421,我们一共会得到16个十进制码(V):

 K就是为了方便映射出来的序号而已,c++用map<>这个函数,或者不用映射让两个数组一一对应也行,但是互补格雷码就只能用映射了,根据以下公式,先将互补格雷码转为十进制(实质就是168421码):

 

 K2虽然只到16,但其对应了32个元素,实质K2为{0、1、1、2、2、3、3...15、15、16},找规律发现K2是从1-33除2取证得到的(在c++记得手动取整!!!!!就是因为这一步错了导致解码一直有错!!!!!),建立其与V2的映射即可。

五、解格雷码

  解格雷码我们需要解四位格雷码和加上互补的五位格雷码两种,

   简单来说:读图遍历像素点——格雷码转成十进制(V)——V查找映射表换成K

解互补格雷码图像
解格雷码图像

 

 可以发现互补格雷码比格雷码提前了半个周期,每一种条纹代表一个K,是从小大到排列的阶梯状

六、求包裹相位

  求包裹相位的公式为:

I为图像的灰度,遍历每一个像素点的灰度值就行,N代表相移步数,根据此求出相位主值。 求出的相位包裹在-pai到pai之间,周而复始。

求包裹相位

 

七、求绝对相位(解包裹)

  K求出的是阶梯状的序号,而相位主值被包裹在[-pai,pai]直接,K对应的就是第K个相位,为了展开相位,将第K个相位挨个往上抬K*2pai个相位值,使其连续展开,K1的边缘和相位主值的边缘是对齐的,所以K1的边缘不稳定也会使求包裹相位时出现边缘跳变现象,为了解决所以引入互补格雷码,使其互补格雷码中间稳定的部分对其相位主值边缘部分(看下图很好理解

所以绝对相位就为:

解包裹相位

 

 

此时解包裹相位就完成,后续根据标定相机和投影仪数据建立相高模型。

  • 7
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值