0

I am trying to pass a set of iplimage from OpenCV to another program (.net) that does not use iplimage but uses list of byte[] instead through c++/cli. Any idea how to add/convert iplimage to the list of byte[] ?

Thanks.

fmvpsenior
  • 197
  • 7
  • 22
  • Do you want to store compressed image (jpg) or unpacked bitmap presentation (imageData)? – Mohammad Jul 09 '12 at 18:37
  • I want to store the Iplimage data. – fmvpsenior Jul 09 '12 at 18:44
  • That's not an answer. Is `lplimage` a pointer to the unpacked image data starting at pixel `(0,0)` or is it a pointer to an entire image in memory which may very well be compressed, contain file headers, etc? The two are very different. – Ed S. Jul 09 '12 at 19:11
  • I am using cvQueryframe to capture a frame from an Avi video and that frame is saved to an Iplimage pointer. I would assume the captured frame is compressed image but I am not sure – fmvpsenior Jul 09 '12 at 20:57
  • @bestnagi No image in iplImage is uncompressed. – Mohammad Jul 10 '12 at 04:14

4 Answers4

0

If you want to copy exact pixels from iplimage.imageData, you can use Marshal.Copy to copy data from an IntPtr (imageData) to a managed array (byte[]).

But since imageData is uncompressed, you might want to use imencode or cvEncodeImage to compress it to a intermediate buffer and then copy that to a byte[] with above code.

Mohammad
  • 1,253
  • 1
  • 10
  • 26
  • I was first doing int img_sz1 = img1->width * img1->height * img1->nChannels; array ^ hh1 = gcnew array (img_sz1); Marshal::Copy( (IntPtr)img->imageData, hh1, 0, img_sz1 ); and it was working. I added the encoding step CvMat* buf = cvEncodeImage(".jpeg", img1, jpeg_params); img_sz1=buf->width*buf->height Marshal::Copy( (IntPtr)buf, hh1, 0, img_sz1 ); and now it gives me the error at the marshal:copy line An unhandled exception of type 'System.AccessViolationException' occurred in mscorlib.dll. Additional information: Attempted to read or write protected memory. – fmvpsenior Jul 13 '12 at 01:01
  • The first approach was partially correct `image_sz1` should be `img1->height * img1->widthStep`. in the second approach your copying `cvMat` instead of its data `buf->ptr` (i guess). correct these two errors and let me now if its still not working. – Mohammad Jul 13 '12 at 04:46
0

Before doing anything else, take the time to learn how an IplImage is created, and what kind of information it stores.

Then, notice that the pixels of the image can be accessed through the member imageData, which is an unsigned char*:

IplImage* image = cvLoadImage("starwars.jpg", 0);
int img_sz = image->width * image->height * image->nChannels;
unsigned char* data = (unsigned char*) malloc(img_sz);
memcopy(data, image->imageData, img_sz);

You'll have to do a similar procedure to convert it to byte[]. By the way, this post]2 shows (among other things) how to convert an IplImage* to a SDL_Surface*.

Community
  • 1
  • 1
karlphillip
  • 92,053
  • 36
  • 243
  • 426
0

Firstly, I would recommend that you switch to the C++ API of OpenCV if possible - it offers a lot more flexibility and features as compared to the old C interface.

In the C++ interface, a snippet to perform the above task would be:

cv::Mat image = cv::imread(imname);
uchar *ptr = (uchar*)image.data

You can use your ptr( an 8 bit unsigned byte data ) wherever you want - do remember that modifying this data will modify the actual image. If you do not want that to happen, take a copy of the data using memcpy.

go4sri
  • 1,490
  • 2
  • 15
  • 29
0

If I understand you right you search something like this :

IplImage* image = cvLoadImage("image.bmp");
std::list<unsigned char*> bytes;
for (int i=0;i<image->height;i++)
 {
   bytes.push_back(image->imageData + image ->widthStep*i);
 }

you could test that this works doing the following (I access here the first pixel of the second row):

std::list<unsigned char*>::iterator it = bytes.begin();
it++;
*(*it) = 22;
int a = *((unsigned char*)(image->imageData + image->widthStep*1));

I didn t find no way to do things like this with the new cv::Mat object. You can transform the image to std::vectors but there is no way to transform the image to a row std::vector/std::list. But if you remain use the cv::Mat class you can try the cv::Ptr<Pixelformat> that also gives access to the row pointers.

jamk
  • 836
  • 1
  • 10
  • 24