Search code examples
opencvsegmentation-faultruntime-errorcoredump

segmentation failed (core dumped) working with opencv


I'm running into a problem, trying to perform a template matching using OpenCV on Ubuntu 18.04LTS

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

using namespace std;
using namespace cv;

int main( int argc, char** argv )
{
    int match_method =5;
    string image_window = "Source Image";
    string result_window = "Result window";
    Mat img, templ, result;

    /// Load image and template
    img = imread("./RI2.jpg", IMREAD_GRAYSCALE );
    templ = imread("./Pump2.jpg", IMREAD_GRAYSCALE );

    /// Create windows
    //namedWindow( image_window, WINDOW_AUTOSIZE );
    //namedWindow( result_window, WINDOW_AUTOSIZE );

    /// Source image to display
    Mat img_display;
    img.copyTo( img_display );

    /// Create the result matrix
    int result_cols =  img.cols - templ.cols + 1;
    int result_rows = img.rows - templ.rows + 1;
    result.create( result_rows, result_cols, CV_32FC1 );


    /// Do the Matching and Normalize
    matchTemplate( img, templ, result, match_method );
    normalize( result, result, 0, 1, NORM_MINMAX, -1, Mat() );
    Mat resultgrey(result_rows, result_cols, CV_8UC1);

    cout << "resultgrey.size().width: " << resultgrey.size().width << endl;
    cout << "resultgrey.size().height: " << resultgrey.size().height << endl;
    cout << "result.size().width: " << result.size().width << endl;
    cout << "result.size().height: " << result.size().height << endl;

    if( match_method  == 0 || match_method == 1 )
    {
        for (int i=0; i<result.size().width; i++)
        {
            for (int j=0; j<result.size().height; j++)
            {
                if (result.at<float>(i,j)>=0.1)
                {
                    resultgrey.at<int>(i,j)=0;
                }
                else
                {
                    resultgrey.at<int>(i,j)=1;

                }
            }
        }
    }


    else
    {
        for (int i=0; i<result.size().width; i++)
        {
            for (int j=0; j<result.size().height; j++)
            {
                if (result.at<float>(i,j)<=0.98)
                {
                    resultgrey.at<int>(i,j)=0;
                    //cout << "0" << endl;
                }
                else
                {
                    resultgrey.at<int>(i,j)=1;
                    //cout << "1" << endl;
                }
            }
        }
    }

    cout << "3" << endl;

    /// Localizing the objects
    vector<Point> matchLoclist;

    //cout << resultgrey << endl;
    findNonZero(resultgrey, matchLoclist);
    cout << "4" << endl;

    if (matchLoclist.size() == 0)
    {
        cout << "no matches found" << endl;
        return 0;
    }

    ///Draw Rectangles on Pumps found in the scene
    for (int i=0; i<matchLoclist.size(); i++)
    {
        //cout << "matchLoclist[i].x: "<<matchLoclist[i].x  << endl << "matchLoclist[i].y: " << matchLoclist[i].y << endl;
        rectangle( img_display, matchLoclist[i], Point( matchLoclist[i].x + templ.cols, matchLoclist[i].y + templ.rows ), Scalar::all(0), 2, 8, 0 );
        rectangle( result, matchLoclist[i], Point( matchLoclist[i].x + templ.cols, matchLoclist[i].y + templ.rows ), Scalar::all(0), 2, 8, 0 );
    }

    imshow( image_window, img_display );
    imshow( result_window, result );

    waitKey(0);
    return 0;
}

as an output i get:

xxx@ubuntu:~/Projects/Template_matching$ ./template_matching

resultgrey.size().width: 1216

resultgrey.size().height: 723

result.size().width: 1216

result.size().height: 723

Segmentation fault (core dumped)

This happens during the double for-loop where either a 1 or a 0 gets written into "resultrgrey" as I never get the "3" as an output from the cout below

if I take different input pictures (espacially smaller ones) the programm tends to run without this error.

I appreciate any help or suggestions!

Alex


Solution

  • You write outside of the allocated buffer because of (1) incorrectly specified data types and (2) swapped arguments to .at, as @rafix07 has noted.

    You create 8-bit matrix (8 in CV_8UC1):

    Mat resultgrey(result_rows, result_cols, CV_8UC1);
    

    but try to assign 32-bit values to its elements in double-for loop:

    resultgrey.at<int>(i,j)=0;
    

    Template method cv::Mat::at calculates address of the (i,j)-th element in memory, based on:

    • data type, specified in template instantiation,
    • pointer to data start, stored in the cv::Mat instance,
    • and data stride (distance in bytes between leftmost pixels of two consecutive lines), also stored in the cv::Mat instance.

    Then it returns reference to it. No checks is performed, for speed, therefore it's your responsibility to submit correct arguments.

    Size of int is 32 bits on most modern platforms, but can be differrent.

    Generally, it is safer to use types from stdint.h header, that have explicit length and sign in their names: uint8_t, int32_t, etc