ошибка сегментации (дамп ядра) при работе с opencv - PullRequest
0 голосов
/ 29 мая 2018

Я столкнулся с проблемой, пытаясь выполнить сопоставление с шаблоном, используя OpenCV в 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;
}

В качестве вывода я получаю:

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

resultgrey.size (). Width: 1216

resultgrey.size (). Height: 723

result.size (). Width: 1216

result.size (). Высота: 723

Ошибка сегментации (ядро сброшено)

Это происходит во время двойного цикла for, где либо 1, либо 0записывается в «resultrgrey», поскольку я никогда не получаю «3» в качестве вывода из cout ниже

, если я беру разные входные изображения (особенно меньшие), программа имеет тенденцию работать без этой ошибки.

Я ценю любую помощь или предложения!

Алекс

Ответы [ 2 ]

0 голосов
/ 29 мая 2018

Посмотрите на справку о Mat::at методе

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

первое измерение - это количество строк, второе - количество столбцов, поэтому вы должны изменить все строки в вашемкод с at

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

до

resultgrey.at<int>(j,i) 
0 голосов
/ 29 мая 2018

Вы пишете вне выделенного буфера из-за (1) неправильно заданных типов данных и (2) перестановки аргументов в .at, как заметил @ rafix07.

Вы создаете 8-битную матрицу (8в CV_8UC1):

Mat resultgrey(result_rows, result_cols, CV_8UC1);

, но попробуйте назначить 32-битные значения его элементам в цикле double-for:

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

Шаблонный метод cv::Mat::at вычисляет адрес(i,j) -й элемент в памяти, основанный на:

  • тип данных, указанный в экземпляре шаблона,
  • указатель на начало данных, хранящийся в экземпляре cv::Mat,
  • и шаг данных (расстояние в байтах между крайними левыми пикселями двух последовательных строк), также сохраненные в экземпляре cv::Mat.

Затем возвращается ссылка на него.Проверка скорости не производится, поэтому вы обязаны предоставить правильные аргументы.

Размер int составляет 32 бита на большинстве современных платформ, но может отличаться.

Как правило, безопаснее использовать типы из заголовка stdint.h, которые имеют явную длину и подписывают свои имена: uint8_t, int32_t и т. Д.

...