Thread: Edge Detection Program//Segmentation fault: 11

  1. #1
    Registered User
    Join Date
    Oct 2020
    Posts
    3

    Edge Detection Program//Segmentation fault: 11

    Hi, I am new to C programming and I am writing a program to apply Sobel and binary/threshold edge detection filters to images. I was able to get the Sobel edge detection working however with the binary/threshold ones, I am getting a "Segmentation Fault:11" error message.

    I have tried debugging using print statements to see where the fault is and it occurs on lines 134-136.

    However, since I am new to C (only started learning a month ago) and do not have any prior experience with filtering, I am not sure how to exactly fix this error? Any help is appreciated!

    Here is the code I have written:
    Code:
    #include <math.h>#include <stdio.h>
    #include <stdlib.h>
    
    
    #include "iplib2New.c"
    
    
    #define n 3
    
    
    //Function prototypes
    image_ptr read_pnm(char *filename, int *rows, int *cols, int *type);
    int getnum(FILE *fp);
    void write_pnm(image_ptr ptr, char *filename, int rows, int cols, int type);
    
    
    int applyHorizontalFilter(unsigned char smallBlock[n][n], int sobelH[n][n]);
    int applyVerticalFilter(unsigned char smallBlock[n][n], int sobelV[n][n]);
    void imageAnalysis(image_ptr imagePtr, int row, int col, int width, int height, int rows, int cols, float *mean, float *sd);
    
    
    
    
    int threshold_image(unsigned char **image, int rows, int cols, float threshold, unsigned char **imageout);
    
    
    unsigned char **allocate_image(int rows, int cols);
    
    
    //argc - argument count
    //argv - stores the arguments as a string
    int main(int argc, char **argv){
        //variable declaration
        int rows, cols, type;
        int i=0, j=0, x=0, y=0, valueH = 0, valueV = 0;
        int tp;
        float mean = 0;
        float sd = 0;
    
    
    
    
        
          unsigned char **image=NULL, **imageout=NULL;
          float threshold = 1;
      
        
        
        unsigned char smallBlock[n][n];//sub block for image
    
    
        image_ptr imagePtr, imagePtr2, imagePtr3, imagePtr4, imagePtr5, imagePtr6, imagePtr7;//image pointer types
    
    
        //sobel filters
        int sobelH[3][3] = {-1, -2, -1, 0, 0, 0, 1, 2, 1}; //horizontal
        int sobelV[3][3] = {-1, 0, 1, -2, 0, 2, -1, 0, 1}; //vertical
    
    
        //checks the inputs
        if (argc != 8){
            printf("Wrong inputs: use %s infile out1 out2 out3 \n", argv[0]);
            return 0;
        }
        else{
        imagePtr = read_pnm(argv[1], &rows, &cols, &type);//pointer to access the whole image
    
    
        printf("\nYour image was read successfully!\n");
        printf("Image information: rows = %d, cols = %d, type = %d\n", rows, cols, type);
        printf("\n");
        
        //spaces for output images
        unsigned char image2[rows][cols];
        unsigned char image3[rows][cols];
        unsigned char image4[rows][cols];
        unsigned char image5[rows][cols];
        unsigned char image6[rows][cols];
        unsigned char image7[rows][cols];
        
        //applies the horizontol edge filter
        for(i=0; i<rows; i++){//height of the image
            for(j=0; j<cols; j++){//width of the image
                for(y=0; y<n; y++){//width of the sub-block
                    for(x=0; x<n; x++){//height of the sub-block
                        smallBlock[x][y]=imagePtr[(i+x)*cols+(j+y)];
                    }
                }
                valueH = applyHorizontalFilter(smallBlock, sobelH);
                image2[i][j] = valueH;
            }
        }
        
        //applies the vertical edge filter
        for(i=0; i<rows; i++){//height of the image
            for(j=0; j<cols; j++){//width of the image
                for(y=0; y<n; y++){//width of the sub-block
                    for(x=0; x<n; x++){//height of the sub-block
                        smallBlock[x][y]=imagePtr[(i+x)*cols+(j+y)];
                    }
                }
                valueV = applyVerticalFilter(smallBlock, sobelV);
                image3[i][j] = valueV;
            }
        }
        
        //applies both vertical and horizontal filters to the image
        for(i=0; i<rows; i++){//height of the image
            for(j=0; j<cols; j++){//width of the image
                for(y=0; y<n; y++){//width of the sub-block
                    for(x=0; x<n; x++){//height of the sub-block
                        smallBlock[x][y]=imagePtr[(i+x)*cols+(j+y)];
                    }
                }
                valueV = applyVerticalFilter(smallBlock, sobelV);
                valueH = applyHorizontalFilter(smallBlock, sobelH);
                image4[i][j] = valueV + valueH;
            }
        }
        tp = 5;
    
    
        imagePtr2 = (image_ptr)image2;
        imageAnalysis(imagePtr2, 0, 0, rows, cols, rows, cols, &mean, &sd);
        
            threshold = mean + sd;
            printf("The overall mean of the image with horizontal filter is: %6.2f\n", mean);
            printf("The overall standard deviation of the image with horizontal filter is: %6.2f\n", sd);
            printf("\n");
        
        imagePtr3 = (image_ptr)image3;
        imageAnalysis(imagePtr3, 0, 0, rows, cols, rows, cols, &mean, &sd);
        printf("The overall mean of the image with vertical filter is: %6.2f\n", mean);
        printf("The overall standard deviation of the image with vertical filter is: %6.2f\n", sd);
        printf("\n");
            
            
        imagePtr4 = (image_ptr)image4;
        imageAnalysis(imagePtr4, 0, 0, rows, cols, rows, cols, &mean, &sd);
        printf("The overall mean of the image with both the horizontal and vertical filter is: %6.2f\n", mean);
        printf("The overall standard deviation of the image with both the horizontal and vertical filter is: %6.2f\n", sd);
        printf("\n");
            
    
    
           
        //binary images
            imagePtr5 = threshold_image(**image2, rows, cols, 1, image5);
            imagePtr6 = threshold_image(**image3, rows, cols, 1, image6);
            imagePtr7 = threshold_image(**image2, rows, cols, 1, image7 );
     
        
        // imageAnalysis(imagePtr5, 0, 0, rows, cols, rows, cols, &mean, &sd);
        //printf("The overall mean of the image with a binary horizontal filter is: %6.2f\n", mean);
       // printf("The overall standard deviation of the image with a binary horizontal filter is: %6.2f\n", sd);
       // printf("\n");
    
    
      //  imagePtr6 = (image_ptr)image6;
        //imageAnalysis(imagePtr6, 0, 0, rows, cols, rows, cols, &mean, &sd);
        //printf("The overall mean of the image with a binary vertical filter is: %6.2f\n", mean);
        //printf("The overall standard deviation of the image with a binary vertical filter is: %6.2f\n", sd);
       // printf("\n");
            
       // imagePtr7 = (image_ptr)image7;
        //imageAnalysis(imagePtr7, 0, 0, rows, cols, rows, cols, &mean, &sd);
        //printf("The overall mean of the image with a binary horizontal and vertical filter is: %6.2f\n", mean);
       // printf("The overall standard deviation of the image with a binary horizontal and vertical filter is: %6.2f\n", sd);
       // printf("\n");
            
        
        write_pnm(imagePtr2, argv[2], rows, cols, tp);//creates the image with just a horizontal filter
        write_pnm(imagePtr3, argv[3], rows, cols, tp);//creates the image with just a vertical filter
        write_pnm(imagePtr4, argv[4], rows, cols, tp);//creates the image with both the horizontal and vertical filters
        
        //unfinished binaey image outputs
        write_pnm(imagePtr5, argv[5], rows, cols, tp);//creates the image with a binary horizontal filter
        write_pnm(imagePtr6, argv[6], rows, cols, tp);//creates the image with a binary vertical filter
        write_pnm(imagePtr7, argv[7], rows, cols, tp);//creates the image with a binary horizontal and vertical filter
        }
        return 0;
    }
    
    
    //methods
    int applyHorizontalFilter(unsigned char smallBlock[n][n], int sobelH[3][3]){
        int x = 0;
        int y = 0;
        int pixelValueH = 0;
       // unsigned char filtered_block[3][3];
    
    
        for(x = 0; x<3; x++){
            for(y=0; y<3; y++){
                pixelValueH += sobelH[x][y]*smallBlock[x][y];
            }
        }
        return abs(pixelValueH);
    }
    
    
    int applyVerticalFilter(unsigned char smallBlock[n][n], int sobelV[3][3]){
        int x = 0;
        int y = 0;
        int pixelValueV = 0;
       // unsigned char filtered_block[3][3];
    
    
        for(x = 0; x<3; x++){
            for(y=0; y<3; y++){
                pixelValueV += sobelV[x][y]*smallBlock[x][y];
            }
        }
        return abs(pixelValueV);
    }
    
    
    //analyzes images to get their mean and standard deviation
    void imageAnalysis(image_ptr imagePtr, int row, int col, int width, int height, int rows, int cols, float *mean, float *sd){
        float sum = 0;
    
    
        //calculate the sum
        for(int i=0; i<height; i++){
            for(int j=0; j<width; j++){
                sum += imagePtr[(row + i)*rows + col + j];
            }
        }
        *mean=sum/(width*height);
        sum = 0;
    
    
        //calculates the standard deviation
        for(int i=0; i<height; i++){
            for(int j=0; j<width; j++){
                sum += pow(imagePtr[(row + i)*rows + col + j]-*mean, 2);
            }
        }
        sum = 1.0/(width*height-1.0)*sum;
        *sd = sqrt(sum);
      }
    
    
    
    
    int threshold_image(unsigned char **image, int rows, int cols, float threshold,unsigned char **imageout){
       unsigned char **imagetmp=NULL;
       int r, c;
    
    
           // Allocate memory for the thresholded image.
        if((imagetmp = allocate_image(rows, cols)) == NULL) return(0);
        *imageout = *imagetmp;
    
    
    
    
       for(r=0;r<rows;r++){
          for(c=0;c<cols;c++){
             if(image[r][c] < threshold) imagetmp[r][c] = 0;
             else imagetmp[r][c] = 255;
          }
       }
    
    
       return(1);
    }
    
    
    
    
    unsigned char **allocate_image(int rows, int cols)
    {
       unsigned char **image=NULL;
       int r, br;
       
       //Allocate an array of pointers of type (unsigned char *). The array is
       allocated to have a length of the number of rows.
    
    
       if((image = (unsigned char **) calloc(rows, sizeof(unsigned char *)))==NULL){
          fprintf(stderr, "Error allocating the array of pointers in allocate_image().\n");
       }
        return((unsigned char **)NULL);
    }

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,644
    Can you post the full code? In particular, iplib2New.c
    Attaching an input image (in the correct format) would be useful, too.
    Also, you should respond to hamster_nz who responded to your last post.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  3. #3
    Registered User
    Join Date
    Oct 2020
    Posts
    3
    Yes sorry! I forgot it utilized another code for a second!
    Code:
    /*************************************************************************** * File: iplib.c                                                           *
     *                                                                         *
     * Desc: general routines for reading and writing ppm files.               *
     * Modified from: Crane R, "A simplified approach to image processing",1997*
     ***************************************************************************/
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include "iplib2New.h"
    
    
    int ROWS, COLS, TYPE;
    
    
    /***************************************************************************
     * Func: read_pnm                                                          *
     *                                                                         *
     * Desc: reads a portable bitmap file                                      *
     *                                                                         *
     * Params: filename - name of image file to read                           *
     *         rows - number of rows in the image                              *
     *         cols - number of columns in the image                           *
     *         type - file type                                                *
     *                                                                         *
     * Returns: pointer to the image just read into memory                     *
     ***************************************************************************/
    
    
    image_ptr read_pnm(char *filename, int *rows, int *cols, int *type)
        {
        int i;                     /* index variable */
        int row_size;              /* size of image row in bytes */
        int maxval;                /* maximum value of pixel */
        FILE *fp;                  /* input file pointer */
        int firstchar, secchar;    /* first 2 characters in the input file */
        image_ptr ptr;             /* pointer to image buffer */
        unsigned long offset;      /* offset into image buffer */
        unsigned long total_size;  /* size of image in bytes */
        unsigned long total_bytes; /* number of total bytes written to file */
        float scale;               /* number of bytes per pixel */
    
    
    
    
        /* open input file */
         if((fp = fopen(filename, "rb")) == NULL)
        {
        printf("Unable to open %s for reading\n",filename);
        exit(1);
        }
    
    
        firstchar = getc(fp);
        secchar = getc(fp);
        printf("second char %d \n", secchar);
    
    
        if(firstchar != 'P')
        {
        printf("Sorry... This is not a PPM file!\n");
        exit(1);
        }
    
    
    
    
         *cols = getnum(fp);
         *rows = getnum(fp);
         *type = secchar - '0';
    
    
        ROWS = *rows; COLS = *cols; TYPE = *type;
    
    
        switch(secchar)
        {
        case '4':            /* PBM */
            scale = 0.125;
            maxval = 1;
            break;
        case '5':            /* PGM */
            scale = 1.0;
            maxval = getnum(fp);
            break;
        case '6':             /* PPM */
            scale = 3.0;
            maxval = getnum(fp);
            break;
        default :             /* Error */
            printf("read_pnm: This is not a Portable bitmap RAWBITS file\n");
            exit(1);
            break;
        }
    
    
        row_size = (*cols) * scale;
        total_size = (unsigned long) (*rows) * row_size;
    
    
        ptr = (image_ptr) malloc(total_size);
    
    
        if(ptr == NULL)
        {
        printf("Unable to malloc %lu bytes\n",total_size);
        exit(1);
        }
    
    
        total_bytes=0;
        offset = 0;
        for(i=0; i<(*rows); i++)
        {
        total_bytes+=fread(ptr+offset, 1, row_size, fp);
        offset += row_size;
        }
    
    
        if(total_size != total_bytes)
        {
        printf("Failed miserably trying to read %ld bytes\nRead %ld bytes\n",
            total_size, total_bytes);
        exit(1);
        }
    
    
        fclose(fp);
        return ptr;
        }
    
    
    /***************************************************************************
     * Func: getnum                                                            *
     *                                                                         *
     * Desc: reads an ASCII number from a portable bitmap file header          *
     *                                                                         *
     * Param: fp - pointer to file being read                                  *
     *                                                                         *
     * Returns: the number read                                                *
     ***************************************************************************/
    
    
    int getnum(FILE *fp)
        {
        char c;               /* character read in from file */
        int i;                /* number accumulated and returned */
    
    
        do
        {
        c = getc(fp);
        }
        while((c==' ') || (c=='\t') || (c=='\n') || (c=='\r'));
    
    
        if((c<'0') || (c>'9'))
        if(c == '#')                   /* chew off comments */
            {
            while(c == '#')
            {
            while(c != '\n')
                c = getc(fp);
            c = getc(fp);
            }
            }
        else
            {
            printf("Garbage in ASCII fields\n");
            exit(1);
            }
        i=0;
        do
        {
        i=i*10+(c-'0');         /* convert ASCII to int */
        c = getc(fp);
        }
        while((c>='0') && (c<='9'));
    
    
        return i;
        }
    
    
    /***************************************************************************
     * Func: write_pnm                                                         *
     *                                                                         *
     * Desc: writes out a portable bitmap file                                 *
     *                                                                         *
     * Params: ptr - pointer to image in memory                                *
     *         filename _ name of file to write image to                       *
     *         rows - number of rows in the image                              *
     *         cols - number of columns in the image                           *
     *         magic_number - number that defines what type of file it is      *
     *                                                                         *
     * Returns: nothing                                                        *
     ***************************************************************************/
    
    
    void write_pnm(image_ptr ptr, char *filename, int rows,
               int cols, int magic_number)
        {
        FILE *fp;             /* file pointer for output file */
        long offset;          /* current offset into image buffer */
        long total_bytes;     /* number of bytes written to output file */
        long total_size;      /* size of image buffer */
        int row_size;         /* size of row in bytes */
        int i;                /* index variable */
        float scale;          /* number of bytes per image pixel */
    
    
        switch(magic_number)
        {
        case 4:            /* PBM */
            scale = 0.125;
            break;
        case 5:            /* PGM */
            scale = 1.0;
            break;
        case 6:             /* PPM */
            scale = 3.0;
            break;
        default :             /* Error */
            printf("write_pnm: This is not a Portable bitmap RAWBITS file\n");
            exit(1);
            break;
        }
    
    
        /* open new output file */
        if((fp=fopen(filename, "wb")) == NULL)
        {
        printf("Unable to open %s for output\n",filename);
        exit(1);
        }
    
    
        /* print out the portable bitmap header */
        fprintf(fp, "P%d\n%d %d\n", magic_number, cols, rows);
        if(magic_number != 4)
        fprintf(fp, "255\n");
    
    
        row_size = cols * scale;
        total_size = (long) row_size *rows;
        offset = 0;
        total_bytes = 0;
        for(i=0; i<rows; i++)
        {
        total_bytes += fwrite(ptr+offset, 1, row_size, fp);
        offset += row_size;
        }
    
    
        if(total_bytes != total_size)
        printf("Tried to write %ld bytes...Only wrote %ld\n",
            total_size, total_bytes);
    
    
        fclose(fp);
        }
    It's basically just used to read image input and then write image out put.

  4. #4
    Registered User
    Join Date
    Sep 2020
    Posts
    425
    I suggest you turn all the errors on, and fix them all...

    Code:
     int threshold_image(unsigned char **image, int rows, int cols, float threshold, unsigned char **imageout);
         ^~~~~~~~~~~~~~~
    sobel.c:149:62: warning: passing argument 5 of ‘threshold_image’ from incompatible pointer type [-Wincompatible-pointer-types]
             imagePtr5 = threshold_image(**image2, rows, cols, 1, image5);
                                                                  ^~~~~~
    sobel.c:25:5: note: expected ‘unsigned char **’ but argument is of type ‘unsigned char (*)[(sizetype)(cols)]’
     int threshold_image(unsigned char **image, int rows, int cols, float threshold, unsigned char **imageout);
         ^~~~~~~~~~~~~~~
    sobel.c:150:37: warning: passing argument 1 of ‘threshold_image’ makes pointer from integer without a cast [-Wint-conversion]
             imagePtr6 = threshold_image(**image3, rows, cols, 1, image6);
                                         ^
    sobel.c:25:5: note: expected ‘unsigned char **’ but argument is of type ‘unsigned char’
     int threshold_image(unsigned char **image, int rows, int cols, float threshold, unsigned char **imageout);
         ^~~~~~~~~~~~~~~
    sobel.c:150:62: warning: passing argument 5 of ‘threshold_image’ from incompatible pointer type [-Wincompatible-pointer-types]
             imagePtr6 = threshold_image(**image3, rows, cols, 1, image6);
                                                                  ^~~~~~
    sobel.c:25:5: note: expected ‘unsigned char **’ but argument is of type ‘unsigned char (*)[(sizetype)(cols)]’
     int threshold_image(unsigned char **image, int rows, int cols, float threshold, unsigned char **imageout);
         ^~~~~~~~~~~~~~~
    sobel.c:151:37: warning: passing argument 1 of ‘threshold_image’ makes pointer from integer without a cast [-Wint-conversion]
             imagePtr7 = threshold_image(**image2, rows, cols, 1, image7 );
                                         ^
    sobel.c:25:5: note: expected ‘unsigned char **’ but argument is of type ‘unsigned char’
     int threshold_image(unsigned char **image, int rows, int cols, float threshold, unsigned char **imageout);
         ^~~~~~~~~~~~~~~
    sobel.c:151:62: warning: passing argument 5 of ‘threshold_image’ from incompatible pointer type [-Wincompatible-pointer-types]
             imagePtr7 = threshold_image(**image2, rows, cols, 1, image7 );
                                                                  ^~~~~~
    sobel.c:25:5: note: expected ‘unsigned char **’ but argument is of type ‘unsigned char (*)[(sizetype)(cols)]’
     int threshold_image(unsigned char **image, int rows, int cols, float threshold, unsigned char **imageout);
         ^~~~~~~~~~~~~~~
    ...

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,666
    Some thoughts.

    1. read_pnm needs to normalise the image format, so the data returned to main() always has an image in the same format.
    You can't do maths on a 1-bit per pixel image as you can on a 3-byte per pixel image.

    2. Your allocate_image always returns NULL.
    Also, on a fundamental level, a **pointer is completely different to a [][] array.
    You can't cast your way from one to the other.

    3. Beware of large arrays on the stack.
    > unsigned char image2[rows][cols];
    You have 6 of these.
    If rows * cols * 6 is in the megabytes, then there is a real risk of you blowing away your stack space.
    Besides, your PPM image format needs 3 bytes per pixel, not 1.
    So just having char isn't going to give you enough space to begin with.

    4. Beware of overflows / underflows
    > image4[i][j] = valueV + valueH;
    If you're not careful, grey-ish + grey-ish will become black-ish, not white-ish.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Issues With Edge Detection Program
    By marshie in forum C Programming
    Replies: 2
    Last Post: 11-01-2020, 02:12 PM
  2. Segmentation fault in C++ program
    By jkepler in forum C++ Programming
    Replies: 2
    Last Post: 08-29-2015, 03:41 PM
  3. Edge Detection done using processes and pipes
    By Bakenshake in forum C Programming
    Replies: 10
    Last Post: 12-04-2014, 09:14 AM
  4. Sobel Edge Detection
    By Bakenshake in forum C Programming
    Replies: 15
    Last Post: 11-23-2014, 01:44 AM
  5. Segmentation fault in my program
    By Dr.JacKaL in forum C Programming
    Replies: 4
    Last Post: 10-29-2014, 02:31 PM

Tags for this Thread