我需要从rgb和深度图像生成oni文件。我使用了来自openni的NiRecordSynthetic样本。它适用于我的深度图像但是当我为我的RGB图像添加transformImageMD函数时,我将在imageMap(x,y)= imagePixel中得到分段错误。 我不知道为什么。
这是我的代码:
void transformDepthMD(Mat FrameDepth,DepthMetaData& depthMD)
{
DepthMap& depthMap = depthMD.WritableDepthMap();
for (XnUInt32 y = 0; y < depthMap.YRes(); y++)
{
for (XnUInt32 x = 0; x < depthMap.XRes(); x++)
{
//Punch vertical cut lines in the depth image
if ((x % 2) == 0)
{
depthMap(x,y) = FrameDepth.at<XnUInt16>(y,x);
}
}
}
}
void transformImageMD(Mat FrameImage,ImageMetaData& imageMD)
{
RGB24Map& imageMap = imageMD.WritableRGB24Map();
for (XnUInt32 y = 0; y < imageMD.YRes(); y++)
{
for (XnUInt32 x = 0; x <imageMD.XRes(); x++)
{
XnRGB24Pixel imagePixel;
imagePixel.nBlue=FrameImage.at<Vec3b>(y,x)[0];
imagePixel.nGreen=FrameImage.at<Vec3b>(y,x)[1];
imagePixel.nRed=FrameImage.at<Vec3b>(y,x)[2];
imageMap(x,y) = imagePixel;
}
}
}
int main(int argc, char* argv[])
{
XnStatus nRetVal = XN_STATUS_OK;
nRetVal = xnLogInitFromXmlFile(SAMPLE_XML_PATH);
if (nRetVal != XN_STATUS_OK)
{
printf("Log couldn't be opened: %s. Running without log", xnGetStatusString(nRetVal));
}
if (argc < 3)
{
printf("usage: %s <inputFile> <outputFile>\n", argv[0]);
return -1;
}
const char* strInputFile = argv[1];
const char* strOutputFile = argv[2];
Context context;
nRetVal = context.Init();
CHECK_RC(nRetVal, "Init");
// open input file
Player player;
nRetVal = context.OpenFileRecording(strInputFile, player);
CHECK_RC(nRetVal, "Open input file");
// Get depth node from recording
DepthGenerator depth;
nRetVal = context.FindExistingNode(XN_NODE_TYPE_DEPTH, depth);
CHECK_RC(nRetVal, "Find depth generator");
// Create mock node based on depth node from recording
MockDepthGenerator mockDepth;
nRetVal = mockDepth.CreateBasedOn(depth);
CHECK_RC(nRetVal, "Create mock depth node");
ImageGenerator image;
nRetVal = context.FindExistingNode(XN_NODE_TYPE_IMAGE, image);
CHECK_RC(nRetVal, "Find depth generator");
// Create mock node based on depth node from recording
MockImageGenerator mockImage;
nRetVal = mockImage.CreateBasedOn(image);
CHECK_RC(nRetVal, "Create mock depth node");
// create recorder
Recorder recorder;
nRetVal = recorder.Create(context);
CHECK_RC(nRetVal, "Create recorder");
nRetVal = recorder.SetDestination(XN_RECORD_MEDIUM_FILE, strOutputFile);
CHECK_RC(nRetVal, "Set recorder destination file");
// add depth node to recorder
nRetVal = recorder.AddNodeToRecording(mockDepth);
CHECK_RC(nRetVal, "Add node to recording");
nRetVal = recorder.AddNodeToRecording(mockImage);
CHECK_RC(nRetVal, "Add node to recording");
nRetVal = player.SetRepeat(FALSE);
XN_IS_STATUS_OK(nRetVal);
XnUInt32 nNumFrames = 0;
nRetVal = player.GetNumFrames(image.GetName(), nNumFrames);
CHECK_RC(nRetVal, "Get player number of frames");
DepthMetaData depthMD;
ImageMetaData imageMD;
int frameNum = 0;
String path = "myData";
while ((nRetVal = depth.WaitAndUpdateData()) != XN_STATUS_EOF)
{
++frameNum;
CHECK_RC(nRetVal, "Read next frame");
// Get depth meta data
depth.GetMetaData(depthMD);
image.GetMetaData(imageMD);
nRetVal = depthMD.MakeDataWritable();
CHECK_RC(nRetVal, "Make depth data writable");
nRetVal = imageMD.MakeDataWritable();
CHECK_RC(nRetVal, "Make depth data writable");
String ficheroActualRGB;
ficheroActualRGB = path +"RGB_" + boost::to_string(frameNum) + ".png";
String ficheroActualDepth = path +"Depth_"+ boost::to_string(frameNum) + ".png";
Mat matFrameImage = imread(ficheroActualRGB, 1);
resize(matFrameImage, matFrameImage, Size(640, 480), 0, 0, INTER_CUBIC);
Mat matFrameDepth = imread(ficheroActualDepth,1);
resize(matFrameDepth, matFrameDepth, Size(640, 480), 0, 0, INTER_CUBIC);
transformDepthMD(matFrameDepth,depthMD);
transformImageMD(matFrameImage,imageMD);
// Pass the transformed data to the mock depth generator
nRetVal = mockDepth.SetData(depthMD);
CHECK_RC(nRetVal, "Set mock node new data");
nRetVal = mockImage.SetData(imageMD);
CHECK_RC(nRetVal, "Set mock node new data");
/* We need to call recorder.Record explicitly because we're not using WaitAndUpdateAll(). */
nRetVal = recorder.Record();
CHECK_RC(nRetVal, "Record");
printf("Recorded: frame %u out of %u\r", depthMD.FrameID(), nNumFrames);
}
printf("\n");
return 0;
}
谢谢,
答案 0 :(得分:1)
由于奇怪的原因,我也无法从imageMD获取任何数据。但您可以使用自己的样式将RGB-D图像转换为.oni文件。 我使用OpenCV和OpenNI来实现这一目标。
以下是示例代码。
string color_dir="your_color_dir/", depth_dir="your_depth_dir/";
int frame_num = 100;
XnStatus nRetVal = XN_STATUS_OK;
Context context;
nRetVal = context.Init();
CHECK_RC(nRetVal, "Init");
Player player;
nRetVal = context.OpenFileRecording("input.oni", player); // we use existence .oni file to simulate a oni context environment.
CHECK_RC(nRetVal, "Open input file");
DepthGenerator depth;
ImageGenerator color;
nRetVal = context.FindExistingNode(XN_NODE_TYPE_IMAGE, color);
CHECK_RC(nRetVal, "Find color generator");
nRetVal = context.FindExistingNode(XN_NODE_TYPE_DEPTH, depth);
CHECK_RC(nRetVal, "Find depth generator");
MockDepthGenerator mockDepth;
nRetVal = mockDepth.CreateBasedOn(depth);
CHECK_RC(nRetVal, "Create mock depth node");
MockImageGenerator mockColor;
mockColor.CreateBasedOn(color);
CHECK_RC(nRetVal, "Create mock color node");
Recorder recorder;
nRetVal = recorder.Create(context);
CHECK_RC(nRetVal, "Create recorder");
nRetVal = recorder.SetDestination(XN_RECORD_MEDIUM_FILE, "dst.oni");
CHECK_RC(nRetVal, "Set recorder destination file");
nRetVal = recorder.AddNodeToRecording(mockDepth);
CHECK_RC(nRetVal, "Add node to recording");
nRetVal = recorder.AddNodeToRecording(mockColor);
CHECK_RC(nRetVal, "Add node to recording");
for (int i = 0; i < frame_num;++i)
{
std::stringstream ss;
ss << depth_dir << i << ".png";
std::string filepath_depth = ss.str();
std::stringstream sss;
sss << color_dir << i << ".png";
std::string filepath_color = sss.str();
cv::Mat depth_img = cv::imread(filepath_depth, CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);
depth_img.convertTo(depth_img, CV_16U);
cv::Mat color_img = cv::imread(filepath_color, CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);
color_img.convertTo(color_img, CV_8UC3);
//depth
DepthMetaData depthMD;
XnUInt32& di = depthMD.FrameID();
di = i; // set frame id.
XnUInt64& dt = depthMD.Timestamp();
dt = i*30000+1; // set a proper timestamp.
depthMD.AllocateData(depth_img.cols, depth_img.rows);
DepthMap& depthMap = depthMD.WritableDepthMap();
for (XnUInt32 y = 0; y < depthMap.YRes(); y++)
{
for (XnUInt32 x = 0; x < depthMap.XRes(); x++)
{
depthMap(x, y) = depth_img.at<ushort>(y, x);
}
}
nRetVal = mockDepth.SetData(depthMD);
CHECK_RC(nRetVal, "Set mock node new data");
//color
ImageMetaData colorMD;
XnUInt32& ci = colorMD.FrameID();
ci = i;
XnUInt64& ct = colorMD.Timestamp();
ct = i*30000+1;
colorMD.AllocateData(color_img.cols, color_img.rows, XN_PIXEL_FORMAT_RGB24);
RGB24Map& imageMap = colorMD.WritableRGB24Map();
for (XnUInt32 y = 0; y < imageMap.YRes(); y++)
{
for (XnUInt32 x = 0; x < imageMap.XRes(); x++)
{
cv::Vec3b intensity = color_img.at<cv::Vec3b>(y, x);
imageMap(x, y).nBlue = (XnUInt8)intensity.val[0];
imageMap(x, y).nGreen = (XnUInt8)intensity.val[1];
imageMap(x, y).nRed = (XnUInt8)intensity.val[2];
}
}
nRetVal = mockColor.SetData(colorMD);
CHECK_RC(nRetVal, "Set mock node new data");
recorder.Record();
printf("Recorded: frame %u out of %u\r", depthMD.FrameID(), frame_num);
}