Blame view

stim/image/image.h 9.34 KB
d32a1854   David Mayerich   added framework f...
1
2
  #ifndef STIM_IMAGE_H
  #define STIM_IMAGE_H
fbf0ab02   David Mayerich   added support for...
3
  
c8c976a9   David Mayerich   replaced CImg wit...
4
5
  #include <opencv2/core/core.hpp>
  #include <opencv2/highgui/highgui.hpp>
912d9073   David Mayerich   added vector.h to...
6
  #include <vector>
d32a1854   David Mayerich   added framework f...
7
  #include <iostream>
a2bf1d08   David Mayerich   general bug fixes...
8
  #include <limits>
6d30a707   Tianshu Cheng   add cuda/array_ad...
9
  
7b3948ab   David Mayerich   added support for...
10
  namespace stim{
c8c976a9   David Mayerich   replaced CImg wit...
11
12
  /// This static class provides the STIM interface for loading, saving, and storing 2D images.
  /// Data is stored in an interleaved (BIP) format (default for saving and loading is RGB).
d32a1854   David Mayerich   added framework f...
13
14
15
16
17
18
  
  //currently this interface uses CImg
  //	T = data type (usually unsigned char)
  template <class T>
  class image{
  
c8c976a9   David Mayerich   replaced CImg wit...
19
20
21
22
  	//cimg_library::CImg<T> img;
  	T* img;										//pointer to the image data (assumes RGB for loading/saving)
  	size_t R[3];
  
a2bf1d08   David Mayerich   general bug fixes...
23
24
25
  	size_t X() const { return R[1]; }
  	size_t Y() const { return R[2]; }
  	size_t C() const { return R[0]; }
c8c976a9   David Mayerich   replaced CImg wit...
26
27
28
29
30
31
32
33
34
  
  	void init(){								//initializes all variables, assumes no memory is allocated
  		memset(R, 0, sizeof(size_t) * 3);		//set the resolution and number of channels to zero
  		img = NULL;
  	}
  
  	void unalloc(){								//frees any resources associated with the image
  		if(img)	free(img);						//if memory has been allocated, free it
  	}
1a224b6a   David Mayerich   fixed linux compa...
35
  
c8c976a9   David Mayerich   replaced CImg wit...
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  
  	void clear(){								//clears all image data
  		unalloc();								//unallocate previous memory
  		init();									//re-initialize the variables
  	}
  
  	void allocate(){
  		img = (T*) malloc( sizeof(T) * R[0] * R[1] * R[2] );	//allocate memory
  	}
  
  	void allocate(size_t x, size_t y, size_t c){	//allocate memory based on the resolution
  		R[0] = c; R[1] = x; R[2] = y;				//set the resolution
  		allocate();									//allocate memory
  	}
  
  	size_t bytes(){ return size() * sizeof(T); }
  
  	size_t idx(size_t x, size_t y, size_t c = 0){
  		return y * C() * X() + x * C() + c;
  	}
1a224b6a   David Mayerich   fixed linux compa...
56
  
c8c976a9   David Mayerich   replaced CImg wit...
57
58
59
60
61
62
63
64
65
  
  	int cv_type(){
  		if(std::is_same<T, unsigned char>::value)	return CV_MAKETYPE(CV_8U, (int)C());
  		if(std::is_same<T, char>::value)			return CV_MAKETYPE(CV_8S, (int)C());
  		if(std::is_same<T, unsigned short>::value)	return CV_MAKETYPE(CV_16U, (int)C());
  		if(std::is_same<T, short>::value)			return CV_MAKETYPE(CV_16S, (int)C());
  		if(std::is_same<T, int>::value)				return CV_MAKETYPE(CV_32S, (int)C());
  		if(std::is_same<T, float>::value)			return CV_MAKETYPE(CV_32F, (int)C());
  		if(std::is_same<T, double>::value)			return CV_MAKETYPE(CV_64F, (int)C());
1a224b6a   David Mayerich   fixed linux compa...
66
  
c8c976a9   David Mayerich   replaced CImg wit...
67
68
69
70
  		std::cout<<"ERROR in stim::image::cv_type - no valid data type found"<<std::endl;
  		exit(1);
  	}
  
a2bf1d08   David Mayerich   general bug fixes...
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  	/// Returns the value for "white" based on the dynamic range (assumes white is 1.0 for floating point images)
  	T white(){
  		if(std::is_same<T, unsigned char>::value)		return UCHAR_MAX;
  		if(std::is_same<T, unsigned short>::value)		return SHRT_MAX;
  		if(std::is_same<T, unsigned>::value)			return UINT_MAX;
  		if(std::is_same<T, unsigned long>::value)		return ULONG_MAX;
  		if(std::is_same<T, unsigned long long>::value)	return ULLONG_MAX;
  		if(std::is_same<T, float>::value)				return 1.0f;
  		if(std::is_same<T, double>::value)				return 1.0;
  
  		std::cout<<"ERROR in stim::image::white - no white value known for this data type"<<std::endl;
  
  	}
  
d32a1854   David Mayerich   added framework f...
85
86
87
  
  public:
  
a2bf1d08   David Mayerich   general bug fixes...
88
  	/// Default constructor - creates an empty image object
c8c976a9   David Mayerich   replaced CImg wit...
89
  	image(){ init(); }							//initialize all variables to zero, don't allocate any memory
7b3948ab   David Mayerich   added support for...
90
  
a2bf1d08   David Mayerich   general bug fixes...
91
  	/// Constructor with a filename - loads the specified file
c8c976a9   David Mayerich   replaced CImg wit...
92
93
  	image(std::string filename){				//constructor initialize the image with an image file
  		load(filename);
7b3948ab   David Mayerich   added support for...
94
95
  	}
  
c8c976a9   David Mayerich   replaced CImg wit...
96
  	/// Create a new image from scratch given a number of samples and channels
1a224b6a   David Mayerich   fixed linux compa...
97
  	image(size_t x, size_t y = 1, size_t c = 1){
a2bf1d08   David Mayerich   general bug fixes...
98
  		allocate(x, y, c);
c8c976a9   David Mayerich   replaced CImg wit...
99
  	}
f186dbda   Tianshu Cheng   header file for b...
100
  
a2bf1d08   David Mayerich   general bug fixes...
101
  	/// Create a new image with the data given in 'data'
c8c976a9   David Mayerich   replaced CImg wit...
102
103
104
  	image(T* data, size_t x, size_t y, size_t c = 1){
  		allocate(x, y, c);
  		memcpy(img, data, bytes());
41acaf5d   David Mayerich   added a CUDA Gaus...
105
106
  	}
  
a2bf1d08   David Mayerich   general bug fixes...
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  	/// Copy constructor - duplicates an image object
  	image(const stim::image<T>& I){
  		allocate(I.X(), I.Y(), I.C());
  		//allocate(I.R[1], I.R[2], I.R[0]);
  		memcpy(img, I.img, bytes());
  	}
  
  	/// Destructor - clear memory
  	~image(){
  		free(img);
  	}
  
  	stim::image<T> operator=(const stim::image<T>& I){
  		if(&I == this)									//handle self-assignment
  			return *this;
  		allocate(I.X(), I.Y(), I.C());
  		memcpy(img, I.img, bytes());
  		return *this;
  	}
  
c8c976a9   David Mayerich   replaced CImg wit...
127
  	/// Load an image from a file
d32a1854   David Mayerich   added framework f...
128
  	void load(std::string filename){
c8c976a9   David Mayerich   replaced CImg wit...
129
130
  
  		cv::Mat cvImage = cv::imread(filename, CV_LOAD_IMAGE_UNCHANGED);	//use OpenCV to open the image file
a2bf1d08   David Mayerich   general bug fixes...
131
132
133
134
  		if(!cvImage.data){
  			std::cout<<"ERROR stim::image::load() - unable to find image "<<filename<<std::endl;
  			exit(1);
  		}
c8c976a9   David Mayerich   replaced CImg wit...
135
136
  		allocate(cvImage.cols, cvImage.rows, cvImage.channels());			//allocate space for the image
  		T* cv_ptr = (T*)cvImage.data;
a2bf1d08   David Mayerich   general bug fixes...
137
138
139
140
  		if(C() == 1)														//if this is a single-color image, just copy the data
  			memcpy(img, cv_ptr, bytes());
  		if(C() == 3)														//if this is a 3-color image, OpenCV uses BGR interleaving
  			set_interleaved_bgr(cv_ptr, X(), Y());
d32a1854   David Mayerich   added framework f...
141
142
143
144
  	}
  
  	//save a file
  	void save(std::string filename){
c8c976a9   David Mayerich   replaced CImg wit...
145
146
  		//OpenCV uses an interleaved format, so convert first and then output
  		T* buffer = (T*) malloc(bytes());
a2bf1d08   David Mayerich   general bug fixes...
147
148
149
150
151
  
  		if(C() == 1)
  			memcpy(buffer, img, bytes());
  		else if(C() == 3)
  			data_interleaved_bgr(buffer);
c8c976a9   David Mayerich   replaced CImg wit...
152
153
  		cv::Mat cvImage((int)Y(), (int)X(), cv_type(), buffer);
  		cv::imwrite(filename, cvImage);
d32a1854   David Mayerich   added framework f...
154
155
  	}
  
8b7be670   David Mayerich   implemented savin...
156
  	//create an image from an interleaved buffer
c8c976a9   David Mayerich   replaced CImg wit...
157
158
159
160
  	void set_interleaved_rgb(T* buffer, size_t width, size_t height){
  		allocate(width, height, 3);
  		memcpy(img, buffer, bytes());
  	}
fbf0ab02   David Mayerich   added support for...
161
  
c8c976a9   David Mayerich   replaced CImg wit...
162
163
164
165
166
167
168
  	void set_interleaved_bgr(T* buffer, size_t width, size_t height){
  		allocate(width, height, 3);
  		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++){
  					img[idx(x, y, c)] = buffer[y * X() * C() + x * C() + (2-c)];
  				}
fbf0ab02   David Mayerich   added support for...
169
170
  			}
  		}
