Blame view

stim/image/image.h 7.32 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>
6d30a707   Tianshu Cheng   add cuda/array_ad...
8
  
7b3948ab   David Mayerich   added support for...
9
  namespace stim{
c8c976a9   David Mayerich   replaced CImg wit...
10
11
  /// 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...
12
13
14
15
16
17
  
  //currently this interface uses CImg
  //	T = data type (usually unsigned char)
  template <class T>
  class image{
  
c8c976a9   David Mayerich   replaced CImg wit...
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  	//cimg_library::CImg<T> img;
  	T* img;										//pointer to the image data (assumes RGB for loading/saving)
  	size_t R[3];
  
  	size_t X(){ return R[1]; }
  	size_t Y(){ return R[2]; }
  	size_t C(){ return R[0]; }
  
  	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
  	}
  			
  
  	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;
  	}
  	
  
  	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());
  		
  		std::cout<<"ERROR in stim::image::cv_type - no valid data type found"<<std::endl;
  		exit(1);
  	}
  
d32a1854   David Mayerich   added framework f...
70
71
72
  
  public:
  
7b3948ab   David Mayerich   added support for...
73
  	//default constructor
c8c976a9   David Mayerich   replaced CImg wit...
74
  	image(){ init(); }							//initialize all variables to zero, don't allocate any memory
7b3948ab   David Mayerich   added support for...
75
  
c8c976a9   David Mayerich   replaced CImg wit...
76
77
  	image(std::string filename){				//constructor initialize the image with an image file
  		load(filename);
7b3948ab   David Mayerich   added support for...
78
79
  	}
  
c8c976a9   David Mayerich   replaced CImg wit...
80
81
82
83
  	/// Create a new image from scratch given a number of samples and channels
  	image(size_t x, size_t y = 1, size_t c = 1){			
  		img = (T*) malloc( sizeof(T) * x * y * c );
  	}
f186dbda   Tianshu Cheng   header file for b...
84
  
c8c976a9   David Mayerich   replaced CImg wit...
85
86
87
  	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...
88
89
  	}
  
c8c976a9   David Mayerich   replaced CImg wit...
90
  	/// Load an image from a file
d32a1854   David Mayerich   added framework f...
91
  	void load(std::string filename){
c8c976a9   David Mayerich   replaced CImg wit...
92
93
94
95
96
  
  		cv::Mat cvImage = cv::imread(filename, CV_LOAD_IMAGE_UNCHANGED);	//use OpenCV to open the image file
  		allocate(cvImage.cols, cvImage.rows, cvImage.channels());			//allocate space for the image
  		T* cv_ptr = (T*)cvImage.data;
  		set_interleaved_bgr(cv_ptr, X(), Y());
d32a1854   David Mayerich   added framework f...
97
98
99
100
  	}
  
  	//save a file
  	void save(std::string filename){
c8c976a9   David Mayerich   replaced CImg wit...
101
102
103
104
105
  		//OpenCV uses an interleaved format, so convert first and then output
  		T* buffer = (T*) malloc(bytes());
  		data_interleaved_bgr(buffer);
  		cv::Mat cvImage((int)Y(), (int)X(), cv_type(), buffer);
  		cv::imwrite(filename, cvImage);
d32a1854   David Mayerich   added framework f...
106
107
  	}
  
8b7be670   David Mayerich   implemented savin...
108
  	//create an image from an interleaved buffer
c8c976a9   David Mayerich   replaced CImg wit...
109
110
111
112
  	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...
113
  
c8c976a9   David Mayerich   replaced CImg wit...
114
115
116
117
118
119
120
  	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...
121
122
  			}
  		}
8b7be670   David Mayerich   implemented savin...
123
124
  	}
  
c8c976a9   David Mayerich   replaced CImg wit...
125
  	void data_interleaved_bgr(T* data){
8b7be670   David Mayerich   implemented savin...
126
127
  
  		//for each channel
c8c976a9   David Mayerich   replaced CImg wit...
128
129
130
131
132
133
134
  		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...
135
136
  	}
  
