I'm successfully opening and displaying a .avi video using OpenCV and I need this to go through OpenCV because I want to learn how to make OpenCV and dlib communicate.
For my understanding, a Mat has to be converted into an array2d in order to be processed by dlib so here's my first attempt:
cv::VideoCapture cap("/home/francesco/Downloads/05-1.avi");
cv::namedWindow("UNLTD", CV_WINDOW_AUTOSIZE);
while(1)
{
cv::Mat temp;
cv_image<bgr_pixel> cimg(temp);
std::vector<rectangle> faces = detector(cimg);
cout << faces.size() << endl;
cv::imshow("UNLTD", temp);
}
This returns the error
Error detected in file /usr/local/include/dlib/opencv/cv_image.h.
Error detected in function dlib::cv_image<pixel_type>::cv_image(cv::Mat) [with pixel_type = dlib::bgr_pixel].
Failing expression was img.depth() == cv::DataType<typename pixel_traits<pixel_type>::basic_pixel_type>::depth && img.channels() == pixel_traits<pixel_type>::num.
The pixel type you gave doesn't match pixel used by the open cv Mat object.
img.depth(): 0
img.cv::DataType<typename pixel_traits<pixel_type>::basic_pixel_type>::depth: 0
img.channels(): 1
img.pixel_traits<pixel_type>::num: 3
I tried swapping bgr_pixel to rgb_pixel but without any luck.
Looking around the internet somebody mentioned that the img.depth() is zero, therefore I should use unsigned char instead of rgb_pixel.
First thing: my video is playing in colors, so it does have 3 channels, I don't understand why it should be interpreted as a 1 channel image.
The strange thing is that, making that change from rgb_pixel to unsigned char, makes the software work but ZERO faces are detected on that video stream (that is the video of a guy talking and the face on the same video is detected with no problems by dlib on python.
I don't understand what I'm doing wrong
In your code, the temp is empty because you have not fed any frame from the video capture to it. Conversion of cv::Mat to dlib::array2d is also not correct. Please see this post for more information.
You may try:
cv::VideoCapture cap("/home/francesco/Downloads/05-1.avi");
cv::namedWindow("UNLTD", CV_WINDOW_AUTOSIZE);
dlib::frontal_face_detector detector = dlib::get_frontal_face_detector();
while(1)
{
cv::Mat temp;
cap >> temp;
dlib::array2d<bgr_pixel> dlibFrame;
dlib::assign_image(dlibFrame, dlib::cv_image<bgr_pixel>(temp));
std::vector<rectangle> faces = detector(dlibFrame);
cout << faces.size() << endl;
cv::imshow("UNLTD", temp);
}
Related
I've had this issue for a long time and I'm not sure whats going on.
So i have a loop from which nextFrame is called, now the issue lies with what the imshow actually shows.
I specifically want one image every time i call cap.grab() and cap.retrieve(), but it seems to have this buffer internally in the "cap" object, so instead on getting individual instantaneous images i would get a sequence/images of images when i click through the images, then after 3/4 frames a new sequence.
How do i get single frames?
cap is a VideoCapture object, maxCount is the size of the vector.
void CamLoop::nextFrame() {
.
.
.
//if first loop fill a vector<Mat> with random Mats from camera
if (firstLoop) {
Mat buff;
cap >> buff;
for(int i = 0; i<(maxCounter); i++) {
buffer.push_back(buff);
}
}
projector.nextCode();
if (!customImages) {
cap.grab();
Mat buff;
cap.retrieve(buff);
//tried this way too
//cap >> buff;
buffer[counter] = buff;
setMouseCallback( "Camera", mouseFunc, this );
imshow("Camera", buffer[counter]);
waitKey(1);
}
.
.
.
counter++;
}
I am using Linux Mint Rosa with OpenCV 3.1.0 on Eclipse Mars
EDIT
The problem is that VideoCapture has a buffer, try this on your own computer in debug mode, the frames aren't live, how would i over come this issue?
I tried using
cap.set(CV_CAP_PROP_BUFFERSIZE,1);
but it gives me this error.
VIDEOIO ERROR: V4L2: setting property #38 is not supported
also tried
cap.set(CV_CAP_PROP_MODE,1);
but it gives me this error.
VIDEOIO ERROR: V4L2: setting property #9 is not supported
EDIT
It may be the camera with the buffer and not the VideoCapture object itself.
A slow and cheat fix may be to do
cap.open( *CAMERA_NUM* );
in the loop, this is slow but it achieves still images without the buffer.
I am using openCV 2.4.10 on visual studios 2012 express for desktop on windows 7, 32 bit operating system.
I created a function that initializes a webcam, takes an image and stores it in a matrix, and then returns the image matrix.
Mat frameCapture ()
{
Mat srcCap;
//initializes structure type of cap
VideoCapture cap(0);
if(!cap.isOpened())
{
//check for camera
cout << "No camera detected" << endl;
waitKey(10);
}
//stores next frame into matrix
cap >> srcCap;
//check to see the camera took a picture
if( srcCap.empty())
{
cout << "no data in image\n";
}
//return the image matrix
cap.release();
return srcCap;
}
int main ()
{
Mat src;
src = frameCapture();
imshow (window1, src);
waitKey(0);
}
So when running the program, it will say "no data in image" meaning that srcCap.empty() returned true and then it will throw an assertion error for the imshow function. However, the program will sometimes run and return an image successfully. Furthermore, when I incorporate the function in a loop for image processing, it will sometimes take a few pictures and then randomly spit out "no data in image" and throw the same assertion error, or it won't take the first picture at all and spits out "no data in image", throwing the same assertion error. The camera is detected every time and cap is opened; the code never says "No camera detected"
My question is what is causing cap >> srcCap to not work, is it a hardware issue? The camera i'm using is a usb 2.0 plugable microscope.
I think you that your current program just reads the first frame only. Mostly when reading the camera frame, the first frame may not contain any data.
I would suggest that you use a loop in the main() and read latter frames.
VideoCapture cap;
cap.open("Path_to_directory\\%03d.jpg");
for (int i = 0; i < number_of_frames; ++i)
{
Mat frame;
cap >> frame;
//...
}
In the line "cap >> frame;" "bad src image pointer" is printed to console. None of the following frames of video could not be retrieved.
Is there a specific property of image should have to captured with VideoCapture then retrieving to a Mat?
Probably there is, because frames could be retrieved with code above. However after I manipulated them with Gimp, then I saved with overwriting them. Their some property should be changed while overwriting, but I don't know what are those.
Thanks.
Note: OpenCV version 2.4.9
These are the steps I want this project to follow using OpenCV:
1) Capture one frame when I press the 1 key.
2) Move the webcam
3) Capture a second frame when I press the 2 key.
4) Show both images.
Here is the code I'm working with:
int main(int, char**){
VideoCapture cap(1);
Mat img1, img2;
int input;
namedWindow("Imagen 1",CV_WINDOW_AUTOSIZE);
namedWindow("Imagen 2",CV_WINDOW_AUTOSIZE);
for(;;){
input = cvWaitKey(40);
if((char) input ==27)
break;
if ((char) input == 49){
cap >> img1;
imshow("Imagen 1",img1);
}
if ((char) input == 50){
cap >> img2;
imshow("Imagen 2",img2);
}
}
return 0;
}
However, when I do run this I get the same image in both windows. Can anyone explain why this is happening? What can I do to make it work the way I have explained?
If You are working on linux, then You will have to empty the buffer from capturing device. I do it by running a separate thread that reads the frames and remembers only the last one. When I want to take a frame for further processing, I clone the one which is now remembered. But, in Your case it might be a slight overkill.
Also, You might like to do something like this instead of Your current main loop:
cv::Mat temp,img1,img2;
cv::VideoCapture cap(1);
char control=' ';
cv::namedWindow("current",CV_AUTOSIZE);
cv::namedWindow("img1",CV_AUTOSIZE);
cv::namedWindow("img2",CV_AUTOSIZE);
do{
if(49 == control){
img1=temp.clone();
cv::imshow("img1",img1);
}else if(50 == control){
img2=temp.clone();
cv::imshow("img2",img2);
}
cap>>tmp; //emptying buffer all the time
cv::imshow("current",tmp);
control=cv::waitKey(40);//if You are faster than captures fps
}while(27 != control);
You need to put the cap() call inside the loop - otherwise you only do one capture
Instead of using cap >> img1 and cap >> img2I added a Mat variable called "captura" to store the current frame and used img1 = captura.clone() and img2 = captura.clone() respectively and now it's working.
I have a grabber which can get the images and show them on the screen with the following code
while((lastPicNr = Fg_getLastPicNumberBlockingEx(fg,lastPicNr+1,0,10,_memoryAllc))<200) {
iPtr=(unsigned char*)Fg_getImagePtrEx(fg,lastPicNr,0,_memoryAllc);
::DrawBuffer(nId,iPtr,lastPicNr,"testing"); }
but I want to use the pointer to the image data and display them with OpenCV, cause I need to do the processing on the pixels. my camera is a CCD mono camera and the depth of the pixels is 8bits. I am new to OpenCV, is there any option in opencv that can get the return of the (unsigned char*)Fg_getImagePtrEx(fg,lastPicNr,0,_memoryAllc); and disply it on the screen? or get the data from the iPtr pointer an allow me to use the image data?
Creating an IplImage from unsigned char* raw_data takes 2 important instructions: cvCreateImageHeader() and cvSetData():
// 1 channel for mono camera, and for RGB would be 3
int channels = 1;
IplImage* cv_image = cvCreateImageHeader(cvSize(width,height), IPL_DEPTH_8U, channels);
if (!cv_image)
{
// print error, failed to allocate image!
}
cvSetData(cv_image, raw_data, cv_image->widthStep);
cvNamedWindow("win1", CV_WINDOW_AUTOSIZE);
cvShowImage("win1", cv_image);
cvWaitKey(10);
// release resources
cvReleaseImageHeader(&cv_image);
cvDestroyWindow("win1");
I haven't tested the code, but the roadmap for the code you are looking for is there.
If you are using C++, I don't understand why your are not doing it the simple way like this:
If your camera is supported, I would do it this way:
cv::VideoCapture capture(0);
if(!capture.isOpened()) {
// print error
return -1;
}
cv::namedWindow("viewer");
cv::Mat frame;
while( true )
{
capture >> frame;
// ... processing here
cv::imshow("viewer", frame);
int c = cv::waitKey(10);
if( (char)c == 'c' ) { break; } // press c to quit
}
I would recommend starting to read the docs and tutorials which you can find here.