OpenCV load image/video from stdin

opencv

Solution

the following reads a jpeg sequence from stdin frame by frame. examples:

ffmpeg

ffmpeg -i input.mp4 -vcodec mjpeg -f image2pipe -pix_fmt yuvj420p -r 10 -|program.exe

mencoder

mencoder input.mp4 -nosound -ovc lavc -lavcopts vcodec=mjpeg -o -|program.exe

curl

curl "http://10.10.201.241/mjpeg/video.cgi&resolution=320x240"|program.exe

code

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;

#if defined(_MSC_VER) || defined(WIN32)  || defined(_WIN32) || defined(__WIN32__) \
    || defined(WIN64)    || defined(_WIN64) || defined(__WIN64__)
# include <io.h>
# include <fcntl.h>
# define SET_BINARY_MODE(handle) setmode(handle, O_BINARY)
#else
# define SET_BINARY_MODE(handle) ((void)0)
#endif

#define BUFSIZE 10240
int main ( int argc, char **argv )
{

    SET_BINARY_MODE(fileno(stdin));
    std::vector<char> data;
    bool skip=true;
    bool imgready=false;
    bool ff=false;
    int readbytes=-1;
    while (1)
    {   
        char ca[BUFSIZE];
        uchar c;
        if (readbytes!=0)
        {
            readbytes=read(fileno(stdin),ca,BUFSIZE);
            for(int i=0;i<readbytes;i++)
            {
                c=ca[i];
                if(ff && c==(uchar)0xd8)
                {
                    skip=false;
                    data.push_back((uchar)0xff);
                }
                if(ff && c==0xd9)
                {
                    imgready=true;
                    data.push_back((uchar)0xd9);
                    skip=true;
                }
                ff=c==0xff;
                if(!skip)
                {
                    data.push_back(c);
                }
                if(imgready)
                {
                    if(data.size()!=0)
                    {
                        cv::Mat data_mat(data);
                        cv::Mat frame(imdecode(data_mat,1));

                        imshow("frame",frame);
                        waitKey(1);
                    }else
                    {
                        printf("warning");
                    }
                    imgready=false;
                    skip=true;
                    data.clear();
                }
            }
        }
        else
        {
            throw std::string("zero byte read");
        }
    }
}    

Problem

I am trying to read a jpg image from stdin using the following code: ``` int c,count=0; vector<uchar> buffer; //buffer for coding /* for stdin, we need to read in the entire stream until EOF */ while ((c = fgetc(stdin)) != EOF) { buffer.push_back(c); count++; } cout << "Bytes: " << count << endl; Mat im = imdecode(Mat(buffer),CV_LOAD_IMAGE_COLOR); cout << "Decoded\n"; namedWindow("image", CV_WINDOW_AUTOSIZE); imshow("image",im); cv::waitKey(0); ``` I run this in cmd: ``` OpenCVTest < thumb.jpg ``` This is what I get: ``` Bytes: 335 Decoded OpenCV Error: Bad flag (parameter or structure field) (Unrecognized or unsupported array type) in unknown function, file ..\..\..\src\opencv\modules\core\src\array.cpp, line 2482 ``` The error seems reasonable since the image is about 7 KB and but according to the counter only 335 bytes have been read. What am I doing wrong ? My ultimate goal is to read a video from stdin frame by frame. Would that be possible ? Thank you very much !

Original source