@TangWill
2019-07-26T20:10:29.000000Z
字数 8433
阅读 622
大创
# -*- coding: utf-8 -*-
from PIL import Image
import os
def de_bruijn(k, n):
"""
de Bruijn sequence for alphabet k
and subsequences of length n.
"""
try:
# let's see if k can be cast to an integer;
# if so, make our alphabet a list
_ = int(k)
alphabet = list(map(str, range(k)))
except (ValueError, TypeError):
alphabet = k
k = len(k)
a = [0] * k * n
sequence = []
def db(t, p):
if t > n:
if n % p == 0:
sequence.extend(a[1:p + 1])
else:
a[t] = a[t - p]
db(t + 1, p)
for j in range(a[t - p] + 1, k):
a[t] = j
db(t + 1, t)
db(1, 1)
return "".join(alphabet[i] for i in sequence)
if __name__ == "__main__":
DB = de_bruijn(3, 3)
DB_list = list(DB)
print(DB_list)
x = 912
y = 1140
c = Image.new("RGB", (x, y))
skip = False
i = 0
while i < x:
for k in range(0, 15):
rgb = 255 - (5*(k - 7) ** 2)
temp = int(i / 20)
if temp < 27:
for j in range(0, y):
if i % 20 == 0:
for m in range(0, 5):
c.putpixel([i + m + 186, j], (0, 0, 0))
i = i + 5
skip = False
elif DB_list[temp] == "0":
c.putpixel([i + k + 186, j], (rgb, 0, 0))
skip = True
elif DB_list[temp] == "1":
c.putpixel([i + k + 186, j], (0, rgb, 0))
skip = True
elif DB_list[temp] == "2":
c.putpixel([i + k + 186, j], (0, 0, rgb))
skip = True
if skip:
i = i + 15
else:
i = i + 1
c.show()
c.save("structured_light .bmp")
main.m
clear all; clc; %清空变量
%--------------------------------------------------------------
% 0:red,1:green,2:blue
% num: 为debruijn序列,包含红绿蓝3种颜色,window size为3
% num序列总长度为3^3 = 27
% 原投影图案生成方法:
% (1).原投影图片大小竖直方向1140像素,水平方向912像素
% (2).每个条纹水平方向长度15个像素,第一个条纹中心位于第8个像素位置
% 因此条纹中心像素坐标为8+(i-1)*20
% map: map(i,j,k)表示连续三个颜色为(i,j,k)的三元组i颜色对应的条纹中心位置
% 例如map(0,0,0)=8,因为三个连续红条纹在开始的位置,第一个红条纹中心为8
% map(1,0,0)=68, 绿红红位于第4个位置,68为绿条纹中心
%--------------------------------------------------------------
num = [0, 0, 0, 1, 0, 0, 2, 0, 1, 1, 0, 1, 2, 0, 2, 1, 0, 2, 2, 1, 1, 1, 2, 1, 2, 2, 2];
map = zeros(3,3,3);
for i=1:25
map(num(i)+1,num(i+1)+1,num(i+2)+1) = 8 + (i-1)*20;
end
%--------------------------------------------------------------
% R12: 由相机到投影仪的旋转矩阵 3*3
% T12: 由相机到投影仪的平移矩阵 1*3
% Kc1: 相机内参矩阵 3*3
% Kp2: 投影仪内参矩阵 3*3
% Hc1: 相机单应性矩阵 3*4
% Hp2: 投影仪单应性矩阵 3*4
%--------------------------------------------------------------
R12 = [9.7516454746001247e-001 -7.7281024823287244e-003 2.2134674564838733e-001;
5.4950021604755926e-004 9.9947240635257240e-001 3.2474713075112072e-002;
-2.2148093242223318e-001 -3.1546558795230203e-002 9.7465430343355963e-001];
T12 = [-1.4326112323874105e+002 2.0614986909838471e+001 -1.0037865572591169e+001];
Kc1 = [2.1363192826189816e+003 0. 6.4087239901301598e+002;
0. 2.1377724542629630e+003 4.9766519824009470e+002;
0. 0. 1.];
Kp2 = [1.7342859113112791e+003 0. 4.5022560667574703e+002;
0. 3.4614881021035653e+003 5.2438368036642009e+002;
0. 0. 1.];
Hp2 = Kp2*[R12,T12'];
Hc1 = Kc1*[eye(3,3),zeros(3,1)];
img12 = imread('2.png'); %读取图片
imshow(img12);
[flag12,color_flag12] = feature_point(img12); %提取特征,详情见函数内部注释
figure;
imshow(color_flag12);
[num_coord12, coord12] = reconstruction(color_flag12,Hc1,Hp2,map); %三维坐标重建,详情见函数内部注释
figure;
scatter3(coord12(:,1),coord12(:,2),coord12(:,3),2) %画三维离散点图
feature.m
%--------------------------------------------------------------
%条纹特征点提取,包括条纹中心点的位置和对应的颜色
%1:red,2:green,3:blue
%输入参数IMG: 大小n*m*3,表示输入三通道彩色图片
%输出参数flag: 大小n*m, 表示对应像素是否是条纹中心
% flag(i,j)=1表示(i,j)位置是条纹中心,flag的值为0或1
%输出参数color_flag: 大小n*m,表示对应条纹中心的颜色
% color_flag(i,j)=2代表(i,j)位置条纹中心颜色为绿色
% color_flag(i,j)=0代表该位置不是条纹中心
%--------------------------------------------------------------
function [flag, color_flag] = feature_point(IMG)
IMG_gray = rgb2gray(IMG); %彩色图转灰度图
flag = zeros(1024,1280); %初始化
color_flag = zeros(1024,1280); %初始化
linyu = 5; %一个阈值,可自取
%i和j的范围代表物体在图片的这个范围内,限制范围可以增加计算速度,可自取
for i=300:880
for j=500:1000
if IMG_gray(i,j)<10 %如果灰度图的对应像素值小于10认为该点为黑色背景
continue;
end
% temp为以(i,j)为中心长度为2*linyu+1的图像灰度数组
temp = IMG_gray(i,j-linyu:j+linyu);
% 如果当前中心点的灰度值是这个邻域中的最大值,那么认为该点是条纹中心
[~,da] = max(temp);
if da == linyu+1
flag(i,j)=1;
end
end
end
for i=300:880
for j=500:1000
if flag(i,j)==0 %如果不是条纹中心则跳过
continue;
end
%灰度图片,如果灰度值大于150认为该点是白色条纹中心
% if IMG_gray(i,j)>150
% color_flag(i,j)=4;
% continue;
% end
%彩色图片,如果第一个通道比另外两个通道值大,认为该位置是红色条纹中心
if IMG(i,j,1)>IMG(i,j,2) && IMG(i,j,1)>IMG(i,j,3)
color_flag(i,j)=1;
continue;
end
%彩色图片,如果第二个通道比另外两个通道值大,认为该位置是绿色条纹中心
if IMG(i,j,2)>IMG(i,j,1) && IMG(i,j,2)>IMG(i,j,3)
color_flag(i,j)=2;
continue;
end
%彩色图片,如果第三个通道比另外两个通道值大,认为该位置是蓝色条纹中心
if IMG(i,j,3)>IMG(i,j,2) && IMG(i,j,3)>IMG(i,j,1)
color_flag(i,j)=3;
continue;
end
end
end
end
reconstruction.m
%--------------------------------------------------------------
%物体三维坐标点重建
%输入参数color_flag: 对应feature_point函数的第二个输出
%输入参数Hc: 相机单应性矩阵
%输入参数Hp: 投影仪单应性矩阵
%输入参数map: 主函数开始的那个map数组
%输出参数num_coord: 输出三维点的数目
%输出参数coord: 输出三维点的坐标
%--------------------------------------------------------------
function [num_coord, coord] = reconstruction(color_flag,Hc,Hp,map)
num_coord = 0; %初始化
for i=300:880
ind = 0;
loc = zeros(1,100);
%将图片第i行的所有条纹中心临时存储在loc中
for j=500:1000
if color_flag(i,j)~=0
ind = ind+1;
loc(ind) = j;
end
end
if (ind<3) % 如果少于3个中心则无法重建
continue;
end
for j = 1:ind-2
A = zeros(3,3);
num_coord = num_coord+1;
A(1,:) = Hc(3,1:3).*loc(j)-Hc(1,1:3);
A(2,:) = Hc(3,1:3).*i-Hc(2,1:3);
A(3,:) = Hp(3,1:3).*map(color_flag(i,loc(j)),color_flag(i,loc(j+1)),color_flag(i,loc(j+2)))-Hp(1,1:3);
ydx = A\[Hc(1,4)-Hc(3,4)*loc(j);Hc(2,4)-Hc(3,4)*i;Hp(1,4)-Hp(3,4)*map(color_flag(i,loc(j)),color_flag(i,loc(j+1)),color_flag(i,loc(j+2)))];
% 设定一下和相机的距离,如果过近或者过远显然都是噪声点,可自取
% if ydx(3)>1000 || ydx(3)<500
% continue;
% end
coord(num_coord,:) = ydx';
end
% debruijn序列最后两个条纹仍利用最后三个颜色重建
for j=ind-1:ind
if j==ind-1
A = zeros(3,3);
num_coord = num_coord+1;
A(1,:) = Hc(3,1:3).*loc(j)-Hc(1,1:3);
A(2,:) = Hc(3,1:3).*i-Hc(2,1:3);
A(3,:) = Hp(3,1:3).*(map(color_flag(i,loc(j-1)),color_flag(i,loc(j)),color_flag(i,loc(j+1)))+15)-Hp(1,1:3);
ydx = A\[Hc(1,4)-Hc(3,4)*loc(j);
Hc(2,4)-Hc(3,4)*i;
Hp(1,4)-Hp(3,4)*(map(color_flag(i,loc(j-1)),color_flag(i,loc(j)),color_flag(i,loc(j+1)))+15)];
% if ydx(3)>1000 || ydx(3)<500
% continue;
% end
coord(num_coord,:) = ydx';
elseif j==ind
A = zeros(3,3);
num_coord = num_coord+1;
A(1,:) = Hc(3,1:3).*loc(j)-Hc(1,1:3);
A(2,:) = Hc(3,1:3).*i-Hc(2,1:3);
A(3,:) = Hp(3,1:3).*(map(color_flag(i,loc(j-2)),color_flag(i,loc(j-1)),color_flag(i,loc(j)))+30)-Hp(1,1:3);
ydx = A\[Hc(1,4)-Hc(3,4)*loc(j);
Hc(2,4)-Hc(3,4)*i;
Hp(1,4)-Hp(3,4)*(map(color_flag(i,loc(j-2)),color_flag(i,loc(j-1)),color_flag(i,loc(j)))+30)];
% if ydx(3)>1000 || ydx(3)<500
% continue;
% end
coord(num_coord,:) = ydx';
end
end
end
end
未注释部分参考公式:
式中,表示的是矩阵的第行和第列元素。将两个式子整理后得到关于、和的三元一次方程,
<?xml version="1.0"?>
<opencv_storage>
<Kc type_id="opencv-matrix">
<rows>3</rows>
<cols>3</cols>
<dt>d</dt>
<data>
2.1363192826189816e+003 0. 6.4087239901301598e+002 0.
2.1377724542629630e+003 4.9766519824009470e+002 0. 0. 1.</data></Kc>
<kc type_id="opencv-matrix">
<rows>5</rows>
<cols>1</cols>
<dt>d</dt>
<data>
-5.6850946659891023e-002 2.6322763056141931e+000
-1.1377015012654045e-003 1.6506197473016759e-003
-2.1654415041354078e+001</data></kc>
<Kp type_id="opencv-matrix">
<rows>3</rows>
<cols>3</cols>
<dt>d</dt>
<data>
1.7342859113112791e+003 0. 4.5022560667574703e+002 0.
3.4614881021035653e+003 5.2438368036642009e+002 0. 0. 1.</data></Kp>
<kp type_id="opencv-matrix">
<rows>5</rows>
<cols>1</cols>
<dt>d</dt>
<data>
9.6270780483633647e-002 -8.0172849754942543e+000
-2.6246483366578217e-003 2.3503112604238339e-003
2.2313956040160841e+002</data></kp>
<Rp type_id="opencv-matrix">
<rows>3</rows>
<cols>3</cols>
<dt>d</dt>
<data>
9.8817697193050202e-001 -2.7706101018562532e-003
1.5329251731877641e-001 1.1226239513894419e-002
9.9846035682073886e-001 -5.4322071055690473e-002
-1.5290599626123413e-001 5.5400718199914163e-002
9.8668663552836944e-001</data></Rp>
<Tp type_id="opencv-matrix">
<rows>3</rows>
<cols>1</cols>
<dt>d</dt>
<data>
-1.5168118625605635e+002 1.7918489397033632e+001
-5.3101094723810185e+001</data></Tp>
<cam_error>6.0649322922523355e-002</cam_error>
<proj_error>1.5337621234636628e-001</proj_error>
<stereo_error>1.3013498108534971e-001</stereo_error>
<frameWidth>1280</frameWidth>
<frameHeight>1024</frameHeight>
<screenResX>0</screenResX>
<screenResY>0</screenResY>
</opencv_storage>