8b7be670   David Mayerich   implemented savin...
171
172
  	}
  
c8c976a9   David Mayerich   replaced CImg wit...
173
  	void data_interleaved_bgr(T* data){
8b7be670   David Mayerich   implemented savin...
174
175
  
  		//for each channel
c8c976a9   David Mayerich   replaced CImg wit...
176
177
178
179
180
181
182
  		for(size_t y = 0; y < Y(); y++){
  			for(size_t x = 0; x < X(); x++){
  				for(size_t c = 0; c < C(); c++){
  					data[y * X() * C() + x * C() + (2-c)] = img[idx(x, y, c)];
  				}
  			}
  		}
8b7be670   David Mayerich   implemented savin...
183
184
  	}
  
9d3ba0b1   David Mayerich   added stim::hsi a...
185
  	image<T> channel(size_t c){
41acaf5d   David Mayerich   added a CUDA Gaus...
186
187
  
  		//create a new image
a2bf1d08   David Mayerich   general bug fixes...
188
  		image<T> r(X(), Y(), 1);
41acaf5d   David Mayerich   added a CUDA Gaus...
189
  
c8c976a9   David Mayerich   replaced CImg wit...
190
191
192
193
194
  		for(size_t x = 0; x < X(); x++){
  			for(size_t y = 0; y < Y(); y++){
  				r.img[r.idx(x, y, c)] = img[idx(x, y, c)];
  			}
  		}
41acaf5d   David Mayerich   added a CUDA Gaus...
195
  
c8c976a9   David Mayerich   replaced CImg wit...
196
  		return r;
41acaf5d   David Mayerich   added a CUDA Gaus...
197
198
199
  
  	}
  
