2014-02-17 3 views
0

Я новичок в C++, и у меня нет реальной идеи, почему моя программа выдает только догадки. Следующая программа внезапно начала сбой по строке 49 на линии void saveSig(cv::Mat *frame), она сама , даже не вдаваясь в функцию, она сама. Раньше все было хорошо. Программа сопечена, чтобы отслеживать человека в видео при определенных обстоятельствах, которые я не буду использовать, так как они еще не были имплементированы. Я могу только догадываться, что у меня закончилась стека, и я не уверен, почему, опять же, это может быть лук-порей, который я пропустил, или, может быть, я просто закончил стековое пространство или, может быть, это совсем другое и очень глупое.Сбой программы при объявлении функции с необработанным исключением: переполнение стека

PS: извините, если код не «хорошенький». Я действительно новичок в C++ и OpenCV, и я буду благодарен за любые комментарии о «плохой практике кодирования».

#include "myCVFunctions.h" 
#include <vector> 


#define LOADING_VIDEO_ERROR -1 
#define LOADING_BACKGROUND_IMAGE_ERROR -2 

#define FRAME_BUFFER_SIZE 10 
#define SIG_BUFFER_SIZE 6 

const cv::string g_c_videoFilePath = "res/tmp.mp4"; 
const cv::string g_c_bgFilePath = "res/bg.jpg"; 
const cv::Mat  g_c_bg = cv::imread(g_c_bgFilePath); 
const cv::Rect  g_c_entranceROIRect(869, 999, 345, 80); 
const cv::Rect  g_c_largeEntranceROIRect(869, 340, 345, 740); 
const cv::Rect  g_c_sigROI(869,539,345,541); 
cv::Mat  g_currFrameBackup; 
cv::Point g_clickCoords(-1,-1); 
cv::Rect g_markedROI; 
bool  g_trace = false; 
bool  g_personInside = false; 
bool  g_useSig = false; 
char  g_sigCount = 0; 
double  g_sig[SIG_BUFFER_SIZE]; 
double  g_newSig[SIG_BUFFER_SIZE]; 
cv::Point g_inSigHeadCoords[SIG_BUFFER_SIZE]; 
cv::Point g_inNewSigHeadCoords[SIG_BUFFER_SIZE]; 
long double av1 = 0; 
long double av2 = 0; 
double  minDiff = 9999999999.999999; 

void onMouse(int event, int x, int y, int flags, void* userdata){ 
    if(event == CV_EVENT_LBUTTONDOWN){ 
     g_clickCoords.x = x; 
     g_clickCoords.y = y; 
    } 
    if(event == CV_EVENT_MOUSEMOVE && g_clickCoords.x>=0){ 
     g_markedROI = cv::Rect(g_clickCoords, cv::Point(x,y)); 
     g_currFrameBackup.copyTo(*((cv::Mat*)userdata)); 
     cv::rectangle(*((cv::Mat*)userdata), g_markedROI, cv::Scalar(0,255,0)); 
    } 
    if(event == CV_EVENT_LBUTTONUP){ 
     g_trace = true; 
     g_useSig = true; 
     g_clickCoords = cv::Point(-1,-1); 
    } 
} 

