Program crashes at Function declaration with Unhandled exception: Stack overflow - c++

I am new to c++ and I have no real idea why my program crashes only guesses.
The following program suddenly started to crash on line 49 at the void saveSig(cv::Mat *frame) line it self
without even steping in to the function it self.
It ran fine before.
The program soposed to track a person in a video under certain circumstances which I will not go over since they haven't been impllementet yet.
I can only guess that I have ran out of stack and I'm not sure why, again it might be a leek that I missed or maybe I just ran out of stack space or maybe it's completely something else and very stupid.
PS: sorry if the code is not "pretty" I'm really new to C++ and OpenCV and I will appreciate any comments about "bad coding practice".
#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;
}
and the "myCVFunctions.h" file:
#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;
}
}

double fftData[512*512];
That's (probably) 2MB of data, which is (probably) too big to fit on the stack. The simplest fix is to use a dynamic array instead:
std::vector<double> fftData(512*512);
Alternatively, if dynamic allocation is too expensive, you could use a static or global array. This is usually a bad idea, since it makes the function non-reentrant and awkward to use in a multi-threaded program; however, you already have so many globals that one more probably won't hurt.

Related

Corrupted memory issue when deleting allocated memory

I am trying to store a sparse vector using a bit mask. I allocate a char* to represent the bit mask. However, when I delete [] the mask, I get a memory corruption error. Upon investigation, I'm seeing that it's because I'm freeing memory that I'm not supposed to. This is confusing, since I don't see how this could be the case.
When I run this on my case, it prints out "ALLOCATED" and "DEALLOCATING" but nothing further.
void set_i_bit(char* mask, int i) {
int field_num = floor(i/8);
int bit_num = i %8;
mask[field_num] = (1 << bit_num) | mask[field_num];
}
int write_sparse_with_bitmask(vector<float> arr, ofstream* fout) {
int mx_sz = arr.size() - 1;
float tol = 0.5;
char* mask = 0;
for(int i = arr.size() -1; i>=0; i-=1) {
if (fabs(arr[i]) > tol) break;
mx_sz = i;
}
int sprse_cnt = 0;
for(int i = 0; i<=mx_sz; i+=1) {
if (fabs(arr[i]) < tol) sprse_cnt++;
}
int bitmask_sz = ceil(mx_sz/8);
if (sprse_cnt*sizeof(int16_t) + sizeof(int16_t) > bitmask_sz) {
cout<<"ALLOCATED"<<endl;
mask = new char[bitmask_sz];
for (int i =0; i<bitmask_sz; i++) mask[i] = 0;
for(int i = 0; i<=mx_sz; i+=1) {
if (fabs(arr[i]) > coef_tol) {
set_i_bit(mask, i);
}
}
}
else {
bitmask_sz = 0;
}
uint16_t sz = mx_sz + 1;
uint16_t bt_msk = bitmask_sz + 1;
char flag = 0;
if (bitmask_sz > 0) {
flag = flag | 1;
}
fout->write((char*)&sz, sizeof(uint16_t));
fout->write((char*)&flag, sizeof(char));
int w_size = sizeof(uint16_t) + sizeof(char);
if (flag & 1) {
fout->write((char*)&bt_msk, sizeof(uint16_t));
fout->write(mask, sizeof(char)*bt_msk);
cout<<"DEALLOCATING"<<endl;
delete [] mask;
cout<<"THIS DOESN'T PRINT"<<endl;
w_size += sizeof(uint16_t) + sizeof(char)*bt_msk;
}
for(int i = 0; i<=mx_sz; i+=1) {
if (fabs(arr[i]) > tol || !(flag & 1)) {
int16_t vl = arr[i];
fout->write((char*) &vl, sizeof(int16_t));
w_size += sizeof(int16_t);
}
}
return w_size;
}

Converting Caffe caffe::Datum to OpenCV cv::Mat in C++

