程序在函数声明时崩溃,出现未经处理的异常:堆栈溢出



我是 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 pathsn";
        return LOADING_VIDEO_ERROR;
    }
    if(!g_c_bg.data){
        std::cerr << "Can't load background image please check the pathsn";
        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 "opencvcv.h"
#include "opencvhighgui.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%fn", 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; 
    }
}
double fftData[512*512];
这是(可能)

2MB的数据,(可能)太大而无法容纳在堆栈上。最简单的解决方法是改用动态数组:

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

或者,如果动态分配成本太高,则可以使用静态或全局数组。这通常是一个坏主意,因为它使函数不可重入且在多线程程序中使用起来很尴尬;但是,您已经拥有如此多的全局变量,因此再多一个可能不会受到伤害。

最新更新