void saveSig(cv::Mat *frame){ //the crash occurs here 
    double fftData[512*512]; 
    cv::Mat sigROI, sigHSV, resized; 
    sigROI = (*frame)(g_c_sigROI); 
    cv::cvtColor(sigROI, sigHSV, CV_BGR2HSV); 
    resized = my_cv::resize_zeros(sigHSV, cv::Size(512,512)); 
    cv::MatIterator_<cv::Vec3b> m_it = resized.begin<cv::Vec3b>(); 
    for(int i=0; m_it!=resized.end<cv::Vec3b>(); m_it++, i++){ 
     fftData[i] = (*m_it)[2]; 
    } 
    my_cv::FFTR fft = my_cv::createFFTR<double>(fftData, 512, 512, FFT_TYPE_2D); 
    //cv::flip(sigHSV, sigHSV, -1); 
    //cv::transpose(sigHSV, sigHSV); 
    //cv::flip(sigHSV, sigHSV, 0); 
    //cv::imshow("1", sigROI); 
    //cv::imshow("", sigHSV); 
    //cv::waitKey(); 
    //resized = my_cv::resize_zeros(sigHSV, cv::Size(512,512)); 
    //m_it = resized.begin<cv::Vec3b>(); 
    //for(int i=0; m_it!=resized.end<cv::Vec3b>(); m_it++, i++){ 
    // fftData[i] = (*m_it)[2]; 
    //} 
    //my_cv::FFTR fft180 = my_cv::createFFTR<double>(fftData, 512, 512, FFT_TYPE_2D); 
    my_cv::FFTR multFFT = my_cv::multFFT(fft, fft); 
    my_cv::m_reverseFFTR(multFFT, FFT_TYPE_2D); 
    if(g_useSig){ 
     g_newSig[g_sigCount] = my_cv::getFFTAverege(multFFT); 
    }else{ 
     g_sig[g_sigCount] = my_cv::getFFTAverege(multFFT); 
    } 
    g_sigCount++; 
    if(g_sigCount>=SIG_BUFFER_SIZE&&g_useSig){ 
     av1 = ((g_sig[0]+g_sig[1]+g_sig[2]+g_sig[3]+g_sig[4]+g_sig[5])/6)/1000000.0; 
     av2 = ((g_newSig[0]+g_newSig[1]+g_newSig[2]+g_newSig[3]+g_newSig[4]+g_newSig[5])/6)/1000000.0; 
     /*for(int i=0; i<SIG_BUFFER_SIZE; i++){ 
      for(int j=0; j<SIG_BUFFER_SIZE; j++){ 
       double diff = abs(g_newSig[i]-g_sig[j]); 
       minDiff = (diff<minDiff ? diff : minDiff); 
      } 
     }*/ 
     my_cv::deleteFFTR(fft); 
     //my_cv::deleteFFTR(fft180); 
     my_cv::deleteFFTR(multFFT); 
    } 
} 

void proccesFrame(cv::Mat *frame){ 
    cv::Mat grayFrame, negativeFrame, bwFrame, entranceROI; 
    negativeFrame = g_c_bg - *frame; 
    cv::cvtColor(negativeFrame, grayFrame, CV_BGR2GRAY); 
    cv::threshold(grayFrame, bwFrame, 30, 255, cv::THRESH_BINARY); 
    cv::Mat erode = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(7,7)); 
    cv::Mat dilate = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(10,10)); 
    cv::erode(bwFrame, bwFrame, erode); 
    cv::dilate(bwFrame, bwFrame, dilate); 

    entranceROI = bwFrame(g_c_largeEntranceROIRect); 
    cv::MatIterator_<uchar> m_it = entranceROI.begin<uchar>(); 
    for(g_personInside = false; m_it!=entranceROI.end<uchar>(); m_it++){ 
     if(*m_it==255){ 
      g_personInside = true; 
      break; 
     } 
    } 

    if(!g_personInside){ 
     g_trace = false; 
     g_sigCount = 0; 
     av1 = 0; 
     av2 = 0; 
     minDiff = 9999999999.999999; 
    }else{ 
     if(g_sigCount<SIG_BUFFER_SIZE){ 
      cv::Mat ROI = bwFrame(g_c_entranceROIRect); 
      cv::MatIterator_<uchar> bw_it = bwFrame.begin<uchar>(); 
      if(!g_useSig){ 
       for(int i=0; bw_it!=bwFrame.end<uchar>(); bw_it++, i++){ 
        if(*bw_it==255){ 
         g_inSigHeadCoords[g_sigCount] = cv::Point(i%bwFrame.cols, i/bwFrame.cols); 
         break; 
        } 
       } 
      }else{ 
       for(int i=0; bw_it!=bwFrame.end<uchar>(); bw_it++, i++){ 
        if(*bw_it==255){ 
         g_inNewSigHeadCoords[g_sigCount] = cv::Point(i%bwFrame.cols, i/bwFrame.cols); 
         break; 
        } 
       } 
      } 
      saveSig(frame); 
     } 
     cv::putText(*frame, "Person inside", cv::Point(20,120), CV_FONT_HERSHEY_PLAIN, 3.0, cv::Scalar(0,255,0), 2); 
     if(g_useSig&&g_sigCount>=SIG_BUFFER_SIZE){ 
      g_sig; 
      g_newSig; 
      g_sigCount++; 
      //g_trace = true; 
     } 
     if(g_trace){ 
      std::vector<std::vector<cv::Point>> contours; 
      std::vector<cv::Vec4i> hierarchy; 
      findContours(bwFrame, contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE); 
      std::vector<std::vector<cv::Point>>::iterator o_it = contours.begin(); 
      for(; o_it!=contours.end(); o_it++){ 
       std::vector<cv::Point>::iterator i_it = (*o_it).begin(); 
       for(; i_it!=(*o_it).end()-1; i_it++){ 
        cv::line(*frame, *i_it, *(i_it+1), cv::Scalar(0,255,0) , 3); 
       } 
      } 
     } 
    } 
} 

