互补格雷码技术
import numpy as np
import cv2
import glob
import open3d as o3d
import matplotlib.pyplot as plt
Gray_Code_Mape = {'0000': 0, '0001': 1, '0011': 2, '0010': 3, '0110': 4, '0111': 5, '0101': 6, '0100': 7, '1100': 8,
'1101': 9, '1111': 10, '1110': 11, '1010': 12, '1011': 13, '1001': 14, '1000': 15}
ComplementGrayCodeMap = {'00000': 1, '00001': 2, '00011': 3, '00010': 4, '00110': 5, '00111': 6, '00101': 7, '00100': 8,
'01100': 9, '01101': 10, '01111': 11, '01110': 12, '01010': 13, '01011': 14, '01001': 15,
'01000': 16, '11000': 17, '11001': 18, '11011': 19, '11010': 20, '11110': 21, '11111': 22,
'11101': 23, '11100': 24, '10100': 25, '10101': 26, '10111': 27, '10110': 28, '10010': 29,
'10011': 30, '10001': 31, '10000': 32}
Gray_Code_Mape1 = {'0': 0, '1': 1, '3': 2, '2': 3, '6': 4, '7': 5, '5': 6, '4': 7, '12': 8,
'13': 9, '15': 10, '14': 11, '10': 12, '11': 13, '9': 14, '8': 15}
ComplementGrayCodeMap1 = {'0': 0, '1': 1, '3': 2, '2': 3, '6': 4, '7': 5, '5': 6, '4': 7,
'12': 8, '13': 9, '15': 10, '14': 11, '10': 12, '11': 13, '9': 14,
'8': 15, '24': 16, '25': 17, '27': 18, '26': 19, '30': 20, '31': 21,
'29': 22, '28': 23, '20': 24, '21': 25, '23': 26, '22': 27, '18': 28,
'19': 29, '17': 30, '16': 31}
class StructureLight(object):
def __init__(self, cal_path):
imagefilenames = glob.glob(cal_path + '/*.bmp')
images = []
for filename in imagefilenames:
img = cv2.imread(filename)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img = img.astype('double')
images.append(img)
self.ImgWhite = images[0]
self.ImgBlack = images[1]
self.ImgMask = (self.ImgWhite - self.ImgBlack).astype('uint8')
ret, self.ImgMask = cv2.threshold(self.ImgMask, 0, 255, cv2.THRESH_OTSU)
self.ImgMask = cv2.medianBlur(self.ImgMask, 5)
self.ImgMaskBool = self.ImgMask <= 128
self.GC1, self.GC2, self.GC3, self.GC4, self.GC5 = images[2:7]
self.PS1, self.PS2, self.PS3, self.PS4 = images[7:11]
pass
def CalTruncPhase(self):
'''计算截断相位'''
self.Phase_Decode = (np.arctan2(self.PS1 - self.PS3, self.PS2 - self.PS4)).astype('double')
index = (self.PS1 - self.PS3) <= 0
self.Phase_Decode[index] += 2 * np.pi
self.Phase_Decode[self.ImgMaskBool] = 0
cv2.imshow('Phase_Decode', self.Phase_Decode / self.Phase_Decode.max())
cv2.waitKey(500)
pass
def CalStepK(self):
'''计算级次K'''
thresh = (self.ImgWhite - self.ImgBlack) * 0.5
GC1_bin = ((self.GC1 - self.ImgBlack) > thresh).astype('double')
GC2_bin = ((self.GC2 - self.ImgBlack) > thresh).astype('double')
GC3_bin = ((self.GC3 - self.ImgBlack) > thresh).astype('double')
GC4_bin = ((self.GC4 - self.ImgBlack) > thresh).astype('double')
GC5_bin = ((self.GC5 - self.ImgBlack) > thresh).astype('double')
V1 = GC1_bin * 8 + GC2_bin * 4 + GC3_bin * 2 + GC4_bin
V2 = V1 * 2 + GC5_bin
self.K1 = np.vectorize(Gray_Code_Mape1.get)(V1.astype('int').astype('str'))
self.K1[self.ImgMaskBool] = 0
cv2.imshow('K1', self.K1 / self.K1.max())
cv2.waitKey(500)
self.K2 = np.floor((np.vectorize(ComplementGrayCodeMap1.get)(V2.astype('int').astype('str')) + 1) / 2.0)
self.K2[self.ImgMaskBool] = 0
cv2.imshow('K2', self.K2 / self.K2.max())
cv2.waitKey(500)
pass
def CalAbsPhase(self):
'''计算绝对相位'''
self.AbsPhase = np.zeros_like(self.Phase_Decode).astype('double')
index = self.Phase_Decode <= 0.5 * np.pi
self.AbsPhase[index] = self.Phase_Decode[index] + 2 * np.pi * self.K2[index]
index = (self.Phase_Decode > 0.5 * np.pi) * (self.Phase_Decode <= 1.5 * np.pi)
self.AbsPhase[index] = self.Phase_Decode[index] + 2 * np.pi * self.K1[index]
index = self.Phase_Decode > 1.5 * np.pi
self.AbsPhase[index] = self.Phase_Decode[index] + 2 * np.pi * self.K2[index] - 2 * np.pi
self.AbsPhase[self.ImgMaskBool] = 0
cv2.imshow('AbsPhase', self.AbsPhase / self.AbsPhase.max())
cv2.waitKey(0)
return self.AbsPhase
if __name__ == '__main__':
sl = StructureLight('G:/Decode/pattern')
sl.CalTruncPhase()
sl.CalStepK()
sl.CalAbsPhase()
实验所需编码图,其中黑白主要是为了去除背景