Reputation: 1207
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.
Upvotes: 1
Views: 7672
Reputation: 68
Since OpenCV 4.7.0, VideoWriter
supports 16-bit grayscale videos.
Short C++ example of the VideoWriter definition with some typical parameters:
#include <opencv2/videoio.hpp>
cv::VideoWriter video;
Size frameSize = cv::Size(1920, 1080);
double fps = 25.0;
video.open(
"video.mkv",
cv::CAP_FFMPEG,
cv::VideoWriter::fourcc('F', 'F', 'V', '1'),
fps,
frameSize,
{
cv::VideoWriterProperties::VIDEOWRITER_PROP_DEPTH, CV_16UC1,
cv::VideoWriterProperties::VIDEOWRITER_PROP_IS_COLOR, false
}
);
If you're looking for a Python alternative with a little bit more explanation, see this answer.
Upvotes: 1
Reputation: 1
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.
Upvotes: 0
Reputation: 117
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
Upvotes: 2
Reputation: 1155
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:)
Upvotes: 0
Reputation: 16753
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).
Upvotes: 0