9d3ba0b1   David Mayerich   added stim::hsi a...
137
  	image<T> channel(size_t c){
41acaf5d   David Mayerich   added a CUDA Gaus...
138
139
  
  		//create a new image
c8c976a9   David Mayerich   replaced CImg wit...
140
  		image<T> r(R[0], R[1], 1);
41acaf5d   David Mayerich   added a CUDA Gaus...
141
  
c8c976a9   David Mayerich   replaced CImg wit...
142
143
144
145
146
  		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...
147
  
c8c976a9   David Mayerich   replaced CImg wit...
148
  		return r;
41acaf5d   David Mayerich   added a CUDA Gaus...
149
150
151
  
  	}
  
c8c976a9   David Mayerich   replaced CImg wit...
152
153
  	T& operator()(size_t x, size_t y, size_t c = 0){
  		return img[idx(x, y, c)];
3d0b6243   David Mayerich   fixed hsiproc bug...
154
155
156
157
158
159
160
  	}
  
  	/// 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...
161
  		size_t N = size();
3d0b6243   David Mayerich   fixed hsiproc bug...
162
  
c8c976a9   David Mayerich   replaced CImg wit...
163
164
  		for(size_t n = 0; n < N; n++)
  			img[n] = v;
3d0b6243   David Mayerich   fixed hsiproc bug...
165
166
167
168
169
  
  		return *this;
  
  	}
  
f186dbda   Tianshu Cheng   header file for b...
170
171
172
173
174
  	/// 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...
175
  	void set_channel(T* buffer, size_t c){
6d30a707   Tianshu Cheng   add cuda/array_ad...
176
  
c8c976a9   David Mayerich   replaced CImg wit...
177
178
179
180
181
182
  		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...
183
184
  	}
  
9d3ba0b1   David Mayerich   added stim::hsi a...
185
  	size_t channels(){
c8c976a9   David Mayerich   replaced CImg wit...
186
  		return C();
8b7be670   David Mayerich   implemented savin...
187
188
  	}
  
9d3ba0b1   David Mayerich   added stim::hsi a...
189
  	size_t width(){
c8c976a9   David Mayerich   replaced CImg wit...
190
  		return X();
8b7be670   David Mayerich   implemented savin...
191
192
  	}
  
9d3ba0b1   David Mayerich   added stim::hsi a...
193
  	size_t height(){
c8c976a9   David Mayerich   replaced CImg wit...
194
  		return Y();
3d0b6243   David Mayerich   fixed hsiproc bug...
195
196
  	}
  
6d30a707   Tianshu Cheng   add cuda/array_ad...
197
  	T* data(){
c8c976a9   David Mayerich   replaced CImg wit...
198
  		return img;
6d30a707   Tianshu Cheng   add cuda/array_ad...
199
200
  	}
  
7b3948ab   David Mayerich   added support for...
201
  	//returns the size (number of values) of the image
c8c976a9   David Mayerich   replaced CImg wit...
202
  	size_t size(){ return C() * X() * Y(); }
d32a1854   David Mayerich   added framework f...
203
  
faef7718   David Mayerich   updates to stim::...
204
  	/// Returns the number of nonzero values
9d3ba0b1   David Mayerich   added stim::hsi a...
205
  	size_t nnz(){
faef7718   David Mayerich   updates to stim::...
206
  
c8c976a9   David Mayerich   replaced CImg wit...
207
  		size_t N = X() * Y() * C();
faef7718   David Mayerich   updates to stim::...
208
  
c8c976a9   David Mayerich   replaced CImg wit...
209
210
211
  		size_t nz = 0;
  		for(size_t n = 0; n < N; n++)
  			if(img[n] != 0) nz++;
faef7718   David Mayerich   updates to stim::...
212
  
c8c976a9   David Mayerich   replaced CImg wit...
213
  		return nz;	//return the number of nonzero pixels
faef7718   David Mayerich   updates to stim::...
214
215
216
217
  
  	}
  
  	//this function returns indices of pixels that have nonzero values
