参考:kinect 2.0 SDK学习笔记(四)–深度图与彩色图对齐
主要是在这个程序里面,加了点语句,因为原理是根据深度图像像素坐标计算出来对应的原始RGB图像像素坐标,出现重影的地方可能是因为这一部分是彩色相机的盲区,没有颜色,而深度相机有像素,根据像素坐标计算出来对应到彩色图像坐标会有重复。所以只要判断每次计算出来彩色图像的坐标,是否和之前计算的重复即可。
每次计算出来彩色图像的坐标后,标记为1,下一次计算出来这个坐标发现标记为1了,说明之前已经提取过了,那么这个深度像素点很有可能就是彩色图像的盲区,把这个像素设置为黑色,就去掉重影了。
但是处理完了之后还是有重影,不知道是我对齐的部分对齐的不太好,还是我这种去除重影的方法有问题,先这样吧。
/*
功能:将深度图映射到彩色图上,生成和深度图匹配的对齐彩色图
参考:https://blog.csdn.net/jiaojialulu/article/details/53154045
https://blog.csdn.net/jiaojialulu/article/details/53154045?locationNum=8&fps=1
日志:
2020.7.23 可用!
2021.4.28 加了去除重影的部分,成功!但是不知道是不太严谨还是因为自己对齐的不太好,有些地方的重影还是存在。但是已经去除很多啦!
*/
#include
#include
#include
#include
#include
#include
#include
#include
using namespace cv;
using namespace std;
struct KinectParm
{
float fx_rgb;
float fy_rgb;
float cx_rgb;
float cy_rgb;
float fx_ir;
float fy_ir;
float cx_ir;
float cy_ir;
Eigen::Matrix3f R_ir2rgb;
Eigen::Vector3f T_ir2rgb;
};
bool loadParm(KinectParm* kinectParm)
{
// 加载参数
ifstream parm("registration_me_modification_T.txt");
string stringLine;
if (parm.is_open())
{
// rgb相机参数:fx,fy,cx,cy
getline(parm, stringLine);
stringstream lin(stringLine);
string s1, s2, s3, s4, s5, s6, s7, s8, s9;
lin >> s1 >> s2 >> s3 >> s4;
kinectParm->fx_rgb = atof(s1.c_str());
kinectParm->fy_rgb = atof(s2.c_str());
kinectParm->cx_rgb = atof(s3.c_str());
kinectParm->cy_rgb = atof(s4.c_str());
stringLine.clear();
// ir相机参数:fx,fy,cx,cy
getline(parm, stringLine);
stringstream lin2(stringLine);
lin2 << stringLine;
lin2 >> s1 >> s2 >> s3 >> s4;
kinectParm->fx_ir = atof(s1.c_str());
kinectParm->fy_ir = atof(s2.c_str());
kinectParm->cx_ir = atof(s3.c_str());
kinectParm->cy_ir = atof(s4.c_str());
stringLine.clear();
// R_ir2rgb
getline(parm, stringLine);
stringstream lin3(stringLine);
lin3 << stringLine;
lin3 >> s1 >> s2 >> s3 >> s4 >> s5 >> s6 >> s7 >> s8 >> s9;
kinectParm->R_ir2rgb <<
atof(s1.c_str()), atof(s2.c_str()), atof(s3.c_str()),
atof(s4.c_str()), atof(s5.c_str()), atof(s6.c_str()),
atof(s7.c_str()), atof(s8.c_str()), atof(s9.c_str());
stringLine.clear();
// T_ir2rgb
getline(parm, stringLine);
stringstream lin4(stringLine);
lin4 << stringLine;
lin4 >> s1 >> s2 >> s3;
kinectParm->T_ir2rgb << atof(s1.c_str()), atof(s2.c_str()), atof(s3.c_str());
}
else
{
cout << "parm.txt not right!!!";
return false;
}
cout << "******************************************" << endl;
cout << "fx_rgb: " << kinectParm->fx_rgb << endl;
cout << "fy_rgb: " << kinectParm->fy_rgb << endl;
cout << "cx_rgb: " << kinectParm->cx_rgb << endl;
cout << "cy_rgb: " << kinectParm->cy_rgb << endl;
cout << "******************************************" << endl;
cout << "fx_ir: " << kinectParm->fx_ir << endl;
cout << "fy_ir: " << kinectParm->fy_ir << endl;
cout << "cx_ir: " << kinectParm->cx_ir << endl;
cout << "cy_ir: " << kinectParm->cy_ir << endl;
cout << "******************************************" << endl;
cout << "R_ir2rgb:" << endl << kinectParm->R_ir2rgb << endl;
cout << "******************************************" << endl;
cout << "T_ir2rgb:" << endl << kinectParm->T_ir2rgb << endl;
cout << "******************************************" << endl;
return true;
}
int main()
{
// 1. 读取参数
KinectParm *parm = new KinectParm();
if (!loadParm(parm))
return 0;
// 2. 载入rgb图片和深度图并显示
Mat bgr(1080, 1920, CV_8UC4);
bgr = imread("2020-12- 3-20-12- 5-rgb.png");
Mat depth(424, 512, CV_16UC1);
depth = imread("2020-12- 3-20-12- 5-depth.png", IMREAD_ANYDEPTH); // 图片读入后的格式不一定和定义时候的一样,比如这里读入后的格式就是8UC3
//Mat depth2rgb = imread("2019- 4-13-19-46-35-depth.png");
// 3. 显示
thread th = std::thread([&]{
while (true)
{
imshow("原始彩色图", bgr);
waitKey(1);
imshow("原始深度图", depth);
waitKey(1);
/*imshow("原始投影图", depth2rgb);
waitKey(1);*/
}
});
// 4. 变换
// 4.1 计算各个矩阵
#pragma region 非齐次
Eigen::Matrix3f K_ir; // ir内参矩阵
K_ir <<
parm->fx_ir, 0, parm->cx_ir,
0, parm->fy_ir, parm->cy_ir,
0, 0, 1;
Eigen::Matrix3f K_rgb; // rgb内参矩阵
K_rgb <<
parm->fx_rgb, 0, parm->cx_rgb,
0, parm->fy_rgb, parm->cy_rgb,
0, 0, 1;
Eigen::Matrix3f R;
Eigen::Vector3f T;
Eigen::Vector3f T_me;//2020.6.23 自己手动平移一下
R = K_rgb*parm->R_ir2rgb*K_ir.inverse();
T = K_rgb*parm->T_ir2rgb;
T_me << 10000, 0, 0;//2020.6.23 加是颜色往左移动
cout << "K_rgb:\n" << K_rgb << endl;
cout << "K_ir:\n" << K_ir << endl;
cout << "R:\n" << R << endl;
cout << "T:\n" << T << endl;
cout << depth.type() << endl;
// 4.2 计算投影
Mat result(424, 512, CV_8UC3);
int i = 0,x;
Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic> matrix_NN;//创建动态矩阵,不能创建静态矩阵,因为维数太高——Eigen::Matrix matrix_NN;
matrix_NN = Eigen::MatrixXd::Zero(1920, 1080);//用零矩阵初始化
for (int row = 0; row < 424; row++)
{
for (int col = 0; col < 512; col++)
{
unsigned short* p = (unsigned short*)depth.data;
unsigned short depthValue = p[row * 512 + col];//16位
//cout << "depthValue " << depthValue << endl;
if (depthValue != -std::numeric_limits<unsigned short>::infinity() && depthValue != -std::numeric_limits<unsigned short>::infinity() && depthValue != 0 && depthValue != 65535)
{
// 投影到彩色图上的坐标
Eigen::Vector3f uv_depth(col, row, 1.0f); // !!!p_ir
//Eigen::Vector3f uv_color = depthValue / 1000.f*R*uv_depth + T / 1000; // !!!Z_rgb*p_rgb=R*Z_ir*p_ir+T; (除以1000,是为了从毫米变米)
Eigen::Vector3f uv_color = depthValue / 1000.f*R*uv_depth + (T + T_me) / 1000;//2020.6.23//公式含义:已知深度某一像素坐标及对应深度值,求彩色图对应像素坐标及其彩色值
int X = static_cast<int>(uv_color[0] / uv_color[2]); // !!!Z_rgb*p_rgb -> p_rgb,这里为深度图某一像素坐标(col,row)对应的彩色图像素坐标(X,Y)(这里说的彩色图为原始彩色图:1920×1080)
int Y = static_cast<int>(uv_color[1] / uv_color[2]); // !!!Z_rgb*p_rgb -> p_rgb
//cout << "X: " << X << " Y: " << Y << endl;
if ((X >= 0 && X < 1920) && (Y >= 0 && Y < 1080))
{
if (matrix_NN(X, Y) == 1)//2021.4.28 去除重影程序,计算出来的XY为原大小的RGB图像,只要第二次计算出来和之前计算出的坐标一样就把这个点置零,而不是赋上颜色
{
result.data[i * 3] = 0;
result.data[i * 3 + 1] = 0;
result.data[i * 3 + 2] = 0;
}
else
{
matrix_NN(X, Y) = 1;
//cout << "X: " << X << " Y: " << Y << endl;
result.data[i * 3] = bgr.data[3 * (Y * 1920 + X)];//1920*1080个点顺次排列,再加上rgb分开来,每个像素三个值,一共1920*1080*3个数字,上面求得深度图坐标(col,row)这个点对应在彩色图中的坐标为(X,Y)通过这3个公式,就能找到这个坐标对应的rgb值
result.data[i * 3 + 1] = bgr.data[3 * (Y * 1920 + X) + 1];//因为对于深度图col,row是顺序遍历的,所以保存到对齐后的彩色图,直接顺序保存即可
result.data[i * 3 + 2] = bgr.data[3 * (Y * 1920 + X) + 2];
//cout << "b: " << result.data[i * 3] << " g: " << result.data[i * 3 + 1] << endl;
}
}
else
{
result.data[i * 3] = 0;
result.data[i * 3 + 1] = 0;
result.data[i * 3 + 2] = 0;
}
}
else
{
result.data[i * 3] = 0;
result.data[i * 3 + 1] = 0;
result.data[i * 3 + 2] = 0;
}
i++;
//cout << "i=" << i << endl;
}
}
imwrite("2020-12- 3-20-12- 5-result.png", result);
thread th2 = std::thread([&]{
while (true)
{
imshow("结果图", result);
waitKey(1);
}
});
th.join();
th2.join();
#pragma endregion
system("pause");
return 0;
}