I'm doing some debugging and so I'm dumping image files to look at the predictions and transformations.
I can create a caffe::Datum from cv::Mat:
cv::Mat matrix;
// ... initialize matrix
caffe::Datum datum;
caffe::CVMatToDatum(matrix, &datum)
but how do I create a cv::Mat from caffe::Datum? The following code gives the fatal exception "Datum not encoded":
caffe::Datum datum;
// ... initialize datum
cv::Mat matrix;
matrix = DecodeDatumToCVMat(datum, true);
You can use following functions.
cv::Mat DatumToCVMat(const Datum& datum){
int datum_channels = datum.channels();
int datum_height = datum.height();
int datum_width = datum.width();
string strData = datum.data();
cv::Mat cv_img;
if (strData.size() != 0)
{
cv_img.create(datum_height, datum_width, CV_8UC(datum_channels));
const string& data = datum.data();
std::vector<char> vec_data(data.c_str(), data.c_str() + data.size());
for (int h = 0; h < datum_height; ++h) {
uchar* ptr = cv_img.ptr<uchar>(h);
int img_index = 0;
for (int w = 0; w < datum_width; ++w) {
for (int c = 0; c < datum_channels; ++c) {
int datum_index = (c * datum_height + h) * datum_width + w;
ptr[img_index++] = static_cast<uchar>(vec_data[datum_index]);
}
}
}
}
else
{
cv_img.create(datum_height, datum_width, CV_32FC(datum_channels));
for (int h = 0; h < datum_height; ++h) {
float* ptr = cv_img.ptr<float>(h);
int img_index = 0;
for (int w = 0; w < datum_width; ++w) {
for (int c = 0; c < datum_channels; ++c) {
ptr[img_index++] = static_cast<float>(datum.float_data(img_index));
}
}
}
}
return cv_img;
}
all code :
http://lab.deepaivision.com/2017/06/opencv-mat-caffe-datum-datum-mat.html
Addition to the answer by #ttagu99 , in the float section there is a slight bug:
The line:
ptr[img_index++] = static_cast<float>(datum.float_data(img_index));
Should be in fact:
int datum_index = (c * datum_height + h) * datum_width + w;
ptr[img_index++] = static_cast<float>(datum->float_data(datum_index));
This fixes the order of writing the data to the matrix. Otherwise, you only see lines of color.

FFTW with qt C++ program crash

