1
votes

Problem description:

With the simple code I can access my internal camera webcam and also change the resolution. So displaying the frame with default resolution and with a predefined resolution (e.g., from 640x480 to 320x240, with cap.set(CV_CAP_PROP_FRAME_WIDTH,320), and FRAME_HEIGHT, 240)) – both work fine.

Using the same code with slight adaption so that it works with a Ximea camera (VideoCapture cap(CV_CAP_XIAPI)), does work for the default resolution. It is a MU9PC_MH with a default resolution of 2592x1944, so 648 x486 is the lower resolution which is required.

For a manually set resolution the displayed window/grabbed frame has the size of the default resolution (2592x1944) and shows the lower amount of pixels of the capture in the this huge display, so that the upper fifths is filled with puzzled pixels and the rest of the window is black.

This effect happens for both, C++ with VideoCapture and Mat and for C CvCaptureFromCAM and IplImage*.

When I’m using the set flag CV_CAP_PROP_XI_DOWNSAMPLING, then I can see the output image with pixels in correct order, but the display frame has still the default high resolution and the output image is shown multiple times (the factor depends on the factor I am using for downsampling).

I’m even not able to force the Mat or IplImage to a predefined size, because then an error of assertion or access violation occurs(Mat image(XRES, YRES, CV_8UC3, Scalar(0,0,255)) (frame = cvCreateImage(cvSize( XRES, YRES), IPL_DEPTH_8U,3);. I've checked through frame.type(), that the output is an CV_8UC3

What I want is a Ximea camera output of 648x486 shown in an (ideally) Mat of same size. Did anyone experience the same problem? Probably it is due to a lack in my knowledge about industrial camera configuration/development, but any help is appreciated.

Situation: Windows 7(x64) Visual Studio Professional 2012 OpenCV Version 2.4.10 compiled for x86 with following flags checked: WITH_XIMEA and WITH_OPENGL Simple VS2012 Project in x86 (both release and debug) for camera streaming and displaying of camera frame in window.

Simple Code Snippets(not mine, copied from opencv tutorials and ximea): C++-Style:

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char **argv) {
	VideoCapture cap(0); // open the default camera
	//VideoCapture cap(CV_CAP_XIAPI);  
  if(!cap.isOpened())  // check if we succeeded
        return -1;
cout<<" "<<cap.get(CV_CAP_PROP_FRAME_WIDTH)<<" "<<cap.get(CV_CAP_PROP_FRAME_HEIGHT)<<endl; //output: 640, 480
	cap.set(CV_CAP_PROP_FRAME_WIDTH,XRES);
	cap.set(CV_CAP_PROP_FRAME_HEIGHT,YRES);	
cout<<" "<<cap.get(CV_CAP_PROP_FRAME_WIDTH)<<"  "<<cap.get(CV_CAP_PROP_FRAME_HEIGHT)<<endl;  //output: 320, 240

 for(;;)
    {
        Mat frame;
        cap >> frame; // get a new frame from camera
        imshow("camera frame", frame);
    if(waitKey(30) == 27) //wait for 'esc' key press
		{
            cout << "esc key is pressed by user" << endl;
			break; 
		}
    }
    return 0;}
C-Style:

#include "cv.h" 
#include "highgui.h" 
#include <stdio.h>  
#include <iostream>

using namespace cv;
using namespace std;
// A Simple Camera Capture Framework 
int main() 
{
   CvCapture* capture = cvCaptureFromCAM( CV_CAP_XIAPI );
   if ( !capture ) {
     fprintf( stderr, "ERROR: capture is NULL \n" );
     getchar();
     return -1;
   }
cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH, 648 ); 
cvSetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT, 486 );
   // Create a window in which the captured images will be presented
   cvNamedWindow( "mywindow", CV_WINDOW_AUTOSIZE );
   // Show the image captured from the camera in the window and repeat
   while ( 1 ) {
     // Get one frame
     IplImage* frame = cvQueryFrame( capture );
cout<<cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH); //output: 648
cout<<cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT); //output: 486

cout<<frame->height<<frame->width<<endl; //output: 1944, 2592
     if ( !frame ) {
       fprintf( stderr, "ERROR: frame is null...\n" );
       getchar();
       break;
     }
     cvShowImage( "mywindow", frame );
     // Do not release the frame!
     //If ESC key pressed, Key=0x10001B under OpenCV 0.9.7(linux version),
     //remove higher bits using AND operator
     if ( (cvWaitKey(10) & 255) == 27 ) break;
   }
   // Release the capture device housekeeping
   cvReleaseCapture( &capture );
   cvDestroyWindow( "mywindow" );
   return 0;
}
2

2 Answers

1
votes

thank you karlphillip for your answer. Unfortunately, you are right that this was not an ideal way. So I take yesterday's snowy wheather and found the solution myself: There's a mistake in the resetCvImage() method of the cap_ximea.cpp.

line 207 if( (int)image.width != width || (int)image.height != height || image.frm != (XI_IMG_FORMAT)format)

has to be:

if( (int)image.width != **frame->**width || (int)image.height != **frame->**height || image.frm != (XI_IMG_FORMAT)format)
0
votes

VideoCapture::set() returns a bool to indicate the success of the method. You shouldn't let your application continue to run without checking the success/failure of this call and readjusting the size of the capture when necessary.

The fact is that some camera drivers don't accept arbitrary dimensions, and there's simply nothing you can do about it. However, you can retrieve the frame using the default size and then cv::resize() it to your needs.

It's not ideal, but it will get the job done.