int main(int argc, char* argv[]){ 

    //init////////////////////////////////////////////////////////////////////// 
    cv::VideoCapture videoBuffer(g_c_videoFilePath); 
    if(!videoBuffer.isOpened()){ 
     std::cerr << "Can't load video please check the paths\n"; 
     return LOADING_VIDEO_ERROR; 
    } 
    if(!g_c_bg.data){ 
     std::cerr << "Can't load background image please check the paths\n"; 
     return LOADING_BACKGROUND_IMAGE_ERROR; 
    } 

    std::vector<cv::Mat> frameBuffer; 
    frameBuffer.resize(FRAME_BUFFER_SIZE); 
    const std::vector<cv::Mat>::iterator currFrame = frameBuffer.begin(); 
    const cv::string mainWindow = "Object Tracker"; 
    cv::namedWindow(mainWindow, CV_WINDOW_AUTOSIZE); 
    cv::setMouseCallback(mainWindow, onMouse, (void*)&(*currFrame)); 
    //init end///////////////////////////////////////////////////////////////////////////// 

    //video loop/////////////////////////////////////////////////////////////////////////// 
    for(char paused = 0;;){ 
     paused = (cv::waitKey(20)==' ' ? 1 : 0); 
     while(paused){ 
      cv::resize(*currFrame, *currFrame, cv::Size(900, 540)); 
      cv::imshow(mainWindow, *currFrame); 
      paused = (cv::waitKey(20)==' ' ? 0 : 1); 
     } 
     cv::Mat frame; 
     videoBuffer.read(frame); 
     frame.copyTo(g_currFrameBackup); 
     frameBuffer.pop_back(); 
     frameBuffer.insert(frameBuffer.begin(), frame); 
     std::stringstream ss; 
     ss << "Frame: " << videoBuffer.get(CV_CAP_PROP_POS_FRAMES); 
     cv::putText(*currFrame, ss.str().c_str(), cv::Point(20,70), CV_FONT_HERSHEY_PLAIN, 3.0, cv::Scalar(0,255,0), 2); 
     proccesFrame(&(*currFrame)); 
     /*if(g_personInside){ 
      cv::resize(*currFrame, *currFrame, cv::Size(900, 540)); 
      while(cv::waitKey(40)!=' ') 
       cv::imshow(mainWindow, *currFrame); 
     }*/ 
     cv::resize(*currFrame, *currFrame, cv::Size(900, 540)); 
     cv::imshow(mainWindow, *currFrame); 
    } 
    //video loop end/////////////////////////////////////////////////////////////////////// 

    return 0; 
} 

и файл "myCVFunctions.h":

#pragma once 

#include "opencv\cv.h" 
#include "opencv\highgui.h" 
#include "fftw3.h" 

#define FFT_TYPE_1D 1 
#define FFT_TYPE_2D 2 


namespace my_cv{ 

    struct myComplex{ 
     double real; 
     double imag; 
    }; 

    struct FFTR{ 
     myComplex** data; 
     int cols; 
     int rows; 
    }; 

    struct ENTROPR{ 
     double** data; 
     int cols; 
     int rows; 
    }; 

    void printFFTR(FFTR fft); 