9d3ba0b1   David Mayerich   added stim::hsi a...
218
  	std::vector<size_t> sparse_idx(){
faef7718   David Mayerich   updates to stim::...
219
  
c8c976a9   David Mayerich   replaced CImg wit...
220
  		std::vector<size_t> s;				//allocate an array
faef7718   David Mayerich   updates to stim::...
221
222
  		s.resize(nnz());					//allocate space in the array
  
c8c976a9   David Mayerich   replaced CImg wit...
223
224
  		size_t N = size();
  		//size_t C = channels();
faef7718   David Mayerich   updates to stim::...
225
  
c8c976a9   David Mayerich   replaced CImg wit...
226
  		//T* ptr = img.data();				//get a pointer to the image data
faef7718   David Mayerich   updates to stim::...
227
  
9d3ba0b1   David Mayerich   added stim::hsi a...
228
  		size_t i = 0;
c8c976a9   David Mayerich   replaced CImg wit...
229
230
231
232
  		for(size_t n = 0; n < N; n++){
  			if(img[n] != 0){
  				s[i] = n;
  				i++;
faef7718   David Mayerich   updates to stim::...
233
234
235
236
237
  			}
  		}
  
  		return s;			//return the index list
  	}
6d30a707   Tianshu Cheng   add cuda/array_ad...
238
  
d32a1854   David Mayerich   added framework f...
239
  	
6d30a707   Tianshu Cheng   add cuda/array_ad...
240
  	/// Returns the maximum pixel value in the image
96f9b10f   Laila Saadatifard   change the header...
241
  	T maxv(){
c8c976a9   David Mayerich   replaced CImg wit...
242
243
  		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...
244
  
c8c976a9   David Mayerich   replaced CImg wit...
245
  		for (size_t n=0; n<N; n++){		//for every value
6d30a707   Tianshu Cheng   add cuda/array_ad...
246
  
c8c976a9   David Mayerich   replaced CImg wit...
247
248
  			if (img[n] > max_val){			//if the value is higher than the current max
  				max_val = img[n];
6d30a707   Tianshu Cheng   add cuda/array_ad...
249
250
251
252
253
  			}	
  		}
  
  		return max;	
  	}
d32a1854   David Mayerich   added framework f...
254
  
c8c976a9   David Mayerich   replaced CImg wit...
255
  	/// Returns the maximum pixel value in the image
96f9b10f   Laila Saadatifard   change the header...
256
  	T minv(){
c8c976a9   David Mayerich   replaced CImg wit...
257
258
  		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...
259
  
c8c976a9   David Mayerich   replaced CImg wit...
260
261
262
  		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];
6d30a707   Tianshu Cheng   add cuda/array_ad...
263
264
265
  			}	
  		}
  
c8c976a9   David Mayerich   replaced CImg wit...
266
  		return max;	
6d30a707   Tianshu Cheng   add cuda/array_ad...
267
268
269
  	}
  
  	image<T> srgb2lab(){
c8c976a9   David Mayerich   replaced CImg wit...
270
271
  		std::cout<<"ERROR stim::image::srgb2lab - function has been broken, re-implement."<<std::endl;
  		exit(1);
6d30a707   Tianshu Cheng   add cuda/array_ad...
272
273
274
275
  	}
  
  	image<T> convolve2(image<T> mask){
  		
c8c976a9   David Mayerich   replaced CImg wit...
276
277
  		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...
278
  	}
d32a1854   David Mayerich   added framework f...
279
280
  
  
f186dbda   Tianshu Cheng   header file for b...
281
  	image<T> rotate(float angle, float cx, float cy){
c8c976a9   David Mayerich   replaced CImg wit...
282
283
  		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...
284
  	}
945ee13c   Laila Saadatifard   the get_list func...
285
286
287
  
  	// leila's code for non_interleaving data in 3D
  	//create an data set from an interleaved buffer
9d3ba0b1   David Mayerich   added stim::hsi a...
288
  	void set_interleaved3(T* buffer, size_t width, size_t height, size_t depth, size_t channels = 3){
c8c976a9   David Mayerich   replaced CImg wit...
289
290
  		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...
291
  	}
f186dbda   Tianshu Cheng   header file for b...
292
  	
d32a1854   David Mayerich   added framework f...
293
294
  };
  
7b3948ab   David Mayerich   added support for...
295
296
  };		//end namespace stim
  
d32a1854   David Mayerich   added framework f...
297
298
  
  #endif