c8c976a9   David Mayerich   replaced CImg wit...
200
201
  	T& operator()(size_t x, size_t y, size_t c = 0){
  		return img[idx(x, y, c)];
3d0b6243   David Mayerich   fixed hsiproc bug...
202
203
204
205
206
207
208
  	}
  
  	/// Set all elements in the image to a given scalar value
  
  	/// @param v is the value used to set all values in the image
  	image<T> operator=(T v){
  
c8c976a9   David Mayerich   replaced CImg wit...
209
  		size_t N = size();
3d0b6243   David Mayerich   fixed hsiproc bug...
210
  
c8c976a9   David Mayerich   replaced CImg wit...
211
212
  		for(size_t n = 0; n < N; n++)
  			img[n] = v;
3d0b6243   David Mayerich   fixed hsiproc bug...
213
214
215
216
217
  
  		return *this;
  
  	}
  
f186dbda   Tianshu Cheng   header file for b...
218
219
220
221
222
  	/// Copy the given data to the specified channel
  
  	/// @param c is the channel number that the data will be copied to
  	/// @param buffer is a pointer to the image to be copied to channel c
  
c8c976a9   David Mayerich   replaced CImg wit...
223
  	void set_channel(T* buffer, size_t c){
6d30a707   Tianshu Cheng   add cuda/array_ad...
224
  
c8c976a9   David Mayerich   replaced CImg wit...
225
226
227
228
229
230
  		size_t x, y;
  		for(y = 0; y < Y(); y++){
  			for(x = 0; x < X(); x++){
  				img[idx(x, y, c)] = buffer[c];
  			}
  		}
6d30a707   Tianshu Cheng   add cuda/array_ad...
231
232
  	}
  