I try to computing fft at a vector of pixels in time from a list of images with fftw and qt,and repeat this treatement for all pixels of all images; the vector contains [pix1.1 of im1,pix1.1 of im2,...pix1.1 of imN], the problem is when number of images is big the program crashes
const int Npoints(widget.imagelistWidget->count());
fftw_complex *in, *out;
in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*Npoints);
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex)*Npoints);
double resfft;
fftw_plan p;
QList<QImage*> imageList;
QImage *imagef ;
for(int k=0;k<liste.size();k++)
{
imagef = new QImage;
imagef->load(liste[k]);
imageList.append(imagef);
}
for(int i=0;i<imagef->width();i++)
{
for(int j=0;j<imagef->height();j++)
{
for(int k=0;k<liste.size();k++)
{
imagef =imageList.at(k);
QRgb pixelfft=imagef->pixel(i,j);
double moyp= qGray(pixelfft);
in[k][0] = moyp;
in[k][1] = 0.0;
}
p = fftw_plan_dft_1d(Npoints, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
fftw_execute(p);
//resultat
QVector<qreal> realV;
QVector<qreal> imgV;
for (int s = 0; s < Npoints; s++)
{
realV.append(out[s][0]);
imgV.append(out[s][1]);
}
for(int l=0;l<liste.size();++l)
{
resfft = sqrt((realV[l] * realV[l]) + (imgV[l] * imgV[l]));
imagef=imageList.at(l);
imagef->setPixel(i,j,qGray(qRgb(resfft,resfft,resfft)));
}
}
}
I think this is what #bibi's comment was getting at, but this part looks wrong:
for(int i=0;i<imagef->width();i++)
{
for(int j=0;j<imagef->height();j++)
{
for(int k=0;k<liste.size();k++)
{
imagef =imageList.at(k);
QRgb pixelfft=imagef->pixel(i,j);
double moyp= qGray(pixelfft);
in[k][0] = moyp;
in[k][1] = 0.0;
}
Your loops appear to be in the wrong order. When you call width and height, you're not calling them on the current image in your inner loop. What you might want instead is this:
for(int k=0;k<liste.size();k++)
{
//Get the current image from the list
imagef = imageList.at(k);
//Loop over every pixel in the image
for(int i=0;i<imagef->width();i++)
{
for(int j=0;j<imagef->height();j++)
{
QRgb pixelfft=imagef->pixel(i,j);
double moyp= qGray(pixelfft);
in[k][0] = moyp;
in[k][1] = 0.0;
}
}
/*...*/

Color Transfer: What's wrong with my code in OpenCV C++

I want to implement the color transfer algorithm in this paper and I refer this tutorial to transfer the algorithm in OpenCV C++.
But I got some strange result, for example:
This is the source image and this is the target, but the combined result look like this.
Some part of the result look strange.
This is my source code
Mat src; Mat tar; Mat result;
class imageInfo{
public:
double lMean, lStd, aMean, aStd, bMean, bStd;
};
/// Function header
void image_stats(Mat img,imageInfo *info);
/** #function main */
int main(int argc, char** argv)
{
vector<Mat> mv;
imageInfo srcInfo, tarInfo;
src = imread("images/autumn.jpg");
tar = imread("images/fallingwater.jpg");
imshow("src", src);
imshow("tar", tar);
cvtColor(src, src, CV_BGR2Lab);
cvtColor(tar, tar, CV_BGR2Lab);
image_stats(src, &srcInfo);
image_stats(tar, &tarInfo);
split(tar, mv);
Mat l = mv[0];
Mat a = mv[1];
Mat b = mv[2];
/*pixel color modify*/
for (int i = 0; i<l.rows; i++){
for (int j = 0; j<l.cols; j++){
double li = l.data[l.step[0] * i + l.step[1] * j];
if (i == 426 && j == 467)
cout << "i:" << i << "j:" << j << " " << li << endl;
li -= tarInfo.lMean;
li = (tarInfo.lStd / srcInfo.lStd)*li;
li += srcInfo.lMean;
li = (int)li % 256;
l.data[l.step[0] * i + l.step[1] * j] = li;
}
}
for (int i = 0; i<a.rows; i++){
for (int j = 0; j<a.cols; j++){
double ai = a.data[a.step[0] * i + a.step[1] * j];
ai -= tarInfo.aMean;
ai = (tarInfo.aStd / srcInfo.aStd)*ai;
ai += srcInfo.aMean;
ai = (int)ai % 256;
a.data[a.step[0] * i + a.step[1] * j] = ai;
}
}
for (int i = 0; i<b.rows; i++){
for (int j = 0; j<b.cols; j++){
double bi = b.data[b.step[0] * i + b.step[1] * j];
bi -= tarInfo.bMean;
bi = (tarInfo.bStd / srcInfo.bStd)*bi;
bi += srcInfo.bMean;
bi = (int)bi % 256;
b.data[b.step[0] * i + b.step[1] * j] = bi;
}
}
mv.clear();
mv.push_back(l);
mv.push_back(a);
mv.push_back(b);
merge(mv, result);
cvtColor(result, result, CV_Lab2BGR);
imshow("result", result);
imwrite("result.png", result);
waitKey(0);
return(0);
}
image_stats function:
void image_stats(Mat img, imageInfo *info){
int Max=0;
vector<Mat> mv;
vector<int> vl, va, vb;
split(img, mv);
Mat l = mv[0];
Mat a = mv[1];
Mat b = mv[2];
/*statistics L space*/
for (int i = 0; i<l.rows; i++){
for (int j = 0; j<l.cols; j++){
int li = l.data[l.step[0] * i + l.step[1] * j];
vl.push_back(li);
}
}
double sum_l = std::accumulate(vl.begin(), vl.end(), 0.0);
double mean_l = sum_l / vl.size();
std::vector<double> diff_l(vl.size());
std::transform(vl.begin(), vl.end(), diff_l.begin(),
std::bind2nd(std::minus<double>(), mean_l));
double sq_sum_l = std::inner_product(diff_l.begin(), diff_l.end(), diff_l.begin(), 0.0);
double stdev_l = std::sqrt(sq_sum_l / vl.size());
info->lMean = mean_l;
info->lStd = stdev_l;
/*statistics A space*/
for (int i = 0; i<a.rows; i++){
for (int j = 0; j<a.cols; j++){
int ai = a.data[a.step[0] * i + a.step[1] * j];
va.push_back(ai);
}
}
double sum_a = std::accumulate(va.begin(), va.end(), 0.0);
double mean_a = sum_a / va.size();
std::vector<double> diff_a(va.size());
std::transform(va.begin(), va.end(), diff_a.begin(),
std::bind2nd(std::minus<double>(), mean_a));
double sq_sum_a = std::inner_product(diff_a.begin(), diff_a.end(), diff_a.begin(), 0.0);
double stdev_a = std::sqrt(sq_sum_a / va.size());
info->aMean = mean_a;
info->aStd = stdev_a;
/*statistics B space*/
for (int i = 0; i<b.rows; i++){
for (int j = 0; j<b.cols; j++){
int bi = b.data[b.step[0] * i + b.step[1] * j];
vb.push_back(bi);
}
}
double sum_b = std::accumulate(vb.begin(), vb.end(), 0.0);
double mean_b = sum_b / vb.size();
std::vector<double> diff_b(vb.size());
std::transform(vb.begin(), vb.end(), diff_b.begin(),
std::bind2nd(std::minus<double>(), mean_b));
double sq_sum_b = std::inner_product(diff_b.begin(), diff_b.end(), diff_b.begin(), 0.0);
double stdev_b = std::sqrt(sq_sum_b / vb.size());
info->bMean = mean_b;
info->bStd = stdev_b;
}
In your main function you should probably bound your result values by upper & lower limits [0; 255], not take a modulo. If li = 256; then code li = (int)li % 256; will make it zero.

FFTW forward and back ward yield in different results why?

I am trying to FFT an image using the library from http://www.fftw.org/. basically i want to do a forward transform and then the backward transform to get the input image i have chosen. Then I would like to get my input back with the backward FFT, but it doesn't work. Here is my code :
double n[w][h][2];
double im[w][h][2];
const int Lx = w;
const int Lt = h;
int var_x;
int var_t;
fftw_complex *in, *out, *result;
fftw_plan p;
fftw_plan inv_p;
in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*Lx*Lt);
out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*Lx*Lt);
result = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) *Lx *Lt);
p = fftw_plan_dft_2d(Lx, Lt, in, out, FFTW_FORWARD, FFTW_MEASURE);
for (int x = 0; x < Lx; x++)
{
for (int t = 0; t < Lt; t++)
{
in[t + Lt*x][0] = n[x][t][0];
in[t + Lt*x][1] = 0;
}
}
fftw_execute(p);
for (int x = 0; x < Lx; x++)
{
for (int t = 0; t < Lt; t++)
{
n[x][t][0] = out[t + Lt*x][0];
n[x][t][1] = out[t + Lt*x][1];
}
}
inv_p = fftw_plan_dft_2d(Lx, Lt, out, result, FFTW_BACKWARD, FFTW_MEASURE);
fftw_execute(inv_p);
for (int x = 0; x < Lx; x++)
{
for (int t = 0; t < Lt; t++)
{
im[x][t][0] = result[t + Lt*x][0];
im[x][t][1] = result[t + Lt*x][1];
std::cout<<im[x][t][0]<<std::endl;
}
}
fftw_destroy_plan(p);
fftw_free(in);
fftw_free(out);
As you can see, I just try to perform a normal FFT, then to reverse it. The problem is that my output 'im' is just full of 0, instead of 1 and 0...
So what's wrong with my code ?
Thank you :)
Your original image and transform matrices are declared as int. Try defining them as double:
double n[w][h][2];
double im[w][h][2];
The line below, for example, is destroying data because result[i][j] is of type double (as of fftw_complex definition). So that if result[i][j] == 0.99, it'll be converted to 0.
im[x][t][0] = result[t + Lt*x][0]; //A value of 0.99 may be converted to 0
This is the corrected version of the code which is now working - thank you to everybody who helped me to fix all the problems.
double n[w][h][2];
double im[w][h][2];
const int Lx = w;
const int Lt = h;
int var_x;
int var_t;
fftw_complex *in, *out, *result;
fftw_plan p;
fftw_plan inv_p;
in = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*Lx*Lt);
out = (fftw_complex*)fftw_malloc(sizeof(fftw_complex)*Lx*Lt);
result = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) *Lx *Lt);
p = fftw_plan_dft_2d(Lx, Lt, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
for (int x = 0; x < Lx; x++)
{
for (int t = 0; t < Lt; t++)
{
in[t + Lt*x][0] = n[x][t][0];
in[t + Lt*x][1] = 0;
}
}
fftw_execute(p);
for (int x = 0; x < Lx; x++)
{
for (int t = 0; t < Lt; t++)
{
n[x][t][0] = out[t + Lt*x][0];
n[x][t][1] = out[t + Lt*x][1];
}
}
inv_p = fftw_plan_dft_2d(Lx, Lt, out, result, FFTW_BACKWARD, FFTW_ESTIMATE);
fftw_execute(inv_p);
for (int x = 0; x < Lx; x++)
{
for (int t = 0; t < Lt; t++)
{
im[x][t][0] = result[t + Lt*x][0];
im[x][t][1] = result[t + Lt*x][1];
std::cout<<im[x][t][0]<<std::endl;
}
}
fftw_destroy_plan(p);
fftw_destroy_plan(inv_p);
fftw_free(in);
fftw_free(out);
fftw_free(result);