LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   difference between scanf and fgets with OpenCV (https://www.linuxquestions.org/questions/programming-9/difference-between-scanf-and-fgets-with-opencv-4175547683/)

savio 07-10-2015 08:42 AM

difference between scanf and fgets with OpenCV
 
Hi all,

I am writing an image filter in C and OpenCV but I notice that scanf and fgets produce different program's behaviours.
In fact, if I write:

Code:

#include <stdio.h>
#include <opencv/cv.h>
#include <opencv2/imgproc/imgproc_c.h>

int main() {

  char name[50];

  printf("Insert an image name: ");
  scanf("%s", name);

  IplImage* img = cvLoadImage(name, CV_LOAD_IMAGE_COLOR);
  IplImage* outimg = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);

  cvSmooth(img, outimg, CV_GAUSSIAN, 5, 5, 0, 0);
  cvSaveImage("smoothed.jpg", outimg, 0);

  cvReleaseImage(&img);
  cvReleaseImage(&outimg);

  return 0;
}

or

Code:

#include <stdio.h>
#include <opencv/cv.h>
#include <opencv2/imgproc/imgproc_c.h>

int main(int argc, char** argv) {

  IplImage* img = cvLoadImage(argv[1], CV_LOAD_IMAGE_COLOR);
  IplImage* outimg = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);

  cvSmooth(img, outimg, CV_GAUSSIAN, 5, 5, 0, 0);
  cvSaveImage("smoothed.jpg", outimg, 0);

  cvReleaseImage(&img);
  cvReleaseImage(&outimg);

  return 0;
}

the program perfectly works, whereas if I write:

Code:

#include <stdio.h>
#include <opencv/cv.h>
#include <opencv2/imgproc/imgproc_c.h>

int main() {

  char* name;

  printf("Insert an image name: ");
  name = fgets(malloc(50*sizeof(char)), 49, stdin);

  IplImage* img = cvLoadImage(name, CV_LOAD_IMAGE_COLOR);
  IplImage* outimg = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);

  cvSmooth(img, outimg, CV_GAUSSIAN, 5, 5, 0, 0);
  cvSaveImage("smoothed.jpg", outimg, 0);

  cvReleaseImage(&img);
  cvReleaseImage(&outimg);

  return 0;
}

then I have the following error:

Code:

OpenCV Error: Bad argument (Array should be CvMat or IplImage) in cvGetSize, file /opt/local/var/macports, build/_opt_mports_dports_graphics_opencv/opencv/work/opencv-2.4.11/modules/core/src/array.cpp, line 1238
The error is about the cvGetSize function, but it doesn't happen using scanf or passing parameters by command line.

Does anyone know what is the difference in "name" when I use scanf or by command line and when I use fgets instead?

thanks in advance

Guttorm 07-10-2015 08:56 AM

Hi

fgets include the \n character in the name string. Also, you should probably check that the file exists and give a better error message.

savio 07-10-2015 09:10 AM

Yes, it is true.
I modified the code as follows but I have a segmentation fault:

Code:

#include <stdio.h>
#include <opencv/cv.h>
#include <opencv2/imgproc/imgproc_c.h>

int main() {

  char* name;
  char* image;

  printf("Insert an image name: ");
  name = fgets(malloc(50*sizeof(char)), 49, stdin);
  printf("strlen(name): lu\n", strlen(name));
  strncpy(image, name, strlen(name) - 1);
  printf("Image name: s\n", image);
  printf(strlen(image): %lu", strlen(image));

  IplImage* img = cvLoadImage(name, CV_LOAD_IMAGE_COLOR);
  IplImage* outimg = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);

  cvSmooth(img, outimg, CV_GAUSSIAN, 5, 5, 0, 0);
  cvSaveImage("smoothed.jpg", outimg, 0);

  cvReleaseImage(&img);
  cvReleaseImage(&outimg);

  return 0;
}

The segmentation fault should be in correspondance of strncpy, is necessary to allocate memory for its first parameter?

Guttorm 07-10-2015 09:28 AM

Hi

Yes, you don't allocate any memory for image before you use it. But why copy it? You could remove the last \n with something like this:

Code:

size_t len = strlen(name);
if (len != 0 && name[len-1] == '\n') {
  name[--len] = '\0';
}


ron7000 07-14-2015 01:11 PM

fgets returns the number of characters read, it looks like your use of it is incorrect.
consider this
Code:

# define MAX_STR_LEN  50

int main( void )
{

  char* name;
  char namestatic[ MAX_STR_LEN ];
  size_t  n_characters;
  size_t  name_size_bytes;
  int name_length;

  name_size_bytes = 50 * sizeof( char );
  name = (char *) malloc( name_size_bytes );
  if ( name == NULL )
  {
      printf("error: malloc returned null for name\n");
  }

  printf("Insert an image name: ");
  fflush( stdout );  /* there is no /n is above printf */


  /* your way */
  n_characters = fgets( name, name_size - 1, stdin );

  /* alternative way, why use malloc if small string size? */
  n_characters = gets( namestatic, MAX_STR_LEN - 1, stdin );

  if ( n_characters == 0 )
  {
    printf("problem with fgets reading name\n");
  }

  name_length = strlen( name );

  /* the following gets rid of the \n that gets captured with fgets */

  name[name_length - 1] = '\0';  /* write over the /n with null character */
  name_length = strlen( name );  /* update name_length */

  /* other stuff */

  return 0
}

not sure why you were using the character string called 'image'


All times are GMT -5. The time now is 12:45 PM.