9d3ba0b1   David Mayerich   added stim::hsi a...
233
  	size_t channels(){
c8c976a9   David Mayerich   replaced CImg wit...
234
  		return C();
8b7be670   David Mayerich   implemented savin...
235
236
  	}
  
9d3ba0b1   David Mayerich   added stim::hsi a...
237
  	size_t width(){
c8c976a9   David Mayerich   replaced CImg wit...
238
  		return X();
8b7be670   David Mayerich   implemented savin...
239
240
  	}
  
9d3ba0b1   David Mayerich   added stim::hsi a...
241
  	size_t height(){
c8c976a9   David Mayerich   replaced CImg wit...
242
  		return Y();
3d0b6243   David Mayerich   fixed hsiproc bug...
243
244
  	}
  
6d30a707   Tianshu Cheng   add cuda/array_ad...
245
  	T* data(){
c8c976a9   David Mayerich   replaced CImg wit...
246
  		return img;
6d30a707   Tianshu Cheng   add cuda/array_ad...
247
248
  	}
  
7b3948ab   David Mayerich   added support for...
249
  	//returns the size (number of values) of the image
c8c976a9   David Mayerich   replaced CImg wit...
250
  	size_t size(){ return C() * X() * Y(); }
d32a1854   David Mayerich   added framework f...
251
  
faef7718   David Mayerich   updates to stim::...
252
  	/// Returns the number of nonzero values
9d3ba0b1   David Mayerich   added stim::hsi a...
253
  	size_t nnz(){
faef7718   David Mayerich   updates to stim::...
254
  
c8c976a9   David Mayerich   replaced CImg wit...
255
  		size_t N = X() * Y() * C();
faef7718   David Mayerich   updates to stim::...
256
  
c8c976a9   David Mayerich   replaced CImg wit...
257
258
259
  		size_t nz = 0;
  		for(size_t n = 0; n < N; n++)
  			if(img[n] != 0) nz++;
faef7718   David Mayerich   updates to stim::...
260
  
c8c976a9   David Mayerich   replaced CImg wit...
261
  		return nz;	//return the number of nonzero pixels
faef7718   David Mayerich   updates to stim::...
262
263
264
265
  
  	}
  
  	//this function returns indices of pixels that have nonzero values
9d3ba0b1   David Mayerich   added stim::hsi a...
266
  	std::vector<size_t> sparse_idx(){
faef7718   David Mayerich   updates to stim::...
267
  
c8c976a9   David Mayerich   replaced CImg wit...
268
  		std::vector<size_t> s;				//allocate an array
faef7718   David Mayerich   updates to stim::...
269
270
  		s.resize(nnz());					//allocate space in the array
  
c8c976a9   David Mayerich   replaced CImg wit...
271
272
  		size_t N = size();
  		//size_t C = channels();
faef7718   David Mayerich   updates to stim::...
273
  
c8c976a9   David Mayerich   replaced CImg wit...
274
  		//T* ptr = img.data();				//get a pointer to the image data
faef7718   David Mayerich   updates to stim::...
275
  
9d3ba0b1   David Mayerich   added stim::hsi a...
276
  		size_t i = 0;
c8c976a9   David Mayerich   replaced CImg wit...
277
278
279
280
  		for(size_t n = 0; n < N; n++){
  			if(img[n] != 0){
  				s[i] = n;
  				i++;
faef7718   David Mayerich   updates to stim::...
281
282
283
284
285
  			}
  		}
  
  		return s;			//return the index list
  	}
6d30a707   Tianshu Cheng   add cuda/array_ad...
286
  
1a224b6a   David Mayerich   fixed linux compa...
287
  
6d30a707   Tianshu Cheng   add cuda/array_ad...
288
  	/// Returns the maximum pixel value in the image
96f9b10f   Laila Saadatifard   change the header...
289
  	T maxv(){
c8c976a9   David Mayerich   replaced CImg wit...
290
291
  		T max_val = img[0];				//initialize the maximum value to the first one
  		size_t N = size();	//get the number of pixels
6d30a707   Tianshu Cheng   add cuda/array_ad...
292
  
c8c976a9   David Mayerich   replaced CImg wit...
293
  		for (size_t n=0; n<N; n++){		//for every value
6d30a707   Tianshu Cheng   add cuda/array_ad...
294
  
c8c976a9   David Mayerich   replaced CImg wit...
295
296
  			if (img[n] > max_val){			//if the value is higher than the current max
  				max_val = img[n];
1a224b6a   David Mayerich   fixed linux compa...
297
  			}
6d30a707   Tianshu Cheng   add cuda/array_ad...
298
299
  		}
  
1a224b6a   David Mayerich   fixed linux compa...
300
  		return max_val;
6d30a707   Tianshu Cheng   add cuda/array_ad...
301
  	}
