2

I have implemented the following code to perform filter2D on a matrix. After I compiled the program it returns Segmentation fault error. In this program, I want to assign an input array in the program (don't want to load images). then perform a filter which is assigned inside the program to measure the time of the filter2D function for different matrices and kernels at runtime.

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>

using namespace std;
using namespace cv;

int main(){

    //Picture size for input and output are the same
    int Pxsize = 128;
    int Pysize = Pxsize;

    //Kernel size
    int Kxsize = 3;
    int Kysize = Kxsize;

    //filter arguments
    Point anchor;
    double delta;
    int ddepth;

    //name for out put
    char window_name[32] = "filter2D Demo";


    Mat input[128][128];
    Mat output[128][128];
    Mat kernel[3][3];

    // Initialize arguments for the filter
    anchor = Point( -1, -1 );
    delta = 0;
    ddepth = -1;

    int i,j;
    //assign data between 0 and 255 to the input matrix
    for (i=0; i<Pxsize; i++)
        for (j=0; j<Pysize; j++)
            input[i][j]=(i*j)%255;

    //assign data to the kernel
    //assign data between 0 and 255 to the input matrix
    for (i=0; i<Kxsize; i++)
        for (j=0; j<Kysize; j++)
            kernel[i][j]=1;

    //the problem is here:
    filter2D((InputArray) input,  (OutputArray) output, ddepth , ( InputArray) kernel, anchor, delta, BORDER_DEFAULT );
    namedWindow( window_name, CV_WINDOW_AUTOSIZE );
    imshow( window_name, (OutputArray) output );


    return 0;
}

the output is:

Segmentation fault


------------------
(program exited with code: 139)
Press return to continue

I used this command for gcc 6.2.0 compiler in Linux mint

g++ -Wall -Wextra -Werror -pedantic -I/usr/local/include/opencv -I/usr/local/include/opencv2 -L/usr/local/lib/ -g -o "opencv"  "opencv.cpp"  -lopencv_core -lopencv_imgproc -lopencv_highgui -lopencv_ml -lopencv_video -lopencv_features2d -lopencv_calib3d -lopencv_objdetect -lopencv_contrib -lopencv_legacy -lopencv_stitching

Compilation finished successfully

Thanks in advance

Amiri
  • 2,417
  • 1
  • 15
  • 42
  • 1
    `Mat input[Pxsize][Pysize];Mat output[Pxsize][Pysize];Mat kernel[Kxsize][Kysize];` -- This is not valid C++. Arrays in C++ are to be declared using the sizes as constants, not variables. – PaulMcKenzie Mar 31 '17 at 22:24
  • "Compilation finished successfully" this is implied by having a program that can raise a segfault. All it means is the program's syntax is correct. It doesn't mean the programs logic is any good. – user4581301 Mar 31 '17 at 22:24
  • @PaulMcKenzie, I use that too. It's not the problem. – Amiri Mar 31 '17 at 22:26
  • Recommend adding -Wall -Wextra -Werror -pedantic to your command line to see if the compiler can catch other stuff you should be careful of. – user4581301 Mar 31 '17 at 22:26
  • @FackedDeveloper -- It is not valid C++ syntax. You are using an extension called *Variable Length Arrays*, and you are possibly blowing out the stack by declaring them within `main`, – PaulMcKenzie Mar 31 '17 at 22:27
  • @user4581301 Still Compilation finished successfully – Amiri Mar 31 '17 at 22:28
  • Doesn't matter if compilation finishes successfully. [Look at the warnings](http://rextester.com/JETQ18916). Using VLA's is an easy way to blow out the stack if they're local variables, and your dimensions are too big. – PaulMcKenzie Mar 31 '17 at 22:32
  • @PaulMcKenzie, I updated the question they are not the problem, I knew this is not the array syntax I program in C but this time I'm using g++ and I saw it accepted the variable array! – Amiri Mar 31 '17 at 22:32
  • The problem is in the filter2D and other openCV's function. it seems my logic is not OK with openCV – Amiri Mar 31 '17 at 22:34
  • @FackedDeveloper `sizeof(Mat) * 32777` gives you what value? Whatever that is, that is probably what your stack needs to have space for, in bytes. In other words, a *stack overflow*. – PaulMcKenzie Mar 31 '17 at 22:34
  • Mat input[128][128]; does this really work? Isnt this an array of 128*128 Mat objects instead of a single 2D Mat? If it does work, what's the element type of the mat? – Micka Mar 31 '17 at 22:35
  • @Paul, it returs : `3145728` – Amiri Mar 31 '17 at 22:37
  • 1
    instead it is typically used as cv::Mat input = cv::Mat(sizeY, sizeX, CV_8UC1); for single channel grayscale images. – Micka Mar 31 '17 at 22:38
  • @FackedDeveloper And you have a 3 megabytes of memory available for local storage, i.e. a stack of that size? Most programs default to have a max of 1 megabyte of stack space. – PaulMcKenzie Mar 31 '17 at 22:38
  • `(InputArray) input` the c-style casting is hiding the errors. that kind of cast completely switches off the type checking. It tells the compiler, "Trust me. I'm right." And after that you sure as heck better be right. – user4581301 Mar 31 '17 at 22:38
  • @Paul, I moved to outside of the main which I think it uses heap space, it still returns that error. – Amiri Mar 31 '17 at 22:41
  • @FackedDeveloper Yes, get rid of all of those casts. Recompile your code. What compiler errors do you get? Whatever they are, don't hide them by casting. – PaulMcKenzie Mar 31 '17 at 22:41
  • 1
    @Micka, It was the problem, but I cannot assign them as input [ 128*128]. how should I fill them ? – Amiri Mar 31 '17 at 22:44
  • @paul, It returns `opencv.cpp:56:77: error: invalid initialization of reference of type ‘cv::InputArray {aka const cv::_InputArray&}’ from expression of type ‘cv::Mat*’` – Amiri Mar 31 '17 at 22:46
  • If you want, answer this question then I will accept the answer. – Amiri Mar 31 '17 at 22:47
  • @Micka, what do you mean about ddepth. now my program works! but it seems I'm missing something. It's not correct – Amiri Mar 31 '17 at 23:09
  • @Micka, could you take a look at [this question](http://stackoverflow.com/questions/42987554/2d-convolution-using-opencv-in-c) I wanted to do the same and now My filter does not work! – Amiri Mar 31 '17 at 23:11
  • @FackedDeveloper -- So the error is legitimate and you should fix it by understanding what it means. A `cv::_InputArray` is not a `cv::Mat*`, and there is no conversion operator, constructor, or assignment operator that knows how to turn a `cv::Mat*` into a `cv::_InputArray`. Casting does not convert. – PaulMcKenzie Apr 01 '17 at 00:46
  • @PaulMcKenzie, Yes I fixed that – Amiri Apr 01 '17 at 01:58

1 Answers1

1

According to the comments, the problem has been found! It is because of casting the Mat object to InputArray and OutputArray in filter2D function. I changed the implementation to the following program and it works.

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <time.h>

//Picture size for input and output are the same
#define MAX1 4096

#define Pxsize MAX1
#define Pysize Pxsize

//Kernel size
#define Kxsize 9
#define Kysize Kxsize
//number of iterations
#define NUM_LOOP 10000

using namespace std;
using namespace cv;

unsigned short int A[Pxsize][Pysize];
unsigned short int B[Pxsize][Pysize];
unsigned short int K[Kxsize][Kysize];

// measuring the time
double pTime = 0, mTime = 10; // to indicate how much program time is (pTime) and how much i want to wait (mTime) 
struct timespec start;


int main(){
    //singleCore
    struct timespec tStart, tEnd;//used to record the processiing time
    double tTotal , tBest=10000;//minimum of toltal time will asign to the best time
    int w=0;

    //filter arguments
    Point anchor;
    double delta;
    int ddepth;

    //assign data between 0 and 255 to the input matrix
    int i,j;
    for (i=0; i<Pxsize; i++)
        for (j=0; j<Pysize; j++)
            A[i][j] = (i+j)%255;

    //assign data to the kernel
    //assign data between 0 and 255 to the input matrix
    for (i=0; i<Kxsize; i++)
        for (j=0; j<Kysize; j++)
            K[i][j]=1;

    cv::Mat input = cv::Mat(Pxsize, Pysize, CV_8UC1, A);
    cv::Mat kernel = cv::Mat::ones(Kxsize, Kysize, CV_8UC1);

    //name for out put

    // Initialize arguments for the filter
    anchor = Point( -1, -1 );
    delta = 0;
    ddepth = -1;

    do{// this loop repeat the body to record the best time
        clock_gettime(CLOCK_MONOTONIC,&tStart);

        //the problem is here:
        filter2D( input,   output, ddepth ,  kernel, anchor, delta, 1 );

        clock_gettime(CLOCK_MONOTONIC,&tEnd);
        tTotal = (tEnd.tv_sec - tStart.tv_sec);
        tTotal += (tEnd.tv_nsec - tStart.tv_nsec) / 1000000000.0;

        if(tTotal<tBest)
            tBest=tTotal;
        pTime += tTotal;
    } while(w++ < NUM_LOOP && pTime < mTime);

    //cout<<" "<< input<<endl;
    //cout<<" "<< output<<endl;
    printf("\nThe best time: %f sec in %d repetition for %dX%d matrix for %d, %d kernel \n",tBest,w, Pxsize, Pysize, Kxsize, Kysize);

    return 0;
}
Amiri
  • 2,417
  • 1
  • 15
  • 42