Sincerely I can't find any difference. Key points:
- the FOURCC for uncompressed video is 0 (zero)
- the videofile should be created using same FPS as grabbing
- the videofile must be gray or color as grabbing
EDIT: adding details
With fourcc=0
OpenCV doesn't use codec and stores video as frame sequence without any compression. The test confirm this on my Win7 ? Please confirm on your Mac.
Using fourcc='raw '
you are selecting a QuickTime codec (may be is Still-Image Formats ?) that could have different byte per pixel and performs some TemporalCompression... Only info I've found is The Raw Compressor is simply a conversion program that increases (pads) or reduces (decimates) the number of bits in a pixel... in this case, storing to "raw " and restoring to BGR could produce some artefacts !
Fps should not have any effect on frame quality, just change overall duration/speed in the output video file. If you grab at 20fps but create the video with fps=10 you will have slow motion at 1/2 of speed. That's why storing fps should be same as grabbing fps.
Anyway to reduce all possible variable during test I suggest to use same fps for grab and store.
Finally, if you need of 100% quality I suggest to use fourcc=0 or some LossLess codec available on Mac.
below is my test code:
/**
\brief Check for difference in frame with VideoCapture and VideoWriter using RAW encoding
*/
int VideoRawReadWriteTest()
{
std::vector<cv::Mat> framebuffer;
cv::VideoCapture cap(0); // open the default camera
if (!cap.isOpened()) // check if we succeeded
return -1;
double fps = 20;
cap.set(CV_CAP_PROP_FPS,fps); // set wanted fps
fps = cap.get(CV_CAP_PROP_FPS); // <<<<<< GET GRABBING FPS (IF IT'S WORK)
cv::namedWindow("frame");
cv::Mat frame;
cap >> frame; // get a new frame from camera
cv::VideoWriter outputVideo;
std::string VideoName = "../bin/test_raw.avi";
int codec = 0;// <<<<<<<<<<< 100% UNCOMPRESSED CODEC REQUIRES FOURCC=0
bool isColor = (frame.type() == CV_8UC3); //<<<<<<<<<<< GRAY OR COLOR VIDEO FILE ?
outputVideo.open(VideoName, codec, fps, frame.size(), isColor);
if (!outputVideo.isOpened())
{
std::cout << "Could not open the output video for write: " << VideoName << std::endl;
return -1;
}
//--------------------------
//GRAB 10 FRAMES FROM CAMERA
int cc;
for (cc = 0; cc<10; cc++)
{
framebuffer.push_back(cv::Mat()); //Create a new empty Mat
cap >> framebuffer.back(); // grab directly into the buffer
if (framebuffer.back().empty())
{
std::cout << std::endl << "ERROR:Empty frame received!";
break;
}
outputVideo << framebuffer.back(); //save the frame into the videofile
cv::imshow("frame", framebuffer.back());
if (cv::waitKey(1) >= 0) break;
}
outputVideo.release();
cap.release();
// ---------------------
// TEST FOR DIFFERENCE
cap.open(VideoName); // open the videofile
if (!cap.isOpened()) // check if we succeeded
return -1;
Mat diff;
for (cc = 0; cc < framebuffer.size(); cc++)
{
cap >> frame; //get a frame from the videofile
if (frame.empty())
{
std::cout << std::endl << "ERROR:Empty frame in file!";
break;
}
//check for difference
cv::absdiff(frame, framebuffer[cc], diff); //dst(i) = saturate( abs( src1(i) - src2(i) ))
if (frame.type() == CV_8UC3)
{
cvtColor(diff, diff, CV_BGR2GRAY);
}
/* show the difference image
normalize ...
(more)
In your testCode, I don't think that raw or tiff are valid fourcc code.
You could try Huffman Lossless Codec (HFYU) (check if you have the codec on your computer before) or save each frame of your video to a list of PNG images and then use ffmpeg to create a lossless video.
As @Eduardo said I think you have to check if you can use this encoder. may be you can use videoCapture::get(CV_CAP_PROP_FOURCC) to check which codec is used
I tried all available codecs on my MAC (~24). Including raw. the results differ e little bit, but none is perfect.