d32a1854   David Mayerich   added framework f...
302
  
c8c976a9   David Mayerich   replaced CImg wit...
303
  	/// Returns the maximum pixel value in the image
96f9b10f   Laila Saadatifard   change the header...
304
  	T minv(){
c8c976a9   David Mayerich   replaced CImg wit...
305
306
  		T min_val = img[0];				//initialize the maximum value to the first one
  		size_t N = size();	//get the number of pixels
6d30a707   Tianshu Cheng   add cuda/array_ad...
307
  
c8c976a9   David Mayerich   replaced CImg wit...
308
309
310
  		for (size_t n=0; n<N; n++){		//for every value
  			if (img[n] < min_val){			//if the value is higher than the current max
  				min_val = img[n];
1a224b6a   David Mayerich   fixed linux compa...
311
  			}
6d30a707   Tianshu Cheng   add cuda/array_ad...
312
313
  		}
  
1a224b6a   David Mayerich   fixed linux compa...
314
  		return min_val;
6d30a707   Tianshu Cheng   add cuda/array_ad...
315
316
  	}
  
a2bf1d08   David Mayerich   general bug fixes...
317
318
319
320
321
322
  	/// Invert an image by calculating I1 = alpha - I0, where alpha is the maximum image value
  	image<T> invert(T white_val){
  		size_t N = size();						//calculate the total number of values in the image
  		image<T> r(X(), Y(), C());				//allocate space for the resulting image
  		for(size_t n = 0; n < N; n++)
  			r.img[n] = white_val - img[n];		//perform the inversion
1a224b6a   David Mayerich   fixed linux compa...
323
  
a2bf1d08   David Mayerich   general bug fixes...
324
325
326
  		return r;								//return the inverted image
  	}
  
6d30a707   Tianshu Cheng   add cuda/array_ad...
327
  	image<T> srgb2lab(){
c8c976a9   David Mayerich   replaced CImg wit...
328
329
  		std::cout<<"ERROR stim::image::srgb2lab - function has been broken, re-implement."<<std::endl;
  		exit(1);
6d30a707   Tianshu Cheng   add cuda/array_ad...
330
331
332
  	}
  
  	image<T> convolve2(image<T> mask){
1a224b6a   David Mayerich   fixed linux compa...
333
  
c8c976a9   David Mayerich   replaced CImg wit...
334
335
  		std::cout<<"ERROR stim::image::convolve2 - function has been broken, and shouldn't really be in here."<<std::endl;
  		exit(1);
6d30a707   Tianshu Cheng   add cuda/array_ad...
336
  	}
d32a1854   David Mayerich   added framework f...
337
338
  
  
f186dbda   Tianshu Cheng   header file for b...
339
  	image<T> rotate(float angle, float cx, float cy){
c8c976a9   David Mayerich   replaced CImg wit...
340
341
  		std::cout<<"ERROR stim::image::rotate - function has been broken, and shouldn't really be in here."<<std::endl;
  		exit(1);
f186dbda   Tianshu Cheng   header file for b...
342
  	}
945ee13c   Laila Saadatifard   the get_list func...
343
344
345
  
  	// leila's code for non_interleaving data in 3D
  	//create an data set from an interleaved buffer
9d3ba0b1   David Mayerich   added stim::hsi a...
346
  	void set_interleaved3(T* buffer, size_t width, size_t height, size_t depth, size_t channels = 3){
c8c976a9   David Mayerich   replaced CImg wit...
347
348
  		std::cout<<"ERROR stim::image::set_interleaved3 - stim::image no longer supports 3D images."<<std::endl;
  		exit(1);
945ee13c   Laila Saadatifard   the get_list func...
349
  	}
1a224b6a   David Mayerich   fixed linux compa...
350
  
d32a1854   David Mayerich   added framework f...
351
352
  };
  
7b3948ab   David Mayerich   added support for...
353
354
  };		//end namespace stim
  
d32a1854   David Mayerich   added framework f...
355
356
  
  #endif