概述
1 格雷码:
1.1 格雷码引言:
在数字系统中,常要求代码按一定顺序变化。
在机器视觉里面,编码结构光也是按照一定的顺序进行变化,最常用的就是Binary,但是,二进制的纯粹的编码,由于二进制的进制关系(每个位是有权的),如果发生一个错码(在机器视觉里面,错码的发生可能是一个背景的干扰,也可能是测试物体的一个比较陡峭的轮廓变更),一个错码往往他的数字权重不是一位,比如二进制的最高为,错了一位,那么就是整个数值发生一半的变化。
去掉权重的好处就是,如果模拟量或者是采样的数据发生了一个微小的变化,在整个测量的范围内,这个微小的变化都只能变更一个格雷码数位,而不论这个测量的数值位于整个测量量程的哪个位置:
【案】在上面这个例子中,假设测量的量程为16,我们测量到7和8之间的模拟量,你看看二进制,红色表示要变更所有的数位来表示,而格雷码只要变更一位。
那么,在我们表示这个数据的时候,二进制码所有的位都必须不能出错,否则数据会大变化。而格雷码就不会出现这个问题。
后来,弗兰克·格雷(Frank Gray,18870913-19690523)专利“Pulse Code Communication” 发明了一种新的顺序编码的方式,这个方式也是每个数值是唯一的二进制标识,但是,每个相邻的位只有一个位值的变化,这样就极大的减少了测量可能发生误差。
1.2 格雷码的定义:
在一组数的编码中,若任意两个相邻的代码只有一位二进制数不同,则称这种编码为格雷码(Gray Code),另外由于最大数与最小数之间也仅一位数不同,即“首尾相连”,因此又称循环码或反射码。
格雷码是一种具有反射特性和循环特性的单步自补码,其循环和单步特性消除了随机取数时出现重大错误的可能,其反射和自补特性使得对其进行求反操作也非常方便,所以,格雷码属于一种可靠性编码,是一种错误最小化的编码方式,因此格雷码在通信和测量技术中得到广泛应用。
Gray Code(格雷码) C++多方法实现_越前浩波的博客-CSDN博客
3位格雷码的顺序编码_几种简单的编码(为什么使用ASCII码)_乔拉爵士的博客-CSDN博客
1.3 认识格雷码
下为3位元的Gray Code:Gray Code是一个数列集合,每个数使用二进位来表示,假设使用n位元来表示每个数好了,任两个数之间只有一个位元值不同
000 001 011 010 110 111 101 100
1.3.1 位元
位元就是数列的基础数是由几个二进位数来表示,就是几个位元。
上面的例子里面:000 是3个二进制数,那么就是3个位元,那么2^3 = 8,总共8个位值
0000 0001 0011 0010 0110 0111 0101 0100 1100 1101 1111 1110 1010 1011 1001 1000
上面,0000 等是4个 二进制数,那么就是4个位元,那么4^3 = 16,总共16个位值
1.3.2 (格雷)码值
001 就是一个码值
2 格雷码的生成:
2.1 方法1:按照定义排列生成格雷码
回到前面的3位元的格雷码:
000 001 011 010 110 111 101 100
如果推广到N个位元,那么码值的数量应该是2^N个
2.1.1 产生的基本规律原则和标准做法
其实就是3个步骤,
第一步,改变最右边的位元值;
第二步,改变右起第一个为1的位元的左边位元;
第三步,第四步重复第一步和第二步,直到所有的格雷码产生完毕(换句话说,已经走了(2^n) - 1 步)。
举例3位元的产生步骤:
假设产生3位元的格雷码,原始值位 000
第一步:改变最右边的位元值: 001
第二步:改变右起第一个为1的位元的左边位元: 011重复1:
第三步:改变最右边的位元值: 010
第四步:改变右起第一个为1的位元的左边位元: 110重复2:
第五步:改变最右边的位元值: 111
第六步:改变右起第一个为1的位元的左边位元: 101重复3:
第七步:改变最右边的位元值: 100 #已经走了(2^n) - 1 = 7步,完成所有码字的产生。
2.1.2 实现算法如下:
#include <stdio.h>
#include <stdlib.h>
#define MAXBIT 20
#define TRUE 1
#define CHANGE_BIT(x) x = ((x) == '0' ? '1' : '0')
#define NEXT(x) x = (1 - (x))
int main(void) {
char digit[MAXBIT]; int i, bits, odd;
printf("输入位元数:"); scanf("%d", &bits);
for(i = 0; i < bits; i++) { digit[i] = '0';
printf("0");
}
printf("n"); odd = TRUE; while(1) {
if(odd)
CHANGE_BIT(digit[0]);
else {
// 计算第一个1的位置
for(i = 0; i < bits && digit[i] == '0'; i++) ; if(i == bits - 1) // 最后一个Gray Code
break; CHANGE_BIT(digit[i+1]);
}
for(i = bits - 1; i >= 0; i--)
printf("%c", digit[i]);
printf("n"); NEXT(odd);
}
return 0;
}
方法2:
///产生n位格雷码(直接排列方法构建)
void generateGraycode2(int n)
{
int i;
char code[20];
for (i = 0; i < n; i++)
code[i] = '0';
code[n] = '