1

Maybe this is somehow obvious, but I'm still a newbie... ^^"

I use OpenCV to save some images to a video-file. I have 16-bit grayscale images and I found out that cvWriteFrame can only handle 8-bit images. Since I need to process the video later in another context and for that purpose I can't afford the information loss, I'm trying to find a way to save my 16-bit images to videos.

I tried every CV_FOURCC from this documentation. But I'm not sure if it's really a codec problem.

PS: I know it's possible to save them as separate 16-bit image-files, but I find the video solution cleaner.

Fei
  • 1,187
  • 1
  • 16
  • 35

4 Answers4

1

OPencv should support 16 bit FFMPEG as part of #12284.

https://github.com/opencv/opencv/pull/12284

Mat frame, frame_split[3];
VideoWriter 8_bit_vid,16_bit_vid;


//for lossless, use 'F''F''V''1', for lossy with good compression, //'X''2''6''4' 

//For 8bit writing

8_bit_vid.open("8_bit_video.avi",('F','F','V','1'),30,[rows,cols],true);

frame_split[0]= Mat Red_channel([rows,cols],CV8_UC1);
frame_split[1]= Mat Green_channel([rows,cols],CV8_UC1);
frame_split[2]= Mat Blue_channel([rows,cols],CV8_UC1);

merge(frame_split,3,frame);

8_bit_vid.write(frame);
8_bit_vid.release();



//For 16bit writing

16_bit_vid.open("16_bit_video.avi",('F','F','V','1'),30,[rows,cols],true);

frame_split[0]= Mat Red_channel([rows,cols],CV16_UC1);
frame_split[1]= Mat Green_channel([rows,cols],CV16_UC1);
frame_split[2]= Mat Blue_channel([rows,cols],CV16_UC1);

merge(frame_split,3,frame);

16_bit_vid.write(frame);
16_bit_vid.release();

Hope this helps

  • **Note**: At the time of this writing the current release of OpenCV (4.2.0) FFMPEG video writer [does NOT support 16 bit video](https://github.com/opencv/opencv/blob/90a4d67e8def9250a2c5250d3f439d25b5e164e2/modules/videoio/src/cap_ffmpeg.cpp#L144). – mattdibi Mar 05 '20 at 15:25
  • In the end this was added by [pull request #22894](https://github.com/opencv/opencv/pull/22894) for OpenCV 4.7.0; the code needed for this seems to be somewhat different to what is shown in this answer, see also https://stackoverflow.com/a/76509662 – Marcono1234 Jun 19 '23 at 19:52
1

I am not aware of a codec which supports 16-bit grayscale images, but I only use OpenCV ffmpeg support, so I could be wrong. This thread seems to support my theory that ffmpeg does not do 16-bit video (there is one message stating it does, but is inaccessible).

Michal Kottman
  • 16,375
  • 3
  • 47
  • 62
1

How about writing the raw image data without compression or formatting using simple file I/O operations? I'm sure this will give you whatever bits image file you want:)

james
  • 1,107
  • 14
  • 29
  • Yes, this is one obvious solution, but not really the answer to my question. And I'm aware of other possibilities. ;) I'm just eager to know why there is no function to write 16-bit videos in OpenCV. Is it because there is no video hardware supporting it? – Fei Feb 16 '12 at 16:15
  • 2
    The available codec in OpenCV does not support 16-bit videos I/O. It would take you lots of time and efforts to find a solution for this, or even end up with nothing. Writing files directly is straight forward and actually needs similar lines of code to implement. Plus, even there is a way in OpenCV to give you a decent way to write video, most likely you will choose a video codec with no compression (to avoid data loss), that is the same as writing the raw data to disk with some file header. – james Feb 16 '12 at 16:43
  • 1
    There is another walk around that you can try converting 16 bits image to 24 bits and treat it as a 3 channels image with each channel 8 bits. Remember to modify the image header to accommodate 8 bit and 3 channels. Then OpenCV video I/O function may work for you. Sample code : cvConvertScale(im16, im24, 1.); DISCLAIMER: I didn't try it, though. – james Feb 16 '12 at 17:18
  • I decided just to skip the saving-to-video-part and work with the original 'IplImages'. The saving-to-video-part was planned as a intermediate step, so I don't need to load some stuff every time and convert them to IplImages, and I thought there might be some easy way in OpenCV to do that. Thanks for your suggestions, the second one is quite clever and I think I will give it a shot when I passed the deadline to my current project! ;) – Fei Feb 17 '12 at 10:24
0

A work around could be to record two 8-bit grayscale videos at the same time. The first one can use the first 8 bits of the 16-bit number as pixels and the other use the last 8 bits.

Another option would be to record a colored image and in a similar fashion set the blue channel to be the first 8-bits and the green channel to the last 8-bits. You can just ignore the red channel maybe set it to 0.

You can then play back the two or single color videos in synch and manipulate them back into your original 16-bit video.

David
  • 1
  • 1