save image as png or jpeg?

2,816 views
Skip to first unread message

Jae Yong Sung

unread,
Jan 20, 2011, 3:42:50 PM1/20/11
to openn...@googlegroups.com
Is there way to take pic with kinect and save it as png, jpeg, or any other regular image format?

Thanks
Jae

Jae

unread,
Jan 21, 2011, 7:58:43 PM1/21/11
to openn...@googlegroups.com

Bene

unread,
Jan 24, 2011, 7:30:53 AM1/24/11
to OpenNI
Hi Jae,
you could convert the image maps provided by openNi into openCV images
and save them to disk with cvSaveImage.
Don't forget, when saving your images in jpg you will loose quality. I
would prefer png as it's a lossless codec.
Conversion from OpenNi to OpenCV image could be done like this:


cv::Mat colorArr[3];
cv::Mat colorImage;
const XnRGB24Pixel* pImageRow;
const XnRGB24Pixel* pPixel;

imageGen.SetPixelFormat(XN_PIXEL_FORMAT_RGB24 ); //
xn::ImageGenerator imageGen;
imageGen.GetMetaData(imageMD); //xn::ImageMetaData imageMD;
pImageRow = imageMD.RGB24Data();

colorArr[0] = cv::Mat(imageMD.YRes(),imageMD.XRes(),CV_8U);
colorArr[1] = cv::Mat(imageMD.YRes(),imageMD.XRes(),CV_8U);
colorArr[2] = cv::Mat(imageMD.YRes(),imageMD.XRes(),CV_8U);

for (int y=0; y<imageMD.YRes(); y++){
pPixel = pImageRow;
uchar* Bptr = colorArr[0].ptr<uchar>(y);
uchar* Gptr = colorArr[1].ptr<uchar>(y);
uchar* Rptr = colorArr[2].ptr<uchar>(y);
for(int x=0;x<imageMD.XRes();++x , ++pPixel){
Bptr[x] = pPixel->nBlue;
Gptr[x] = pPixel->nGreen;
Rptr[x] = pPixel->nRed;
}
pImageRow += imageMD.XRes();
}
cv::merge(colorArr,3,colorImage);


On 22 Jan., 01:58, Jae <jysung...@gmail.com> wrote:
>

andrissh

unread,
Feb 15, 2011, 11:04:47 AM2/15/11
to OpenNI
Hi, Bene and Jae
did this work for you?
thanks for the helpful code. I tried it, but it did not work correctly
and it has a strange behaviour. (I used
cv::imwrite("test.png",colorImage for the saving). Let me describe it:
-1)at best, it gives a picture in which exactly the first 2/3 part
(firs 320 pixel rows) is a mess (although this mess resemles a bit the
real view), and the last 160 rows are OK and nice sharp correct image,
BUT it shows the upper third of the real view. In other words, the
last third shows my head instead of my legs, if the real view has the
3 equal parts ( eg. head+body+legs)
so even this correct one third is not on its correct place.
-2) at worst the whole picture is a mess resembling the real view ,
and also the first third part of the real view is at the bottom on the
last third

there is only best and worst case.

is this opencv algorithm problem, or something with the openNI part of
my program?
thanks,


On Jan 24, 1:30 pm, Bene <benedikt.mei...@gmx.de> wrote:
> Hi Jae,
> you could convert theimagemaps provided by openNi into openCV images
> andsavethem to disk with cvSaveImage.
> Don't forget, when saving your images in jpg you will loose quality. I
> would prefer png as it's a lossless codec.
> Conversion from OpenNi to OpenCVimagecould be done like this:

andrissh

unread,
Feb 15, 2011, 11:04:54 AM2/15/11
to OpenNI
Hi, Bene and Jae
did this work for you?
thanks for the helpful code. I tried it, but it did not work correctly
and it has a strange behaviour. (I used
cv::imwrite("test.png",colorImage for the saving). Let me describe it:
-1)at best, it gives a picture in which exactly the first 2/3 part
(firs 320 pixel rows) is a mess (although this mess resemles a bit the
real view), and the last 160 rows are OK and nice sharp correct image,
BUT it shows the upper third of the real view. In other words, the
last third shows my head instead of my legs, if the real view has the
3 equal parts ( eg. head+body+legs)
so even this correct one third is not on its correct place.
-2) at worst the whole picture is a mess resembling the real view ,
and also the first third part of the real view is at the bottom on the
last third

there is only best and worst case.

is this opencv algorithm problem, or something with the openNI part of
my program?
thanks,