    FFTR createFFTR(cv::Mat mGrey, int type){ 
     FFTR result; 
     result.rows = mGrey.rows, result.cols = mGrey.cols; 
     result.data = new myComplex*[result.cols]; 
     for(int i = 0; i<result.cols; i++) 
      result.data[i] = new myComplex[result.rows]; 

     fftw_complex *in, *out; 
     fftw_plan p; 

     in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * result.rows * result.cols); 
     out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * result.rows * result.cols); 
     switch(type){ 
     case FFT_TYPE_1D: 
      p = fftw_plan_dft_1d(result.rows*result.cols, in, out, FFTW_FORWARD, FFTW_ESTIMATE); 
      break; 
     case FFT_TYPE_2D: 
      p = fftw_plan_dft_2d(result.rows, result.cols, in, out, FFTW_FORWARD, FFTW_ESTIMATE); 
      break; 
     } 

     cv::MatIterator_<uchar> mGrey_it = mGrey.begin<uchar>(); 
     for(int i=0; mGrey_it != mGrey.end<uchar>(); mGrey_it++, i++){ 
      in[i][0] = *mGrey_it; 
      in[i][1] = 0; 
     } 

     fftw_execute(p); 

     for(int i=0; i<result.rows*result.cols; i++){ 
      int x = i%result.cols, y = i/result.cols; 
      result.data[x][y].real = out[i][0]; 
      result.data[x][y].imag = out[i][1]; 
     } 

     fftw_destroy_plan(p); 
     fftw_free(in); 
     fftw_free(out); 

     return result; 
    } 

    template<class T> FFTR createFFTR(const T* const mat, int cols, int rows, int type){ 
     FFTR result; 
     result.rows = rows, result.cols = cols; 
     result.data = new myComplex*[result.cols]; 
     for(int i = 0; i<result.cols; i++) 
      result.data[i] = new myComplex[result.rows]; 

     fftw_complex *in, *out; 
     fftw_plan p; 

     in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * result.rows * result.cols); 
     out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * result.rows * result.cols); 
     switch(type){ 
     case FFT_TYPE_1D: 
      p = fftw_plan_dft_1d(result.rows*result.cols, in, out, FFTW_FORWARD, FFTW_ESTIMATE); 
      break; 
     case FFT_TYPE_2D: 
      p = fftw_plan_dft_2d(result.rows, result.cols, in, out, FFTW_FORWARD, FFTW_ESTIMATE); 
      break; 
     } 

     for(int i=0; i<cols*rows; i++){ 
      in[i][0] = mat[i]; 
      in[i][1] = 0; 
     } 

     fftw_execute(p); 

     for(int i=0; i<result.rows*result.cols; i++){ 
      int x = i%result.cols, y = i/result.cols; 
      result.data[x][y].real = out[i][0]; 
      result.data[x][y].imag = out[i][1]; 
     } 

     fftw_destroy_plan(p); 
     fftw_free(in); 
     fftw_free(out); 

     return result; 
    } 

    void m_reverseFFTR(FFTR fft, int type){ 
     fftw_complex *in, *out; 
     fftw_plan p; 

     int scaleFactor = fft.cols*fft.rows; 
     in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * fft.rows * fft.cols); 
     out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * fft.rows * fft.cols); 
     switch(type){ 
     case FFT_TYPE_1D: 
      p = fftw_plan_dft_1d(fft.rows*fft.cols, in, out, FFTW_BACKWARD, FFTW_ESTIMATE); 
      break; 
     case FFT_TYPE_2D: 
      p = fftw_plan_dft_2d(fft.rows, fft.cols, in, out, FFTW_BACKWARD, FFTW_ESTIMATE); 
      break; 
     } 

     for(int j=0; j<fft.rows; j++) 
      for(int i=0; i<fft.cols; i++){ 
       int index = j*fft.cols+i; 
       in[index][0] = fft.data[i][j].real; 
       in[index][1] = fft.data[i][j].imag; 
      } 

     fftw_execute(p); 

     for(int i=0; i<fft.rows*fft.cols; i++){ 
      int x = i%fft.cols, y = i/fft.cols; 
      fft.data[x][y].real = out[i][0]/scaleFactor; 
      fft.data[x][y].imag = out[i][1]/scaleFactor; 
     } 

     fftw_destroy_plan(p); 
     fftw_free(in); 
     fftw_free(out); 
    } 

    FFTR multFFT(const FFTR fft1, const FFTR fft2){ 
     FFTR result; 
     result.cols = fft1.cols; 
     result.rows = fft1.rows; 
     result.data = new myComplex*[result.cols]; 
     for(int i=0; i<result.cols; i++) 
      result.data[i] = new myComplex[result.rows]; 
     for(int i=0; i<result.cols; i++){ 
      for(int j=0; j<result.rows; j++){ 
       result.data[i][j].real = (fft1.data[i][j].real*fft2.data[i][j].real)-(fft1.data[i][j].imag*fft2.data[i][j].imag); 
       result.data[i][j].imag = (fft1.data[i][j].real*fft2.data[i][j].imag)+(fft1.data[i][j].imag*fft2.data[i][j].real); 
      } 
     } 
     return result; 
    } 

    long double getFFTAverege(FFTR fft){ 
     long double result = 0; 
     for(int i=0; i<fft.cols; i++){ 
      long double sum=0; 
      for(int j=0; j<fft.rows; j++){ 
       sum += fft.data[i][j].real; 
      } 
      result += sum/fft.rows; 
     } 
     return result/fft.rows; 
    } 

    void deleteFFTR(FFTR fftr){ 
     for(int i=0; i<fftr.cols; i++) 
      if(fftr.data[i]) delete [] fftr.data[i]; 
     if(fftr.data) delete [] fftr.data; 
    } 

    void printFFTR(FFTR fft){ 
     for(int j=0; j<fft.rows; j++){ 
      for(int i=0; i<fft.cols; i++){ 
       printf("%f%si%f\n", fft.data[i][j].real, (fft.data[i][j].imag<0 ? "-" : "+"), abs(fft.data[i][j].imag)); 
      } 
     } 
    } 

    cv::Mat resize_zeros(const cv::Mat src, cv::Size newSize){ 
     cv::Mat srcROI, result, resultROI;  
     result.create(newSize, src.type()); 
     srcROI = src(cv::Rect(0,0,(src.cols>result.cols ? result.cols : src.cols), (src.rows>result.rows ? result.rows : src.rows))); 
     result = 0; 
     resultROI = result(cv::Rect(0,0, srcROI.cols, srcROI.rows)); 
     srcROI.copyTo(resultROI); 
     return result; 
    } 

    //otsu's threshhold 
    template<class T> T getThreshold(cv::Mat mGrey){ 
     uchar* image = mGrey.data; 
     int columns = mGrey.cols; 
     int rows = mGrey.rows; 
     const T SIGMA = 0.000001; 
     const int num_bins = 257; 
     int counts[num_bins] = {0}; 
     T p[num_bins] = {0}; 
     T mu[num_bins] = {0}; 
     T omega[num_bins] = {0}; 
     T sigma_b_squared[num_bins] = {0}; 
     int sumC; 

     // calculate histogram 
     for(int i = 0; i < rows*columns; i++) 
      counts[image[i]]++; 

     sumC = 0; 
     for(int i = 0; i < num_bins; i++) 
      sumC += counts[i]; 

     for(int i = 0; i < num_bins; i++) 
      p[i] = ((T)counts[i])/sumC; 

     mu[0] = omega[0] = p[0]; 
     for(int i = 1; i < num_bins; i++){ 
      omega[i] = omega[i-1] + p[i]; 
      mu[i] = mu[i-1] + p[i]*(i+1); 
     } 

     T mu_t = mu[num_bins-1]; 
     T maxval = -1.0; 
     for(int i = 0; i < num_bins; i++){ 
      T v = mu_t * omega[i] - mu[i]; 
      if (omega[i] > SIGMA && abs(1.0-omega[i]) > SIGMA){ 
       sigma_b_squared[i] = v*v/(omega[i]* (1.0 - omega[i])); 
       maxval = std::max(maxval,sigma_b_squared[i]); 
      } 
     } 

     // Find the location of the maximum value of sigma_b_squared. 
     // The maximum may extend over several bins, so average together the 
     // locations. 
     // If maxval == -1, sigma_b_squared is not defined, then return 0. 

     T level = 0; 
     if (maxval > 0){ 
      T idx = 0; 
      int maxNumbers = 0; 
      for(int i = 0; i < num_bins; i++){ 
       if (sigma_b_squared[i] == maxval){ 
        idx += i; 
        maxNumbers++; 
       } 
      } 
      if (maxNumbers >= 0){ 
       idx /= maxNumbers; 
       // Normalize the threshold to the range [0, 1]. 
       // level = (idx - 1)/(num_bins - 1); 
       level = idx/(num_bins - 1); 
      } 
     } 
     return level; 
    } 

} 
+0

