0

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

2 Answers 2

1

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

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your answer! Works like a charm now!
1

Look at reference about Mat::at method

const _Tp& cv::Mat::at    ( int i0, int i1 ) const 
  Parameters  
   i0 Index along the dimension 0
   i1 Index along the dimension 1

the first dimenstion is number of rows, the second dim is number of columns, so you should change all lines in your code with at

resultgrey.at<int>(i,j) // i means col, j means row 

to

resultgrey.at<int>(j,i) 

1 Comment

Thank you for your answer! Its these careless mistakes, that sometimes just get me -.-'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.