From ae05c3e48657bbd5c1bc3ac2154a6760be2a2ce1 Mon Sep 17 00:00:00 2001 From: pgovyadi Date: Tue, 17 May 2016 15:29:54 -0500 Subject: [PATCH] Found an error with the image.h class. Not sure how to fix, but it is pretty serious. Since using openCV uses it's own mechanics internally, memcpy does not create a copy correctly and hence when loading multiple images with 1 in memory at a time, the previously loaded image data is never released leading to OOM errors --- stim/gl/gl_spider.h | 2 +- stim/grids/image_stack.h | 42 +++++++++++++++++++++++++++++++++--------- stim/image/image.h | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 96 insertions(+), 19 deletions(-) diff --git a/stim/gl/gl_spider.h b/stim/gl/gl_spider.h index f56aa8c..cbe379e 100644 --- a/stim/gl/gl_spider.h +++ b/stim/gl/gl_spider.h @@ -140,7 +140,7 @@ class gl_spider : public virtual gl_texture setMatrix(); //create the transformation matrix. glCallList(dList+1); //move the templates to p, d, m. int best = getCost(ptexbufferID, numSamplesPos); //find min cost. - std::cerr << best << std::endl; +// std::cerr << best << std::endl; stim::vec next( //find next position. pV[best][0], pV[best][1], diff --git a/stim/grids/image_stack.h b/stim/grids/image_stack.h index afb9a12..130b924 100644 --- a/stim/grids/image_stack.h +++ b/stim/grids/image_stack.h @@ -1,10 +1,10 @@ #ifndef STIM_IMAGE_STACK_H #define STIM_IMAGE_STACK_H -#include "../parser/wildcards.h" -#include "../parser/filename.h" -#include "../grids/grid.h" -#include "../image/image.h" +#include +#include +#include +#include namespace stim{ @@ -48,7 +48,7 @@ public: } //load the first image and set all of the image_stack properties - std::cout<<"File to Load: "< I(file_list[0].str()); //set the image resolution and number of channels @@ -63,7 +63,7 @@ public: //load and copy each image into the grid for(unsigned int i = 0; i I(file_list[i].str()); @@ -73,8 +73,15 @@ public: } } - ///Saves a single page to an image file + ///Inserts image I into slot i. + /// @param stim::image I; image to insert. + /// @int I, where to place the image. + void insert_image(stim::image I, int i) + { + I.get_interleaved_rgb(&ptr[i *R[0] *R[1] *R[2] ]); + } + ///Saves a single page to an image file /// @param file_name is the name of the image file to be created /// @param i is the page to be saved void save_image(std::string file_name, unsigned int i){ @@ -83,10 +90,11 @@ public: stim::image I; //retrieve the interlaced data from the image - store it in the grid - I.set_interleaved(&ptr[ i * R[0] * R[1] * R[2] ], R[1], R[2], R[0]); + I.set_interleaved_rgb(&ptr[ i * R[0] * R[1] * R[2] ], R[1], R[2], R[0]); I.save(file_name); } + ///Sets the dimensions of the image in each direction ///Voxel-size. /// @param x size in the x direction @@ -100,8 +108,24 @@ public: S[2] = y; S[3] = z; } - ///Saves the entire stack to a set of images + ///set dimensions of the grid. + /// @param channels, number of channels in each image. + /// @param width, number of pixels in width each image. + /// @param height, number of pixels in height. + /// @param depth, number of pixels in depth. + void init(int channels, int width, int height, int depth) + { + R.resize(4); + R[0] = channels; + R[1] = width; + R[2] = height; + R[3] = depth; + + ptr = (T*)malloc(sizeof(T) * samples()); + } + + ///Saves the entire stack to a set of images /// @param file_mask is the mask describing how the file names will be saved (ex. image????.bmp) void save_images(std::string file_mask){ diff --git a/stim/image/image.h b/stim/image/image.h index d101ec4..28ce502 100644 --- a/stim/image/image.h +++ b/stim/image/image.h @@ -112,8 +112,13 @@ public: } /// Destructor - clear memory - ~image(){ - free(img); +// ~image(){ +// free(img); +// } + + void clear_exp(){ //clears all image data + unalloc(); + } stim::image operator=(const stim::image& I){ @@ -133,11 +138,28 @@ public: exit(1); } allocate(cvImage.cols, cvImage.rows, cvImage.channels()); //allocate space for the image - T* cv_ptr = (T*)cvImage.data; - if(C() == 1) //if this is a single-color image, just copy the data - memcpy(img, cv_ptr, bytes()); + T* cv_ptr = (T*) cvImage.data; + if(C() == 1) + { + //if this is a single-color image, just copy the data +/* + THIS DOES NOT WORK PROPERLY. + YOU CANNOT DO MEMCPY LIKE THIS BECAUSE IT CORRUPTS THE POINTREF MECHANIC IN OPENCV AND NEVER ACTUALLY CREATES A DEEP COPY BUT TAKES UP THE MEMORY. + TO TEST run and compile pseudocode + stim::image I; + for(int i = 0; i < file_list.size(); i++) + I.load(file_list[i].srt()) + + + You will run out of memory. +*/ + memcpy(img, cv_ptr, bytes()); +// img = cvImage.data; + } if(C() == 3) //if this is a 3-color image, OpenCV uses BGR interleaving set_interleaved_bgr(cv_ptr, X(), Y()); + +// cvImage.deallocate(); } //save a file @@ -151,16 +173,18 @@ public: get_interleaved_bgr(buffer); cv::Mat cvImage((int)Y(), (int)X(), cv_type(), buffer); cv::imwrite(filename, cvImage); + cvImage.release(); + free(buffer); } //create an image from an interleaved buffer - void set_interleaved_rgb(T* buffer, size_t width, size_t height){ - allocate(width, height, 3); + void set_interleaved_rgb(T* buffer, size_t width, size_t height, size_t channels = 3){ + allocate(width, height, channels); memcpy(img, buffer, bytes()); } - void set_interleaved_bgr(T* buffer, size_t width, size_t height){ - allocate(width, height, 3); + void set_interleaved_bgr(T* buffer, size_t width, size_t height, size_t channels = 3){ + allocate(width, height, channels); for(size_t c = 0; c < C(); c++){ //copy directly for(size_t y = 0; y < Y(); y++){ for(size_t x = 0; x < X(); x++){ @@ -329,6 +353,34 @@ public: return r; //return the inverted image } + ///crops the image from x1 to x0 and y1 to y0 and returns a new (smaller) image. + ///Untested + image crop(int x0, int x1, int y0, int y1) + { + + image ret(x1-x0, y1-y0, C()); + int newWidth = x1-x0; + int destidx, srcidx; +// for(int i = 0; i < (y1-y0); i++) + { + destidx = i*newWidth*C(); ///destination index one per each row + srcidx = ((i+(y0))*X()+x0)*C(); ///source index, one per each row. + ret.set_interleaved_rgb(img[srcidx], newWidth, y1-y0, C()); + memcpy(&ret.img[destidx], &buffer[srcidx], sizeof(T)*newWidth*C()); + } + +// for(int i = 0; i < (x1 -x0); i++) +// { +// for(int j = 0; j < (y1 - y0); j++) +// { +// destidx = j*newWidth*C() + i; +// srcidx = ((i+(y0))*X() +x0)*C() + i; +// ret.img[destidx] = img[srcidx]; +// } +// } + return ret; + } + image srgb2lab(){ std::cout<<"ERROR stim::image::srgb2lab - function has been broken, re-implement."<