плохой кодировка практика: течение Mat * вокруг. предпочитайте Mat & else, вы wrec havoc на внутренних refcounts и в конечном итоге с оборванными указателями (ваша проблема звучит довольно так) – berak

ответ

3
double fftData[512*512]; 

Это (вероятно) 2Мб данных, который (вероятно) слишком большой, чтобы поместиться в стеке. Самым простым способом исправить это использовать динамический массив вместо:

std::vector<double> fftData(512*512); 

В качестве альтернативы, если динамическое распределение является слишком дорогим, вы можете использовать статический или глобальный массив. Это, как правило, плохая идея, поскольку она делает функцию не реентерабельной и неудобной для использования в многопоточной программе; тем не менее, у вас уже так много глобалов, что еще один, вероятно, не повредит.

+0

Большое спасибо, что действительно была проблемой. Однако динамическое распределение стоит дорого. Насколько это плохо, если я выделил кучу, используя новый Double [512 * 512] и удалим его в конце, если функция является contineous и dosnt throw? –

+0

@ Dima: Это все еще динамическое распределение (почти) точно так же, как это делает 'vector'. Все, что вы делаете, - это отказаться от безопасности исключений, что «вектор» дает вам неэффективную выгоду. –

+0

Еще раз спасибо, переключился на статический массив, и все работает отлично (на данный момент); –

Смежные вопросы