RGB-D相机(Azure Kinect DK)RGB图、深度图的获取,配准与保存
前提:官方apt安装Azure Kinect 传感器 SDK
代码AcquiringImages将原始深度图转换到RGB摄像头坐标系下,得到的配准后的深度图,并将转换后的depth图,原始RGB图、原始IR图保存在本地,采集格式仿照TUM数据集,图片的命名格式为时间戳+.png后缀。
1.C++代码:
// C++
#include
#include
#include
// OpenCV
#include
#include
#include
// Kinect DK
#include
using namespace cv;
using namespace std;
// 宏
// 方便控制是否 std::cout 信息
#define DEBUG_std_cout 0
int main(int argc, char *argv[]) {
/*
找到并打开 Azure Kinect 设备
*/
// 发现已连接的设备数
const uint32_t device_count = k4a::device::get_installed_count();
if (0 == device_count) {
std::cout << "Error: no K4A devices found. " << std::endl;
return -1;
} else {
std::cout << "Found " << device_count << " connected devices. " << std::endl;
if (1 != device_count)// 超过1个设备,也输出错误信息。
{
std::cout << "Error: more than one K4A devices found. " << std::endl;
return -1;
} else// 该示例代码仅限对1个设备操作
{
std::cout << "Done: found 1 K4A device. " << std::endl;
}
}
// 打开(默认)设备
k4a::device device = k4a::device::open(K4A_DEVICE_DEFAULT);
std::cout << "Done: open device. " << std::endl;
/*
检索并保存 Azure Kinect 图像数据
*/
// 配置并启动设备
k4a_device_configuration_t config = K4A_DEVICE_CONFIG_INIT_DISABLE_ALL;
config.camera_fps = K4A_FRAMES_PER_SECOND_30;
config.color_format = K4A_IMAGE_FORMAT_COLOR_BGRA32;
config.color_resolution = K4A_COLOR_RESOLUTION_1080P;
config.depth_mode = K4A_DEPTH_MODE_NFOV_UNBINNED;
//config.depth_mode = K4A_DEPTH_MODE_WFOV_2X2BINNED;
config.synchronized_images_only = true;// ensures that depth and color images are both available in the capture
device.start_cameras(&config);
std::cout << "Done: start camera." << std::endl;
//写入txt文件流
ofstream rgb_out;
ofstream d_out;
ofstream ir_out;
rgb_out.open("./rgb.txt");
d_out.open("./depth.txt");
ir_out.open("./ir.txt");
rgb_out<<"# color images"<<endl;
rgb_out<<"# file: rgbd_dataset"<<endl;
rgb_out<<"# timestamp"<<" "<<"filename"<<endl;
d_out<<"# depth images"<<endl;
d_out<<"# file: rgbd_dataset"<<endl;
d_out<<"# timestamp"<<" "<<"filename"<<endl;
ir_out<<"# ir images"<<endl;
ir_out<<"# file: rgbd_dataset"<<endl;
ir_out<<"# timestamp"<<" "<<"filename"<<endl;
rgb_out<<flush;
d_out<<flush;
// 稳定化
k4a::capture capture;
int iAuto = 0;//用来稳定,类似自动曝光
int iAutoError = 0;// 统计自动曝光的失败次数
while (true) {
if (device.get_capture(&capture)) {
std::cout << iAuto << ". Capture several frames to give auto-exposure" << std::endl;
// 跳过前 n 个(成功的数据采集)循环,用来稳定
if (iAuto != 30) {
iAuto++;
continue;
} else {
std::cout << "Done: auto-exposure" << std::endl;
break;// 跳出该循环,完成相机的稳定过程
}
} else {
std::cout << iAutoError << ". K4A_WAIT_RESULT_TIMEOUT." << std::endl;
if (iAutoError != 30) {
iAutoError++;
continue;
} else {
std::cout << "Error: failed to give auto-exposure. " << std::endl;
return -1;
}
}
}
std::cout << "-----------------------------------" << std::endl;
std::cout << "----- Have Started Kinect DK. -----" << std::endl;
std::cout << "-----------------------------------" << std::endl;
// 从设备获取捕获
k4a::image rgbImage;
k4a::image depthImage;
k4a::image irImage;
k4a::image transformed_depthImage;
cv::Mat cv_rgbImage_with_alpha;
cv::Mat cv_rgbImage_no_alpha;
cv::Mat cv_depth;
cv::Mat cv_depth_8U;
cv::Mat cv_irImage;
cv::Mat cv_irImage_8U;
while (true)
// for (size_t i = 0; i < 100; i++)
{
// if (device.get_capture(&capture, std::chrono::milliseconds(0)))
if (device.get_capture(&capture)) {
// rgb
// * Each pixel of BGRA32 data is four bytes. The first three bytes represent Blue, Green,
// * and Red data. The fourth byte is the alpha channel and is unused in the Azure Kinect APIs.
rgbImage = capture.get_color_image();
#if DEBUG_std_cout == 1
std::cout << "[rgb] " << "
"
<< "format: " << rgbImage.get_format() << "
"
<< "device_timestamp: " << rgbImage.get_device_timestamp().count() << "
"
<< "system_timestamp: " << rgbImage.get_system_timestamp().count() << "
"
<< "height*width: " << rgbImage.get_height_pixels() << ", " << rgbImage.get_width_pixels()
<< std::endl;
#endif
// depth
// * Each pixel of DEPTH16 data is two bytes of little endian unsigned depth data. The unit of the data is in
// * millimeters from the origin of the camera.
depthImage = capture.get_depth_image();
#if DEBUG_std_cout == 1
std::cout << "[depth] " << "
"
<< "format: " << depthImage.get_format() << "
"
<< "device_timestamp: " << depthImage.get_device_timestamp().count() << "
"
<< "system_timestamp: " << depthImage.get_system_timestamp().count() << "
"
<< "height*width: " << depthImage.get_height_pixels() << ", " << depthImage.get_width_pixels()
<< std::endl;
#endif
// ir
// * Each pixel of IR16 data is two bytes of little endian unsigned depth data. The value of the data represents
// * brightness.
irImage = capture.get_ir_image();
#if DEBUG_std_cout == 1
std::cout << "[ir] " << "
"
<< "format: " << irImage.get_format() << "
"
<< "device_timestamp: " << irImage.get_device_timestamp().count() << "
"
<< "system_timestamp: " << irImage.get_system_timestamp().count() << "
"
<< "height*width: " << irImage.get_height_pixels() << ", " << irImage.get_width_pixels()
<< std::endl;
#endif
//深度图和RGB图配准
k4a::calibration k4aCalibration = device.get_calibration(config.depth_mode, config.color_resolution);// Get the camera calibration for the entire K4A device, which is used for all transformation functions.
k4a::transformation k4aTransformation = k4a::transformation(k4aCalibration);
transformed_depthImage = k4aTransformation.depth_image_to_color_camera(depthImage);
cv_rgbImage_with_alpha = cv::Mat(rgbImage.get_height_pixels(), rgbImage.get_width_pixels(), CV_8UC4,
(void *) rgbImage.get_buffer());
cv::cvtColor(cv_rgbImage_with_alpha, cv_rgbImage_no_alpha, cv::COLOR_BGRA2BGR);
cv_depth = cv::Mat(transformed_depthImage.get_height_pixels(), transformed_depthImage.get_width_pixels(), CV_16U,
(void *) transformed_depthImage.get_buffer(), static_cast<size_t>(transformed_depthImage.get_stride_bytes()));
cv_depth.convertTo(cv_depth_8U, CV_8U, 1);
cv_irImage = cv::Mat(irImage.get_height_pixels(), irImage.get_width_pixels(), CV_16U,
(void *) irImage.get_buffer(), static_cast<size_t>(irImage.get_stride_bytes()));
cv_irImage.convertTo(cv_irImage_8U, CV_8U, 1);
// show image
cv::imshow("color", cv_rgbImage_no_alpha);
cv::imshow("depth", cv_depth_8U);
cv::imshow("ir", cv_irImage_8U);
// save image
double time_rgb = static_cast<double >(std::chrono::duration_cast<std::chrono::microseconds>(
rgbImage.get_device_timestamp()).count());
std::string filename_rgb = std::to_string(time_rgb/1000000)+".png";
double time_d = static_cast<double >(std::chrono::duration_cast<std::chrono::microseconds>(
depthImage.get_device_timestamp()).count());
std::string filename_d = std::to_string(time_d/1000000)+".png";
double time_ir = static_cast<double >(std::chrono::duration_cast<std::chrono::microseconds>(
irImage.get_device_timestamp()).count());
std::string filename_ir = std::to_string(time_ir/1000000)+".png";
imwrite("./rgb/"+filename_rgb, cv_rgbImage_no_alpha);
imwrite("./depth/"+filename_d,cv_depth_8U);
imwrite("./ir/"+filename_ir, cv_irImage_8U);
std::cout<<"Acquiring!"<<endl;
//写入depth.txt,rgb.txt文件
rgb_out<<std::to_string(time_rgb/1000000)<<" "<<"rgb/"<<filename_rgb<<endl;
d_out<<std::to_string(time_d/1000000)<<" "<<"depth/"<<filename_d<<endl;
ir_out<<std::to_string(time_ir/1000000)<<" "<<"ir/"<<filename_ir<<endl;
rgb_out<<flush;
d_out<<flush;
ir_out<<flush;
cv_rgbImage_with_alpha.release();
cv_rgbImage_no_alpha.release();
cv_depth.release();
cv_depth_8U.release();
cv_irImage.release();
cv_irImage_8U.release();
capture.reset();
//if (cv::waitKey(0) == 'q') {//按键采集,用户按下'q',跳出循环,结束采集
// std::cout << "----------------------------------" << std::endl;
// std::cout << "------------- closed -------------" << std::endl;
// std::cout << "----------------------------------" << std::endl;
// break;
// }
} else {
std::cout << "false: K4A_WAIT_RESULT_TIMEOUT." << std::endl;
}
}
cv::destroyAllWindows();
rgb_out<<flush;
d_out<<flush;
ir_out<<flush;
rgb_out.close();
d_out.close();
ir_out.close();
// 释放,关闭设备
rgbImage.reset();
depthImage.reset();
irImage.reset();
capture.reset();
device.close();
return 1;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
2. CMakeLists
# Enable C++11
set(CMAKE_CXX_FLAGS "-std=c++11")
set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
# Define project name
project(AcquiringImages)
# Kinect DK相机
find_package(k4a REQUIRED)# 后面的target_link_libraries中用到了k4a::k4a
# Find OpenCV
find_package(OpenCV REQUIRED)
# Add includes
include_directories( ${OpenCV_INCLUDE_DIRS} )
# Declare the executable target built from your sources
add_executable(AcquiringImages main.cpp)
# Link your application with other libraries
target_link_libraries(AcquiringImages k4a::k4a ${OpenCV_LIBS})
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
3. 编译运行:
进入源码目录:
mkdir build
cd build
mkdir rgb depth ir//未创建rgb depth ir文件夹
cmake .. -GNinja
ninja
./AcquiringImages
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
闭终端或终止程序即可结束图像的采集。
结束图像采集后,将RGB图和深度图相关联:
进入源码目录:
cd build
python associate.py rgb.txt depth.txt > ./associations.txt
- 1
- 2
- 3
- 4
- 5
4. 采集示例
以下为409实验室采集的图片示例:
RGB图:
深度图:
IR图:
5. 参考
http://iyenn.com/index/link?url=https://cloud.tencent.com/developer/column/81192
评论记录:
回复评论: