Structural deformable models
Data.cpp
Go to the documentation of this file.
1 #ifdef WIN32
2 #include <windows.h>
3 #endif
4 #include <fstream>
5 #include <sstream>
6 #include <math.h>
7 #include <GL/gl.h>
8 #include "Data.h"
9 
10 //-- image loader setup
11 #include "fxconfig.h"
12 #include <fx.h>
13 #ifdef HAVE_PNG_H
14 #include <FXPNGImage.h>
15 #endif
16 #ifdef HAVE_JPEG_H
17 #include <FXJPGImage.h>
18 #endif
19 #ifdef HAVE_TIFF_H
20 #include <FXTIFImage.h>
21 #endif
22 #include <FXICOImage.h>
23 #include <FXTGAImage.h>
24 #include <FXRGBImage.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <sys/stat.h>
28 #include <signal.h>
29 #ifndef WIN32
30 #include <unistd.h>
31 #endif
32 using namespace std;
33 
34 //-----------------------------------------------------------------------------
35 //static declarations
36 static void copyFXImage2Image(vector<Image<byte> > &dimg, const FXImage &img);
37 static void copyFXImage2Image(Image<byte> &dimg, const FXImage &img);
38 static void copyImage2FXImage(FXImage &img, const vector<Image<byte> >& dimg);
39 
40 template<class T>
41 Image<T>& makeNoiseImage(Image<T>& nimg, T mean, T sigma);
42 
43 //-----------------------------------------------------------------------------
44 //Data methods
45 
46 Dataset::Dataset() : data(1),
47  m_Dim1(0), m_Dim2(0), m_Dim3(0), m_NChannels(0),
48  m_CurrImage(0),m_ppmm(DEFAULT_PPMM),m_RefreshImage(false),
49  m_HalveBeyondSize(0xffffffff)
50 {
51  setID("d0");
52 }
53 
54 Dataset::Dataset(const char* filename) : m_Dim1(0), m_Dim2(0), m_Dim3(0),
55  m_NChannels(0), m_CurrImage(0),
57  m_RefreshImage(false)
58 {
59  load(filename);
60 }
61 
62 bool Dataset::load(const char* filename, dword ppmm)
63 {
64  if(data.empty()) data.push_back(*(new ByteImage()));
65  vuLock l(writeMutex);
66  bool loaded = loadImage(data, filename);
67  if(loaded) {
68  m_Filename = filename;
69  m_Origin = 0.0f;
70  if(data[0].getSizeY()>3 && data[0].getSizeX()>3) {
71  ByteImage zimg(data[0].getSizeX()-2, data[0].getSizeY()-2,0);
72  int brd = (1<<6);
73  m_Origin = (float)brd;
74  for(vector< ByteImage >::iterator ii=data.begin();
75  ii!=data.end();ii++)
76  {
77  if((dword)ii->getSize() > m_HalveBeyondSize) {
78  *ii = ii->scaleBy(0.5);
79  ppmm /= 2;
80  cout << "reducing image" << endl;
81  }
82  ByteImage copimg(*ii);
83  copimg.insert(zimg, 1, 1);
84  double avgcol = copimg.sum()/
85  ((copimg.getSizeX()+copimg.getSizeY())*2-4);
86  ii->zeroPad(brd, byte(avgcol));
87  // make edge length even
88  dword nx = (ii->getSizeX()/2+1)*2;
89  dword ny = (ii->getSizeY()/2+1)*2;
90  ByteImage ni(nx, ny, byte(avgcol));
91  ni.insert(*ii);
92  *ii = ni;
93 // stringstream fname;
94 // fname << "bimage" << ii-data.begin() << ".ppm";
95 // if(ii->writePPM(fname.str())) cout << "ok." << endl;
96  }
97  }
98  m_OSize.x = (float)data[0].getSizeX();
99  m_OSize.y = (float)data[0].getSizeY();
100  m_CurrImage = 0;
101  m_Dim1 = data[0].getSizeX();
102  m_Dim2 = data[0].getSizeY();
103  m_Dim3 = 1;
104  m_RefreshImage = true;
105  m_NChannels = data.size();
106  setPPMM(ppmm);
108  performUpdate();
109  return true;
110  } else return false;
111 }
112 
113 void Dataset::draw(float x, float y, float sx, float sy) const
114 {
115  if(!data.empty())
116  {
117  if(m_RefreshImage) {
120  m_RefreshImage = false;
121  }
122  m_GLImage.draw(x, y, sx, sy);
123  //drawImage(data,x,y,sx,sy);
124  }
125 }
126 
128 {
129  data = rhs.data;
130  m_CurrImage = 0;
131  m_Dim1 = data[0].getSizeX();
132  m_Dim2 = data[0].getSizeY();
133  m_Dim3 = 1;
134  m_NChannels = data.size();
135  m_ppmm = rhs.m_ppmm;
136  m_Filename = rhs.m_Filename;
139  performUpdate();
140  return *this;
141 }
142 
144 {
145  m_Dim1 = m_Dim2 = m_Dim3 = 0;
146  m_NChannels = 0; m_CurrImage = 0;
148  data.clear();
149  data.resize(1);
150  m_Filename.clear();
151  m_Origin = 0.0f;
153  performUpdate();
154 }
155 
156 //---------------------------------------------------------------------------
157 // Data static methods
158 
159 bool Dataset::loadImage(vector< Image<byte> > &image, const char* file){
160  FXString ext=FXPath::extension(file);
161  FXImage *img=NULL;
162  FXApp *app = FXApp::instance(); //getApp()
163 
164  if(comparecase(ext,"bmp")==0){
165  img=new FXBMPImage(app,NULL,IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
166  }
167  else if(comparecase(ext,"gif")==0){
168  img=new FXGIFImage(app,NULL,IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
169  }
170  else if(comparecase(ext,"tga")==0){
171  img=new FXTGAImage(app,NULL,IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
172  }
173 #ifdef HAVE_PNG_H
174  else if(comparecase(ext,"png")==0){
175  img=new FXPNGImage(app,NULL,IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
176  }
177 #endif
178 #ifdef HAVE_JPEG_H
179  else if(comparecase(ext,"jpg")==0){
180  img=new FXJPGImage(app,NULL,IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
181  }
182 #endif
183 #ifdef HAVE_TIFF_H
184  else if(comparecase(ext,"tif")==0 || comparecase(ext,"tiff")==0){
185  img=new FXTIFImage(app,NULL,IMAGE_KEEP|IMAGE_SHMI|IMAGE_SHMP);
186  }
187 #endif
188  bool load_ok = false;
189  if(img!=NULL) {
190  // Load it
191  FXFileStream stream;
192  if(stream.open(file,FXStreamLoad)){
193  //app->beginWaitCursor();
194  load_ok = img->loadPixels(stream);
195  if(load_ok) {
196  img->create();
197  //app->endWaitCursor();
198  //img->mirror(false, true);
199  copyFXImage2Image(image, *img);
200  }
201  stream.close();
202  }
203  delete img;
204  }
205  //note: modal error message causes deadlock on Brain::m_DataMutex
206  //between Brain::loadData and Brain::drawAllModels
207  //if(!load_ok)
208  // FXMessageBox::error(/*this app->getRootWindow()*/ app,MBOX_OK,"Error Loading Image","Unsupported type: %s",ext.text());
209  return load_ok;
210 }
211 
212 void Dataset::addNoise(float sigma)
213 {
214  for(vector< ByteImage >::iterator ii=data.begin();
215  ii!=data.end();ii++)
216  {
217  byte* data = ii->getData();
218  for(int i=ii->getSize(); i>0; i--, data++)
219  {
220  int val = int(int(*data) + fgauss01()*sigma);
221  if(val<0) *data = 0;
222  else if(val>255) *data = 255;
223  else *data = byte(val);
224  }
225  }
226  m_RefreshImage = true;
227 }
228 
229 void Dataset::drawImage(const Image<byte> &image, float x, float y,
230  float sx, float sy)
231 {
232  glPixelZoom(sx, sy);
233  glRasterPos3f(x,y,0.0f);
234  glDrawPixels(image.getSizeX(),
235  image.getSizeY(),
236  GL_LUMINANCE,
237  GL_UNSIGNED_BYTE,
238  image.getData());
239 }
240 
241 byte* interleave(const vector< Image<byte> > &img) {
242  const int comp = img.size()>3 ? 3 : img.size();
243  int size = img[0].size();
244  byte *b = new byte[size*3];
245  if(comp<3) {
246  Image<byte>::const_iterator bi = img[0].begin();
247  byte *cv = b;
248  for(int i=0; i!=size; i++, cv++, bi++)
249  *cv = *bi;
250  } else { // comp == 3
252  for(int a=0; a<comp; a++) bi[a] = img[a].begin();
253  byte *cv = b;
254  for(int i=0; i<size; i++) {
255  *(cv++) = *bi[0]; bi[0]++;
256  *(cv++) = *bi[1]; bi[1]++;
257  *(cv++) = *bi[2]; bi[2]++;
258  }
259  }
260  return b;
261 }
262 
263 void Dataset::drawImage(const vector< Image<byte> > &image, float x, float y,
264  float sx, float sy)
265 {
266  byte *buf = interleave(image);
267  glPixelZoom(sx, sy);
268  glRasterPos3f(x,y,0.0f);
269  glDrawPixels(image[0].getSizeX(),
270  image[0].getSizeY(),
271  GL_RGB,
272  GL_UNSIGNED_BYTE,
273  buf);
274  delete buf;
275 }
276 
277 //--------------------------------------------------------------------------
278 //--- internal static
279 
280 static void copyFXImage2Image(vector< Image<byte> > &dimg, const FXImage &img)
281 {
282  //FXImage *img=imgv->getImage();
283  // copy to image buffer
284  int height = img.getHeight();
285  int width = img.getWidth();
286  int size = width*height;
287  byte *imgdat = (byte*)img.getData();
288  const int nchan = 4;
289  dimg.clear();
290  dimg.resize(nchan);//, Image<byte>(width,height));
291  for(vector< Image<byte> >::iterator ii = dimg.begin();
292  ii!=dimg.end(); ii++)
293  ii->setSize(width, height);
294  //dimg.setSize(width,height);
295  int sind = 0;
296  for(int i=size;i>0;i--,imgdat+=nchan,sind++)
297  {
298  for(int c=0; c<nchan; c++) {
299  dimg[c][sind] = imgdat[c];
300  }
301  }
302 }
303 
304 static void copyFXImage2Image(Image<byte> &dimg, const FXImage &img)
305 {
306  //FXImage *img=imgv->getImage();
307  // copy to image buffer
308  int height = img.getHeight();
309  int width = img.getWidth();
310  int size = width*height;
311  byte *imgdat = (byte*)img.getData();
312  dimg.setSize(width,height);
313  byte *htimg = dimg.getData();
314  int nchan = 4;
315  for(int i=size;i>0;i--,imgdat+=nchan,htimg++)
316  {
317  //int val = int(0.299f*imgdat[0]+0.587f*imgdat[1]+0.114f*imgdat[2]);
318  //int val = (int(imgdat[0])+imgdat[1]+imgdat[2])/3;
319  int val = imgdat[0];
320  //*htimg = val > 255 ? 255 : val;
321  *htimg = byte(val);
322  }
323 }
324 
325 // copy to image buffer
326 static void copyImage2FXImage(FXImage &img, const Image<byte>& dimg)
327 {
328  int height = img.getHeight();
329  int width = img.getWidth();
330  img.resize(dimg.getSizeX(), dimg.getSizeY());
331  int size = width*height;
332  byte *imgdat = (byte*)img.getData();
333  const byte *htimg = dimg.getData();
334  int nchan = 4;
335  for(int i=size;i>0;i--,imgdat+=nchan,htimg++)
336  {
337  imgdat[0] = *htimg;
338  imgdat[1] = *htimg;
339  imgdat[2] = *htimg;
340  }
341 
342  img.create();
343 }
344 
345 template<class T>
347 {
348  T* data = nimg.getData();
349  for(int j=0; j<nimg.getSizeY(); j++)
350  for(int i=0; i<nimg.getSizeX(); i++, data++)
351  {
352  *data = (T)(fgauss01()*sigma+mean);
353  }
354  return nimg;
355 }
byte * interleave(const vector< Image< byte > > &img)
Definition: Data.cpp:241
void setPPMM(dword ppmm)
Definition: Data.h:71
std::vector< ByteImage > data
Definition: Data.h:108
#define NULL
Definition: simpletypes.h:9
void clear()
Definition: Data.cpp:143
int m_Dim2
Definition: Data.h:111
static bool loadImage(std::vector< Image< byte > > &image, const char *filename)
Definition: Data.cpp:159
int m_Dim3
Definition: Data.h:111
static void drawImage(const std::vector< Image< byte > > &image, float x=0, float y=0, float sx=1.0f, float sy=1.0f)
Definition: Data.cpp:263
static void copyImage2FXImage(FXImage &img, const vector< Image< byte > > &dimg)
float y
Definition: Point.h:224
void setImage(const Image< byte > &image)
Definition: glImage.h:27
void draw(float x, float y, float sx=1.f, float sy=1.f) const
Definition: glImage.h:85
void setID(const std::string &id)
Definition: Sensor.h:129
STL namespace.
Dataset()
Definition: Data.cpp:46
int getSizeX() const
Definition: Image.h:42
void unsetImage()
Definition: glImage.h:72
bool m_RefreshImage
Definition: Data.h:117
Point2D m_Origin
Definition: Data.h:115
virtual bool performUpdate()
Definition: Sensor.cpp:123
bool load(const char *filename, dword ppmm=0)
Definition: Data.cpp:62
Point2D m_OSize
Definition: Data.h:115
std::string m_Filename
Definition: Data.h:114
double sum() const
Definition: Image.h:355
dword m_HalveBeyondSize
Definition: Data.h:118
int m_NChannels
Definition: Data.h:111
void draw(float x=0, float y=0, float sx=1.0f, float sy=1.0f) const
Definition: Data.cpp:113
unsigned long dword
Definition: simpletypes.h:6
Image< T > & makeNoiseImage(Image< T > &nimg, T mean, T sigma)
Definition: Data.cpp:346
void addNoise(float sigma)
Definition: Data.cpp:212
float fgauss01()
Definition: mathutil.h:53
Definition: Data.h:21
GLImage m_GLImage
Definition: Data.h:116
unsigned char byte
Definition: simpletypes.h:4
int m_Dim1
Definition: Data.h:111
vuMutex writeMutex
Definition: Data.h:68
int m_CurrImage
current image
Definition: Data.h:112
void setSize(int nx, int ny)
Definition: Image.h:268
void insert(const Image< T > &ii, const int x=0, const int y=0)
Definition: Image.h:568
const T * getData() const
Definition: Image.h:39
float mean
Definition: Sensor.h:177
dword m_ppmm
Definition: Data.h:113
#define DEFAULT_PPMM
Definition: Data.h:16
float x
Definition: Point.h:224
Dataset & copyData(const Dataset &rhs)
Definition: Data.cpp:127
void setModified(dword mask=UPD_ALL)
Definition: Sensor.h:110
static void copyFXImage2Image(vector< Image< byte > > &dimg, const FXImage &img)
Definition: Data.cpp:280
int getSizeY() const
Definition: Image.h:43