On Jan 24, 1:30 pm, Bene <benedikt.mei...@gmx.de> wrote:
> Hi Jae,
> you could convert theimagemaps provided by openNi into openCV images
> andsavethem to disk with cvSaveImage.
> Don't forget, when saving your images in jpg you will loose quality. I
> would prefer png as it's a lossless codec.
> Conversion from OpenNi to OpenCVimagecould be done like this:

Hongyoung Jeon

unread,
Feb 15, 2011, 11:38:49 AM2/15/11
to OpenNI
With bene's code as a base, I did not have problems to save correct
images in png or bitmap (but I did not use opencv).
So, if you have problems with your images, it probably be your code
issue.

steve...@bluewin.ch

unread,
Feb 16, 2011, 6:22:17 AM2/16/11
to openn...@googlegroups.com
hi
i think its opencv ...... ?
i came from libfreenect, and work with opencv & opengl under ubuntu-10.10
i save my
images to *.jpg but i have the same error
if i translate a opencv(x,y-Point) (color or grayScale) to opengl 3d-point
(x,y,z) , z == 0.0f,
in the next days i hope to solve (.;-o this problem
regards nomad

----Ursprüngliche
Nachricht----
Von: andris...@gmail.com
Datum: 15.02.2011 17:04
An: "OpenNI"<openn...@googlegroups.com>
Betreff:
[OpenNI-dev] Re: save image as png or jpeg?


--
You received this message because you are subscribed to the Google Groups "OpenNI" group.
To post to this group,
send email to openn...@googlegroups.com.
To unsubscribe from this group, send email to openni-
dev+uns...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/openni-dev?hl=en.


andrissh

unread,
Feb 16, 2011, 8:43:54 AM2/16/11
to OpenNI
Yes, Jeon, you were right.
I had a silly mistype in my code.
Now it is working, I could save the rgb image. Now I am trying to save
an IR image, but I dont really understand how should it work.. I guess
I only need one matrix for that, cause it is only one channel, the
XnIRPixel format is 16bit. how can I build the matrix?

cv::Mat colorArr;
const XnIRPixel* pImageRow;
const XnIRPixel* pPixel;
pImageRow = imageMD.Data();
colorArr = cv::Mat(imageMD.YRes(),imageMD.XRes(),CV_16U); // <<<???

for (int y=0; y<imageMD.YRes(); y++){
pPixel = pImageRow;

//WHAT TO WRITE HERE???

pImageRow += imageMD.XRes();
}
cv::imwrite(filename, colorArr); //<<<???


any hint?

Hongyoung Jeon

unread,
Feb 16, 2011, 10:18:51 AM2/16/11
to OpenNI
Yes, you would need one 640*480 matrix, but need to have 2 BYTE array
since it is 16 bit data. As I mentioned before, I am not using openCV,
so I am not sure how to do this in OpenCV.

But the way I did is I converted 16 bit data to 8 bit data (of course
the converting results in losing resolution, and save as bitmap.
Basically, you get what you see in depth image display window and this
works fine for me.
Or if you want to save as 16 bit grayscale images, why bother to
convert to other formats? There is a built-in function to save 16 bit
grayscale images in raw format, and you can open raw images from
imageJ. In addition, if you need depth information for your
application, you should be able to directly get it from depthmap (or
whatever you use for storing depth information) .

Sam Muscroft

unread,
Feb 16, 2011, 11:14:20 AM2/16/11
to OpenNI
I'd recommend reading up on OpenCV (http://www.cs.iit.edu/~agam/cs512/
lect-notes/opencv-intro/opencv-intro.html#SECTION00041000000000000000)

You just need to create a single channel 16U matrix (or IplImage -
seeing as an IplImage is essentially a matrix with headers) loop
through each pixel of the IR map and set the corresponding pixel in
the matrix to the IR value. Check the direct access using a pointer
section in the link above.

Jeon - it depends on what you want to do with maps, if you need to
process them somehow in opencv then you'll need to convert them to an
opencv matrix format.

andrissh

unread,
Feb 16, 2011, 11:22:17 AM2/16/11
to OpenNI
on the built in function you mean the openNI function
xnOSSaveFile("test1.raw",imageMD.Data(),imageMD.DataSize());
?
or you referred to other built in function?
I used this to save rgb image in raw format, but I could not open the
raw file with imageJ 1.4

sorry for the newbie questions.
thanx

Bene

unread,
Feb 16, 2011, 11:54:39 AM2/16/11
to OpenNI
Hi,
I'm glad I could help some people with the conversion code. If anyone
still has a problem with cv::imwrite, I could recommend to create an C
API IplImage header for the cv::Mat and try to save it with
cvSaveImage(). Some functions seem to be buggy in the C++ API (of
OpenCv 2.1) like cv::imwrite, cv::threshold... especially in
combination with 16bit Images.

This worked for me :
fullPath = bgrPath + fileName; // the path and
filename in a std::string
IplImage bgrIpl = bgrImg; // create a
IplImage header for the cv::Mat bgrImage
cvSaveImage(fullPath.c_str(),&bgrIpl); // save it with the old
C API

regards,
Bene

Hongyoung Jeon

unread,
Feb 16, 2011, 12:05:59 PM2/16/11
to OpenNI
Yes. That is the function that I mentioned.
Well. I am not sure why you have problems.. Anyway, I did not have any
problems to open raw files.
I am sure you know this, but just FYI.
When you open raw files in ImageJ, you should use 'Import' instead of
'open'.
And you need to select few information (I think data bit, and image
sizes.. something like that..).
If ImageJ is not working for you, you can use photoshop too. Photoshop
worked fine for me when I open RGB image. But it did not work for
grayscale images.
Hope this helps.

Jaume Gallego

unread,
Mar 18, 2011, 5:37:40 AM3/18/11
to OpenNI
Hi all,
I am working on foreground segmentation using kinect. I needed to
extract the color and depth images in a synchronized and registerd way
and This thread has been very useful for me. I write you the code I
have used to do it, if someone need to do the same:

I started modifying the NiViewer sample code you can find in:
/OpenNI/Platform/Linux-x86/Redist/Samples/NiViewer

Then, I modified some of their files to achieve the .jpg recording
jointly with the .oni file. To save the images, I have used opencv
library.

extract RGB images (in Device.cpp):

//new includes:
#include "cv.h"
#include "highgui.h"
#include "sstream"
#include "string"

//jaume. New function to save RGB frames in jpg format.

void saveFrame_RGB(int num)
{
cv::Mat colorArr[3];
cv::Mat colorImage;
const XnRGB24Pixel* pImageRow;
const XnRGB24Pixel* pPixel;

// ImageMetaData* g_ImageMD = getImageMetaData();
g_Image.GetMetaData(g_ImageMD);
pImageRow = g_ImageMD.RGB24Data();

colorArr[0] = cv::Mat(g_ImageMD.YRes(),g_ImageMD.XRes(),CV_8U);
colorArr[1] = cv::Mat(g_ImageMD.YRes(),g_ImageMD.XRes(),CV_8U);
colorArr[2] = cv::Mat(g_ImageMD.YRes(),g_ImageMD.XRes(),CV_8U);

for (int y=0; y<g_ImageMD.YRes(); y++)
{
pPixel = pImageRow;
uchar* Bptr = colorArr[0].ptr<uchar>(y);
uchar* Gptr = colorArr[1].ptr<uchar>(y);
uchar* Rptr = colorArr[2].ptr<uchar>(y);
for(int x=0;x<g_ImageMD.XRes();++x , ++pPixel)
{
Bptr[x] = pPixel->nBlue;
Gptr[x] = pPixel->nGreen;
Rptr[x] = pPixel->nRed;
}
pImageRow += g_ImageMD.XRes();
}
cv::merge(colorArr,3,colorImage);

char framenumber[10];
sprintf(framenumber,"%06d",num);


std::stringstream ss;
std::string str_frame_number;
// char c = 'a';
ss << framenumber;
ss >> str_frame_number;

std::string str_aux = "CapturedFrames/image_RGB_"+
str_frame_number +".jpg";
IplImage bgrIpl = colorImage; // create a
IplImage header for the cv::Mat bgrImage
cvSaveImage(str_aux.c_str(),&bgrIpl); // save it with the
old

}

extract Depth images (in Draw.cpp):

//new includes:
#include "cv.h"
#include "highgui.h"

//jaume. New function to save depth map in jpg format. I have based
this implementation on the draw images function.

void saveFrame_depth(int num)
{
const DepthMetaData* pDepthMD = getDepthMetaData();
const XnDepthPixel* pDepth = pDepthMD->Data();
XN_ASSERT(pDepth);

cv::Mat depthImage;
cv::Mat colorArr[3];

colorArr[0] = cv::Mat(pDepthMD->YRes(),pDepthMD->XRes(),CV_8U);
colorArr[1] = cv::Mat(pDepthMD->YRes(),pDepthMD->XRes(),CV_8U);
colorArr[2] = cv::Mat(pDepthMD->YRes(),pDepthMD->XRes(),CV_8U);


for (XnUInt16 nY = pDepthMD->YOffset(); nY < pDepthMD->YRes() +
pDepthMD->YOffset(); nY++)
{
XnUInt8* pTexture = TextureMapGetLine(&g_texDepth, nY) + pDepthMD-
>XOffset()*4;

uchar* Bptr = colorArr[0].ptr<uchar>(nY);
uchar* Gptr = colorArr[1].ptr<uchar>(nY);
uchar* Rptr = colorArr[2].ptr<uchar>(nY);

for (XnUInt16 nX = 0; nX < pDepthMD->XRes(); nX++, pDepth++,
pTexture+=4)
{
XnUInt8 nRed = 0;
XnUInt8 nGreen = 0;
XnUInt8 nBlue = 0;
XnUInt8 nAlpha = g_DrawConfig.Streams.Depth.fTransparency*255;

XnUInt16 nColIndex;

switch (g_DrawConfig.Streams.Depth.Coloring)
{
case LINEAR_HISTOGRAM:
nBlue = nRed = nGreen = g_pDepthHist[*pDepth]*255;
break;
case PSYCHEDELIC_SHADES:
nAlpha *= (((XnFloat)(*pDepth % 10) / 20) + 0.5);
case PSYCHEDELIC:

switch ((*pDepth/10) % 10)
{
case 0:
nRed = 255;
break;
case 1:
nGreen = 255;
break;
case 2:
nBlue = 255;
break;
case 3:
nRed = 255;
nGreen = 255;
break;
case 4:
nGreen = 255;
nBlue = 255;
break;
case 5:
nRed = 255;
nBlue = 255;
break;
case 6:
nRed = 255;
nGreen = 255;
nBlue = 255;
break;
case 7:
nRed = 127;
nBlue = 255;
break;
case 8:
nRed = 255;
nBlue = 127;
break;
case 9:
nRed = 127;
nGreen = 255;
break;
}
break;
case RAINBOW:
nColIndex = (XnUInt16)((*pDepth / (g_fMaxDepth / 256)));
nRed = PalletIntsR[nColIndex];
nGreen = PalletIntsG[nColIndex];
nBlue = PalletIntsB[nColIndex];
break;
case CYCLIC_RAINBOW:
nColIndex = (*pDepth % 256);
nRed = PalletIntsR[nColIndex];
nGreen = PalletIntsG[nColIndex];
nBlue = PalletIntsB[nColIndex];
break;
}



Bptr[nX] = nBlue ;
Gptr[nX] = nGreen;
Rptr[nX] = nRed;


}
}

cv::merge(colorArr,3, depthImage);


char framenumber[10];
sprintf(framenumber,"%06d",num);


std::stringstream ss;
std::string str_frame_number;

ss << framenumber;
ss >> str_frame_number;

//CapturedFrames folder must exist!!!
std::string str_aux = "CapturedFrames/image_depth_"+
str_frame_number +".jpg";

IplImage bgrIpl = depthImage; // create a
IplImage header for the cv::Mat bgrImage
cvSaveImage(str_aux.c_str(),&bgrIpl); // save it with the
old

}



File where I use these new functionalities: Capture.cpp.


//New include:
#include <iostream>

//Function modified to save frames in jpg format:
XnStatus captureFrame()
{
XnStatus nRetVal = XN_STATUS_OK;
if (g_Capture.State == SHOULD_CAPTURE)
{
XnUInt64 nNow;
xnOSGetTimeStamp(&nNow);
nNow /= 1000;

if (nNow >= g_Capture.nStartOn)
{
g_Capture.nCapturedFrames = 0;
g_Capture.State = CAPTURING;
}
}

if (g_Capture.State == CAPTURING)
{
nRetVal = g_Capture.pRecorder->Record();
XN_IS_STATUS_OK(nRetVal);

//start.jaume
saveFrame_RGB(g_Capture.nCapturedFrames);
saveFrame_depth(g_Capture.nCapturedFrames);
//end.jaume

g_Capture.nCapturedFrames++;
}
return XN_STATUS_OK;
}

To test the code, you must execute the new NiViewer app, and use the
options Capture->start that appear just clicking in the left mouse
button.

It's all, I hope this code will be useful.

Jaume

qkqh

unread,
May 2, 2011, 9:23:14 PM5/2/11
to openn...@googlegroups.com
Hi,

This was very helpful for me getting 640*480 image.
However if I run both skeleton tracking and image dumping together, frame rate drops ..
Is there simple way to cut the image down to 320*240 image??

Thanks for help.
Reply all
Reply to author
Forward
0 new messages