How to copy frames read by videoCapture
I"m trying to use the OpenCV VideoCapture class to read images sequentially from a specific folder, as shown in the code below, which is extracted from https://www.kevinhughes.ca/tutorials/.... The reading works just fine and I can view the video streaming of the read images (imgSrc) correctly. The problem happens when I try to copy each frame into a new Mat object using nested for loops, the new image (imgDst) is different from the original one. I attached the results of the frame below. I did try using image.clone() and it worked perfectly, however, it is not an option for me, as I need to read the image on a pixel-by-pixel basis. Is there anything I am doing wrong so that I get this weird result? I'm reading 16 bit png images, but I assume that the VideoCapture is changing this in some way, could this really be the issue ?
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void help(char** argv)
{
cout << "\nThis program gets you started reading a sequence of images using cv::VideoCapture.\n"
<< "Image sequences are a common way to distribute video data sets for computer vision.\n"
<< "Usage: " << argv[0] << " <path to the first image in the sequence>\n"
<< "example: " << argv[0] << " right%%02d.jpg\n"
<< "q,Q,esc -- quit\n"
<< "\tThis is a starter sample, to get you up and going in a copy paste fashion\n"
<< endl;
}
int main(int argc, char** argv)
{
if(argc != 2)
{
help(argv);
return 1;
}
string arg = argv[1];
VideoCapture sequence(arg);
if (!sequence.isOpened())
{
cerr << "Failed to open Image Sequence!\n" << endl;
return 1;
}
Mat imgSrc; // source image
for(;;)
{
sequence >> imgSrc;
if(imgSrc.empty())
{
cout << "End of Sequence" << endl;
break;
}
Mat imgDst = cv::Mat::zeros(cv::Size(imgSrc.size().width,imgSrc.size().height),CV_16U);
// Copying the elements of imgSrc to imgDst
uint16_t* imgSrcPtr;
uint16_t* imgDstPtr;
for(int i = 0; i < imgSrc.rows; i++)
{
imgDstPtr = imgDst.ptr<uint16_t>(i);
imgSrcPtr = imgSrc.ptr<uint16_t>(i);
for(int j= 0; j < imgSrc.cols; j++)
imgDstPtr[j] = imgSrcPtr[j];
}
namedWindow("Source image ",WINDOW_AUTOSIZE );
namedWindow("Destination image ",WINDOW_AUTOSIZE );
imshow("Destination image ", imgDst);
waitKey(0;
return 0;
}
please check
imgSrc.type()
the output of imgSrc.type() at runtime is 16
16 == CV_8UC3
your assumption, it would be CV_16U is as wrong as the types in your for loops (please do not write code like that)
So, although my images are grayscale, the VideoCapture is reading them as if they were in color space, is there anyway to configure the VideoCapture class to read them without change ?
I converted the read frames from color to grayscale and this solved the problem. However, I would like to know whether I can read the images directly as 16-bit grayscale using videoCapture, otherwise, I'm satisfied with the answers provided so far.
Taking a look at the VideoCapture class - i would say its surprisingly not possible. I would have expected the same flags like on imread() but i didn't found anything so far. But its fine - just make an additional convert step - its not too much code(1 line) :-)
The fact is that I'm using OpenCV only to facilitate the reading and writing operations, I'm really concerned with performance issues here. So an extra conversion step will have its cost. It's really frustrating how the VideoCapture class cannot read grayscale images.
you should probably write a loop and use imread() instead, not VideoCapture
hahahahahaha.
make it work, then make it fast. in exactly that order.
(and again, NEVER write per-pixel loops, then)
Alright, I'm not really familiar with strings in c++, so can you tell me how can I format the path to my images, in order to read them in the correct order using imread function ?