d32a1854
David Mayerich
added framework f...
|
1
2
|
#ifndef STIM_IMAGE_H
#define STIM_IMAGE_H
|
fbf0ab02
David Mayerich
added support for...
|
3
|
|
4d80c1dd
David Mayerich
added a GLUT temp...
|
4
5
6
7
|
#ifdef _WIN32
#undef max
#endif
|
2e5e3a26
David Mayerich
added 2D convolut...
|
8
|
#ifdef USING_OPENCV
|
dd5aab2f
David Mayerich
fixed errors in s...
|
9
10
11
|
//#include <opencv2/core/core.hpp>
//#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
|
7d01bb90
David Mayerich
matlab matrix sav...
|
12
13
|
#else
#include <stim/image/bmp.h>
|
2e5e3a26
David Mayerich
added 2D convolut...
|
14
|
#endif
|
912d9073
David Mayerich
added vector.h to...
|
15
|
#include <vector>
|
d32a1854
David Mayerich
added framework f...
|
16
|
#include <iostream>
|
11ff9d7e
David Mayerich
improved user out...
|
17
|
#include <climits> //use limits and remove the MIN and MAX macros
|
e252a6d6
David Mayerich
somehow the C++11...
|
18
|
#include <typeinfo>
|
cfcf8619
David Mayerich
changes to filena...
|
19
|
#include <fstream>
|
b4cea01a
David Mayerich
removed automated...
|
20
|
#include <cstring>
|
6d30a707
Tianshu Cheng
add cuda/array_ad...
|
21
|
|
7d01bb90
David Mayerich
matlab matrix sav...
|
22
|
|
d9b2b2a8
David Mayerich
enabled basic rea...
|
23
24
|
#include <stim/parser/filename.h>
|
7b3948ab
David Mayerich
added support for...
|
25
|
namespace stim{
|
c8c976a9
David Mayerich
replaced CImg wit...
|
26
27
|
/// 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...
|
28
29
30
31
32
33
|
//currently this interface uses CImg
// T = data type (usually unsigned char)
template <class T>
class image{
|
cfcf8619
David Mayerich
changes to filena...
|
34
|
T* img; //pointer to the image data (interleaved RGB for color)
|
c8c976a9
David Mayerich
replaced CImg wit...
|
35
36
|
size_t R[3];
|
dbeb83f2
David Mayerich
added separable c...
|
37
38
39
|
inline size_t X() const { return R[1]; }
inline size_t Y() const { return R[2]; }
inline size_t C() const { return R[0]; }
|
c8c976a9
David Mayerich
replaced CImg wit...
|
40
|
|
c8c976a9
David Mayerich
replaced CImg wit...
|
41
42
43
44
45
46
47
|
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
|
c8c976a9
David Mayerich
replaced CImg wit...
|
48
|
}
|
1a224b6a
David Mayerich
fixed linux compa...
|
49
|
|
c8c976a9
David Mayerich
replaced CImg wit...
|
50
51
52
53
54
55
56
|
void clear(){ //clears all image data
unalloc(); //unallocate previous memory
init(); //re-initialize the variables
}
void allocate(){
|
e9a1b974
Pavel Govyadinov
imlemented Dr. Ma...
|
57
|
unalloc();
|
814eb271
David Mayerich
fixed problems wi...
|
58
|
img = (T*) malloc( sizeof(T) * R[0] * R[1] * R[2] ); //allocate memory
|
55417e1e
David Mayerich
fixed data type l...
|
59
60
61
62
|
if (img == NULL) {
std::cout << "stim::image ERROR - failed to allocate memory for image" << std::endl;
exit(1);
}
|
c8c976a9
David Mayerich
replaced CImg wit...
|
63
64
65
|
}
void allocate(size_t x, size_t y, size_t c){ //allocate memory based on the resolution
|
c8c976a9
David Mayerich
replaced CImg wit...
|
66
67
68
69
|
R[0] = c; R[1] = x; R[2] = y; //set the resolution
allocate(); //allocate memory
}
|
86dfa80b
David Mayerich
added 2D gaussian...
|
70
|
inline size_t idx(size_t x, size_t y, size_t c = 0) const {
|
dbeb83f2
David Mayerich
added separable c...
|
71
|
return y * R[0] * R[1] + x * R[0] + c;
|
c8c976a9
David Mayerich
replaced CImg wit...
|
72
|
}
|
1a224b6a
David Mayerich
fixed linux compa...
|
73
|
|
2e5e3a26
David Mayerich
added 2D convolut...
|
74
|
#ifdef USING_OPENCV
|
c8c976a9
David Mayerich
replaced CImg wit...
|
75
|
int cv_type(){
|
e252a6d6
David Mayerich
somehow the C++11...
|
76
77
78
79
80
81
82
|
if(typeid(T) == typeid(unsigned char)) return CV_MAKETYPE(CV_8U, (int)C());
if(typeid(T) == typeid(char)) return CV_MAKETYPE(CV_8S, (int)C());
if(typeid(T) == typeid(unsigned short)) return CV_MAKETYPE(CV_16U, (int)C());
if(typeid(T) == typeid(short)) return CV_MAKETYPE(CV_16S, (int)C());
if(typeid(T) == typeid(int)) return CV_MAKETYPE(CV_32S, (int)C());
if(typeid(T) == typeid(float)) return CV_MAKETYPE(CV_32F, (int)C());
if(typeid(T) == typeid(double)) return CV_MAKETYPE(CV_64F, (int)C());
|
1a224b6a
David Mayerich
fixed linux compa...
|
83
|
|
c8c976a9
David Mayerich
replaced CImg wit...
|
84
|
std::cout<<"ERROR in stim::image::cv_type - no valid data type found"<<std::endl;
|
3ff136b3
David Mayerich
replaced C++11 co...
|
85
|
exit(1);
|
c8c976a9
David Mayerich
replaced CImg wit...
|
86
|
}
|
2e5e3a26
David Mayerich
added 2D convolut...
|
87
|
#endif
|
a2bf1d08
David Mayerich
general bug fixes...
|
88
89
|
/// Returns the value for "white" based on the dynamic range (assumes white is 1.0 for floating point images)
T white(){
|
11ff9d7e
David Mayerich
improved user out...
|
90
91
92
93
|
if (typeid(T) == typeid(double) || typeid(T) == typeid(float))
return (T)1.0;
else
return std::numeric_limits<T>::max();
|
a2bf1d08
David Mayerich
general bug fixes...
|
94
95
|
}
|
d32a1854
David Mayerich
added framework f...
|
96
97
|
public:
|
a7ed4b2e
David Mayerich
ivote updates
|
98
99
|
size_t bytes() { return size() * sizeof(T); }
|
a2bf1d08
David Mayerich
general bug fixes...
|
100
|
/// Default constructor - creates an empty image object
|
814eb271
David Mayerich
fixed problems wi...
|
101
|
image(){ init(); } //initialize all variables to zero, don't allocate any memory
|
7b3948ab
David Mayerich
added support for...
|
102
|
|
a2bf1d08
David Mayerich
general bug fixes...
|
103
|
/// Constructor with a filename - loads the specified file
|
c8c976a9
David Mayerich
replaced CImg wit...
|
104
|
image(std::string filename){ //constructor initialize the image with an image file
|
fba6e7e3
Pavel Govyadinov
fixed image.h bug...
|
105
|
init();
|
c8c976a9
David Mayerich
replaced CImg wit...
|
106
|
load(filename);
|
7b3948ab
David Mayerich
added support for...
|
107
108
|
}
|
c8c976a9
David Mayerich
replaced CImg wit...
|
109
|
/// Create a new image from scratch given a number of samples and channels
|
1a224b6a
David Mayerich
fixed linux compa...
|
110
|
image(size_t x, size_t y = 1, size_t c = 1){
|
e9a1b974
Pavel Govyadinov
imlemented Dr. Ma...
|
111
|
init();
|
a2bf1d08
David Mayerich
general bug fixes...
|
112
|
allocate(x, y, c);
|
c8c976a9
David Mayerich
replaced CImg wit...
|
113
|
}
|
f186dbda
Tianshu Cheng
header file for b...
|
114
|
|
a2bf1d08
David Mayerich
general bug fixes...
|
115
|
/// Create a new image with the data given in 'data'
|
c8c976a9
David Mayerich
replaced CImg wit...
|
116
|
image(T* data, size_t x, size_t y, size_t c = 1){
|
e9a1b974
Pavel Govyadinov
imlemented Dr. Ma...
|
117
|
init();
|
c8c976a9
David Mayerich
replaced CImg wit...
|
118
119
|
allocate(x, y, c);
memcpy(img, data, bytes());
|
41acaf5d
David Mayerich
added a CUDA Gaus...
|
120
121
|
}
|
a2bf1d08
David Mayerich
general bug fixes...
|
122
|
/// Copy constructor - duplicates an image object
|
814eb271
David Mayerich
fixed problems wi...
|
123
|
image(const stim::image<T>& I){
|
e9a1b974
Pavel Govyadinov
imlemented Dr. Ma...
|
124
|
init();
|
a2bf1d08
David Mayerich
general bug fixes...
|
125
|
allocate(I.X(), I.Y(), I.C());
|
a2bf1d08
David Mayerich
general bug fixes...
|
126
127
128
129
130
131
132
133
|
memcpy(img, I.img, bytes());
}
/// Destructor - clear memory
~image(){
free(img);
}
|
a7ed4b2e
David Mayerich
ivote updates
|
134
|
///Resize an image - this function looks like it hasn't been implemented
|
86dfa80b
David Mayerich
added 2D gaussian...
|
135
136
137
138
|
void resize(size_t x, size_t y, size_t c = 1) {
allocate(x, y, c);
}
|
735a2a24
David Mayerich
started testing o...
|
139
|
stim::image<T>& operator=(const stim::image<T>& I){
|
a2bf1d08
David Mayerich
general bug fixes...
|
140
141
|
if(&I == this) //handle self-assignment
return *this;
|
276f9b23
David Mayerich
forced matching t...
|
142
|
init();
|
a2bf1d08
David Mayerich
general bug fixes...
|
143
144
145
146
|
allocate(I.X(), I.Y(), I.C());
memcpy(img, I.img, bytes());
return *this;
}
|
d661ab7d
David Mayerich
linux fixes for s...
|
147
|
#ifndef USING_OPENCV
|
d9b2b2a8
David Mayerich
enabled basic rea...
|
148
149
150
151
152
153
154
155
156
157
|
void load_bmp(std::string filename) {
stim::bmp bitmap;
bitmap.open(filename); //load the bitmap and read the headers
resize(bitmap.width, bitmap.height, 3); //resize the current image to match the bitmap
if (!bitmap.read((char*)img)) { //read the bits from file
std::cout << "stim::image ERROR: problem loading bitmap image." << std::endl;
exit(1);
}
bitmap.close(); //close the bitmap file
}
|
7c396e30
David Mayerich
fixed Linux stim:...
|
158
|
#endif
|
d9b2b2a8
David Mayerich
enabled basic rea...
|
159
|
|
08ada8c2
David Mayerich
updated image to ...
|
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
|
//determines if a filename represents a valid file format that can be loaded/saved
static bool test_filename(std::string f) {
stim::filename fname = f;
std::string ext = fname.extension();
#ifdef USING_OPENCV
if (ext == "bmp" ||
ext == "jpg" ||
ext == "png" ||
ext == "pbm" ||
ext == "tif" )
return true;
#else
if (ext == "pbm" || ext == "bmp")
return true;
#endif
return false;
}
|
cfcf8619
David Mayerich
changes to filena...
|
178
179
|
//save a Netpbm file
void load_netpbm(std::string filename) {
|
683f216a
David Mayerich
fixed? Linux comp...
|
180
|
std::ifstream infile(filename.c_str(), std::ios::in | std::ios::binary); //open an output file
|
cfcf8619
David Mayerich
changes to filena...
|
181
182
183
184
|
if (!infile) {
std::cout << "Error opening input file in image::load_netpbm()" << std::endl;
exit(1);
}
|
cfcf8619
David Mayerich
changes to filena...
|
185
|
|
2e5e3a26
David Mayerich
added 2D convolut...
|
186
187
|
size_t nc; //allocate space for the number of channels
char format[2]; //allocate space to hold the image format tag
|
cfcf8619
David Mayerich
changes to filena...
|
188
|
infile.read(format, 2); //read the image format tag
|
2e5e3a26
David Mayerich
added 2D convolut...
|
189
|
infile.seekg(1, std::ios::cur); //skip the newline character
|
cfcf8619
David Mayerich
changes to filena...
|
190
191
192
193
194
|
if (format[0] != 'P') {
std::cout << "Error in image::load_netpbm() - file format tag is invalid: " << format[0] << format[1] << std::endl;
exit(1);
}
|
2e5e3a26
David Mayerich
added 2D convolut...
|
195
196
|
if (format[1] == '5') nc = 1; //get the number of channels from the format flag
else if (format[1] == '6') nc = 3;
|
cfcf8619
David Mayerich
changes to filena...
|
197
198
199
200
|
else {
std::cout << "Error in image::load_netpbm() - file format tag is invalid: " << format[0] << format[1] << std::endl;
exit(1);
}
|
2e5e3a26
David Mayerich
added 2D convolut...
|
201
202
203
204
205
206
207
208
209
|
unsigned char c; //stores a character
while (infile.peek() == '#') { //if the next character indicates the start of a comment
while (true) {
c = infile.get();
if (c == 0x0A) break;
}
}
|
cfcf8619
David Mayerich
changes to filena...
|
210
|
std::string sw; //create a string to store the width of the image
|
cfcf8619
David Mayerich
changes to filena...
|
211
212
213
214
215
216
217
218
219
220
221
222
223
|
while(true){
c = infile.get(); //get a single character
if (c == ' ') break; //exit if we've encountered a space
sw.push_back(c); //push the character on to the string
}
size_t w = atoi(sw.c_str()); //convert the string into an integer
std::string sh;
while (true) {
c = infile.get();
if (c == 0x0A) break;
sh.push_back(c);
}
|
cfcf8619
David Mayerich
changes to filena...
|
224
|
|
2e5e3a26
David Mayerich
added 2D convolut...
|
225
226
227
228
229
230
|
while (true) { //skip the maximum value
c = infile.get();
if (c == 0x0A) break;
}
size_t h = atoi(sh.c_str()); //convert the string into an integer
|
01707489
David Mayerich
implemented a new...
|
231
232
233
234
235
236
|
allocate(w, h, nc); //allocate space for the image
unsigned char* buffer = (unsigned char*)malloc(w * h * nc); //create a buffer to store the read data
infile.read((char*)buffer, size()); //copy the binary data from the file to the image
infile.close(); //close the file
for (size_t n = 0; n < size(); n++) img[n] = (T)buffer[n]; //copy the buffer data into the image
free(buffer); //free the buffer array
|
cfcf8619
David Mayerich
changes to filena...
|
237
238
239
|
}
|
2e5e3a26
David Mayerich
added 2D convolut...
|
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
|
#ifdef USING_OPENCV
void from_opencv(unsigned char* buffer, size_t width, size_t height) {
allocate(width, height, 3);
T value;
size_t i;
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++) {
i = y * X() * C() + x * C() + (2 - c);
value = buffer[i];
img[idx(x, y, c)] = value;
}
}
}
}
#endif
|
55417e1e
David Mayerich
fixed data type l...
|
256
257
258
259
260
261
262
263
|
//Copy N data points from source to dest, casting while doing so
template<typename S, typename D>
void type_copy(S* source, D* dest, size_t N) {
if (typeid(S) == typeid(D)) //if both types are the same
memcpy(dest, source, N * sizeof(S)); //just use a memcpy
for (size_t n = 0; n < N; n++) //otherwise, iterate through each element
dest[n] = (D)source[n]; //copy and cast
}
|
c8c976a9
David Mayerich
replaced CImg wit...
|
264
|
/// Load an image from a file
|
d32a1854
David Mayerich
added framework f...
|
265
|
void load(std::string filename){
|
2e5e3a26
David Mayerich
added 2D convolut...
|
266
|
#ifdef USING_OPENCV
|
c8c976a9
David Mayerich
replaced CImg wit...
|
267
|
cv::Mat cvImage = cv::imread(filename, CV_LOAD_IMAGE_UNCHANGED); //use OpenCV to open the image file
|
a2bf1d08
David Mayerich
general bug fixes...
|
268
|
if(!cvImage.data){
|
814eb271
David Mayerich
fixed problems wi...
|
269
|
std::cout<<"ERROR stim::image::load() - unable to find image "<<filename<<std::endl;
|
a2bf1d08
David Mayerich
general bug fixes...
|
270
271
|
exit(1);
}
|
55417e1e
David Mayerich
fixed data type l...
|
272
|
int cv_type = cvImage.type();
|
26da82c8
David Mayerich
finalized stim::g...
|
273
274
275
276
|
int cols = cvImage.cols;
int rows = cvImage.rows;
int channels = cvImage.channels();
allocate(cols, rows, channels); //allocate space for the image
|
55417e1e
David Mayerich
fixed data type l...
|
277
|
size_t img_bytes = bytes();
|
ca99f951
David Mayerich
faster implementa...
|
278
|
unsigned char* cv_ptr = (unsigned char*)cvImage.data;
|
55417e1e
David Mayerich
fixed data type l...
|
279
280
|
if (C() == 1) //if this is a single-color image, just copy the data
type_copy<unsigned char, T>(cv_ptr, img, size());
|
814eb271
David Mayerich
fixed problems wi...
|
281
|
if(C() == 3) //if this is a 3-color image, OpenCV uses BGR interleaving
|
ca99f951
David Mayerich
faster implementa...
|
282
|
from_opencv(cv_ptr, X(), Y());
|
2e5e3a26
David Mayerich
added 2D convolut...
|
283
|
#else
|
d9b2b2a8
David Mayerich
enabled basic rea...
|
284
285
286
287
288
|
stim::filename file(filename);
if (file.extension() == "ppm")
load_netpbm(filename);
else if (file.extension() == "bmp")
load_bmp(filename);
|
2e5e3a26
David Mayerich
added 2D convolut...
|
289
|
#endif
|
ca99f951
David Mayerich
faster implementa...
|
290
291
|
}
|
2e5e3a26
David Mayerich
added 2D convolut...
|
292
|
|
d32a1854
David Mayerich
added framework f...
|
293
|
|
cfcf8619
David Mayerich
changes to filena...
|
294
295
|
//save a Netpbm file
void save_netpbm(std::string filename) {
|
683f216a
David Mayerich
fixed? Linux comp...
|
296
|
std::ofstream outfile(filename.c_str(), std::ios::out | std::ios::binary); //open an output file
|
cfcf8619
David Mayerich
changes to filena...
|
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
|
if(!outfile) {
std::cout << "Error generating output file in image::save_netpbm()" << std::endl;
exit(1);
}
if (sizeof(T) != 1) {
std::cout << "Error in image::save_netpbm() - data type must be 8-bit integer." << std::endl;
exit(1);
}
std::string format;
if (channels() == 1) outfile << "P5" << (char)0x0A; //output P5 if the file is grayscale
else if (channels() == 3) outfile << "P6" << (char)0x0A; //output P6 if the file is color
else {
std::cout << "Error in image::save_netpbm() - data must be grayscale or RGB." << std::endl;
exit(1);
}
|
2e5e3a26
David Mayerich
added 2D convolut...
|
312
313
314
|
size_t w = width();
size_t h = height();
outfile << w << " " << h << (char)0x0A; //save the width and height
|
cfcf8619
David Mayerich
changes to filena...
|
315
316
317
318
|
outfile << "255" << (char)0x0A; //output the maximum value
outfile.write((const char*)img, size()); //write the binary data
outfile.close();
}
|
d661ab7d
David Mayerich
linux fixes for s...
|
319
|
#ifndef USING_OPENCV
|
d9b2b2a8
David Mayerich
enabled basic rea...
|
320
321
322
|
void save_bmp(std::string filename) {
stim::save_bmp(filename, (char*)img, width(), height());
}
|
d661ab7d
David Mayerich
linux fixes for s...
|
323
|
#endif
|
d9b2b2a8
David Mayerich
enabled basic rea...
|
324
|
|
d32a1854
David Mayerich
added framework f...
|
325
326
|
//save a file
void save(std::string filename){
|
2e5e3a26
David Mayerich
added 2D convolut...
|
327
|
#ifdef USING_OPENCV
|
c8c976a9
David Mayerich
replaced CImg wit...
|
328
329
|
//OpenCV uses an interleaved format, so convert first and then output
T* buffer = (T*) malloc(bytes());
|
a2bf1d08
David Mayerich
general bug fixes...
|
330
331
332
333
|
if(C() == 1)
memcpy(buffer, img, bytes());
else if(C() == 3)
|
9b766f1f
Pavel Govyadinov
completed merge f...
|
334
|
get_interleaved_bgr(buffer);
|
c8c976a9
David Mayerich
replaced CImg wit...
|
335
336
|
cv::Mat cvImage((int)Y(), (int)X(), cv_type(), buffer);
cv::imwrite(filename, cvImage);
|
efe7b7cc
Pavel Govyadinov
Added a detailed ...
|
337
|
free(buffer);
|
2e5e3a26
David Mayerich
added 2D convolut...
|
338
|
#else
|
d9b2b2a8
David Mayerich
enabled basic rea...
|
339
340
341
342
343
344
345
346
347
|
stim::filename file(filename);
if (file.extension() == "ppm")
save_netpbm(filename);
else if (file.extension() == "bmp")
save_bmp(filename);
else {
std::cout << "stim::image ERROR: File type not supported without OpenCV. Make sure to link OpenCV and define USING_OPENCV" << std::endl;
exit(1);
}
|
2e5e3a26
David Mayerich
added 2D convolut...
|
348
|
#endif
|
d32a1854
David Mayerich
added framework f...
|
349
350
|
}
|
ca99f951
David Mayerich
faster implementa...
|
351
352
353
354
355
|
void set_interleaved(T* buffer, size_t width, size_t height, size_t channels){
allocate(width, height, channels);
memcpy(img, buffer, bytes());
}
|
8b7be670
David Mayerich
implemented savin...
|
356
|
//create an image from an interleaved buffer
|
814eb271
David Mayerich
fixed problems wi...
|
357
|
void set_interleaved_rgb(T* buffer, size_t width, size_t height){
|
ca99f951
David Mayerich
faster implementa...
|
358
|
set_interleaved(buffer, width, height, 3);
|
c8c976a9
David Mayerich
replaced CImg wit...
|
359
|
}
|
fbf0ab02
David Mayerich
added support for...
|
360
|
|
814eb271
David Mayerich
fixed problems wi...
|
361
362
|
void set_interleaved_bgr(T* buffer, size_t width, size_t height){
allocate(width, height, 3);
|
ca99f951
David Mayerich
faster implementa...
|
363
364
|
T value;
size_t i;
|
c8c976a9
David Mayerich
replaced CImg wit...
|
365
366
367
|
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++){
|
ca99f951
David Mayerich
faster implementa...
|
368
369
370
|
i = y * X() * C() + x * C() + (2-c);
value = buffer[i];
img[idx(x, y, c)] = value;
|
c8c976a9
David Mayerich
replaced CImg wit...
|
371
|
}
|
fbf0ab02
David Mayerich
added support for...
|
372
373
|
}
}
|
8b7be670
David Mayerich
implemented savin...
|
374
375
|
}
|
ca99f951
David Mayerich
faster implementa...
|
376
377
378
379
|
void set_interleaved(T* buffer, size_t width, size_t height){
set_interleaved_rgb(buffer, width, height);
}
|
9b766f1f
Pavel Govyadinov
completed merge f...
|
380
|
void get_interleaved_bgr(T* data){
|
8b7be670
David Mayerich
implemented savin...
|
381
382
|
//for each channel
|
c8c976a9
David Mayerich
replaced CImg wit...
|
383
384
385
386
387
388
389
|
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...
|
390
391
|
}
|
9b766f1f
Pavel Govyadinov
completed merge f...
|
392
393
394
395
|
void get_interleaved_rgb(T* data){
memcpy(data, img, bytes());
}
|
904614c3
David Mayerich
added normalizati...
|
396
397
398
399
400
401
402
403
404
405
406
407
|
//copies data in the given channel order as a non-interleaved image
void get_noninterleaved(T* data){
//for each channel
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[c * Y() * X() + y * X() + x] = img[idx(x, y, c)];
}
}
}
}
|
dbeb83f2
David Mayerich
added separable c...
|
408
409
|
/// Return an image representing a specified channel
/// @param c is the channel to be returned
|
86dfa80b
David Mayerich
added 2D gaussian...
|
410
|
image<T> channel(size_t c) const {
|
dbeb83f2
David Mayerich
added separable c...
|
411
|
image<T> r(X(), Y(), 1); //create a new image
|
c8c976a9
David Mayerich
replaced CImg wit...
|
412
413
|
for(size_t x = 0; x < X(); x++){
for(size_t y = 0; y < Y(); y++){
|
8e2fb2b4
David Mayerich
fixed a segmentat...
|
414
|
r.img[r.idx(x, y, 0)] = img[idx(x, y, c)];
|
c8c976a9
David Mayerich
replaced CImg wit...
|
415
416
|
}
}
|
c8c976a9
David Mayerich
replaced CImg wit...
|
417
|
return r;
|
dbeb83f2
David Mayerich
added separable c...
|
418
419
420
|
}
/// Returns an std::vector containing each channel as a separate image
|
683f216a
David Mayerich
fixed? Linux comp...
|
421
422
|
std::vector< image<T> > split() const {
std::vector< image<T> > r; //create an image array
|
dbeb83f2
David Mayerich
added separable c...
|
423
|
r.resize(C()); //create images for each channel
|
41acaf5d
David Mayerich
added a CUDA Gaus...
|
424
|
|
dbeb83f2
David Mayerich
added separable c...
|
425
426
427
428
|
for (size_t c = 0; c < C(); c++) { //for each channel
r[c] = channel(c); //copy the channel image to the array
}
return r;
|
41acaf5d
David Mayerich
added a CUDA Gaus...
|
429
430
|
}
|
86dfa80b
David Mayerich
added 2D gaussian...
|
431
|
/// Merge a series of single-channel images into a multi-channel image
|
683f216a
David Mayerich
fixed? Linux comp...
|
432
|
void merge(std::vector< image<T> >& list) {
|
86dfa80b
David Mayerich
added 2D gaussian...
|
433
434
435
436
437
438
439
|
size_t x = list[0].width(); //calculate the size of the image
size_t y = list[0].height();
allocate(x, y, list.size()); //re-allocate the image
for (size_t c = 0; c < list.size(); c++) //for each channel
set_channel(list[c].channel(0).data(), c); //insert the channel into the output image
}
|
c8c976a9
David Mayerich
replaced CImg wit...
|
440
441
|
T& operator()(size_t x, size_t y, size_t c = 0){
return img[idx(x, y, c)];
|
3d0b6243
David Mayerich
fixed hsiproc bug...
|
442
443
|
}
|
08ada8c2
David Mayerich
updated image to ...
|
444
445
446
447
448
|
/// This function returns a pixel reference based on a 1D index into the image
T& operator()(size_t i) {
return img[i];
}
|
3d0b6243
David Mayerich
fixed hsiproc bug...
|
449
450
451
|
/// Set all elements in the image to a given scalar value
/// @param v is the value used to set all values in the image
|
a8ad9192
David Mayerich
removed warnings ...
|
452
|
void set_all(T v) { //set all elements of the image to a given value v
|
c8c976a9
David Mayerich
replaced CImg wit...
|
453
|
size_t N = size();
|
a8ad9192
David Mayerich
removed warnings ...
|
454
455
456
457
|
for (size_t n = 0; n < N; n++) img[n] = v;
}
image<T> operator=(T v){
set_all(v);
|
3d0b6243
David Mayerich
fixed hsiproc bug...
|
458
|
return *this;
|
3d0b6243
David Mayerich
fixed hsiproc bug...
|
459
460
|
}
|
a7ed4b2e
David Mayerich
ivote updates
|
461
462
463
464
465
466
467
468
469
|
/// invert the image, given a specified maximum value (ex. maxval = 255, I' = 255 - I)
/*image<T> invert(T maxval) {
image<T> result(width(), height(), channels()); //create a new image
size_t N = size(); //get the number of elements in the image
for (size_t n = 0; n < N; n++)
result.data()[n] = maxval - img[n]; //perform the inversion and save the result to the new image
return result;
}*/
|
5bd6c411
David Mayerich
added contrast st...
|
470
471
472
473
|
/// Stretch the contrast of the image such that the minimum and maximum intensity match the given values
image<T> stretch(T low, T high) {
T maxval = maxv();
T minval = minv();
|
5bd6c411
David Mayerich
added contrast st...
|
474
|
image<T> result = *this; //create a new image for output
|
a8ad9192
David Mayerich
removed warnings ...
|
475
476
477
478
479
|
if (maxval == minval) { //if the minimum and maximum values are the same, return an image composed of low
result = low;
return result;
}
|
5bd6c411
David Mayerich
added contrast st...
|
480
|
size_t N = size(); //get the number of values in the image
|
d9b2b2a8
David Mayerich
enabled basic rea...
|
481
482
|
T range = maxval - minval; //calculate the current range of the image
T desired_range = high - low; //calculate the desired range of the image
|
5bd6c411
David Mayerich
added contrast st...
|
483
|
for (size_t n = 0; n < N; n++) { //for each element in the image
|
ec0fdb47
Mahsa Lotfollahi
changes in stretc...
|
484
|
result.data()[n] = desired_range * (img[n] - minval) / range + low;
|
5bd6c411
David Mayerich
added contrast st...
|
485
486
487
488
|
}
return result;
}
|
70f0baaf
Laila Saadatifard
update the image....
|
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
|
/// Add a border of width w with the given value around the image
/// @param w specifies the total size of the border
/// @param T is the pixel value (all channels will be the same)
image<T> border(size_t w, T value = 0) {
image<T> result(width() + w * 2, height() + w * 2, channels()); //create an output image
result = value; //assign the border value to all pixels in the new image
for (size_t y = 0; y < height(); y++) { //for each pixel in the original image
for (size_t x = 0; x < width(); x++) {
size_t n = (y + w) * (width() + w * 2) + x + w; //calculate the index of the corresponding pixel in the result image
size_t n0 = idx(x,y); //calculate the index for this pixel in the original image
result.data()[n] = img[n0]; // copy the original image to the result image afer the border area
}
}
return result;
}
|
276f9b23
David Mayerich
forced matching t...
|
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
|
/// Adds curcular padding for the specified number of pixels - in this case replicating the boundary pixels
image<T> pad_replicate(size_t p) {
image<T> result(width() + p * 2, height() + p * 2, channels()); //create an output image
result = 0;
//result = value; //assign the border value to all pixels in the new image
for (size_t y = 0; y < height(); y++) { //for each pixel in the original image
for (size_t x = 0; x < width(); x++) {
size_t n = (y + p) * (width() + p * 2) + x + p; //calculate the index of the corresponding pixel in the result image
size_t n0 = idx(x, y); //calculate the index for this pixel in the original image
result.data()[n] = img[n0]; // copy the original image to the result image afer the border area
}
}
size_t l = p;
size_t r = p + width() - 1;
size_t t = p;
size_t b = p + height() - 1;
for (size_t y = 0; y < p; y++) for (size_t x = l; x <= r; x++) result(x, y) = result(x, t); //pad the top
for (size_t y = b + 1; y < result.height(); y++) for (size_t x = l; x <= r; x++) result(x, y) = result(x, b); //pad the bottom
for (size_t y = t; y <= b; y++) for (size_t x = 0; x < l; x++) result(x, y) = result(l, y); //pad the left
for (size_t y = t; y <= b; y++) for (size_t x = r+1; x < result.width(); x++) result(x, y) = result(r, y); //pad the right
for (size_t y = 0; y < t; y++) for (size_t x = 0; x < l; x++) result(x, y) = result(l, t); //pad the top left
for (size_t y = 0; y < t; y++) for (size_t x = r+1; x < result.width(); x++) result(x, y) = result(r, t); //pad the top right
for (size_t y = b+1; y < result.height(); y++) for (size_t x = 0; x < l; x++) result(x, y) = result(l, b); //pad the bottom left
for (size_t y = b+1; y < result.height(); y++) for (size_t x = r + 1; x < result.width(); x++) result(x, y) = result(r, b); //pad the bottom right
return result;
}
|
f186dbda
Tianshu Cheng
header file for b...
|
532
533
534
535
536
|
/// 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...
|
537
|
void set_channel(T* buffer, size_t c){
|
6d30a707
Tianshu Cheng
add cuda/array_ad...
|
538
|
|
c8c976a9
David Mayerich
replaced CImg wit...
|
539
540
541
|
size_t x, y;
for(y = 0; y < Y(); y++){
for(x = 0; x < X(); x++){
|
2e5e3a26
David Mayerich
added 2D convolut...
|
542
|
img[idx(x, y, c)] = buffer[y * X() + x];
|
c8c976a9
David Mayerich
replaced CImg wit...
|
543
544
|
}
}
|
6d30a707
Tianshu Cheng
add cuda/array_ad...
|
545
546
|
}
|
86dfa80b
David Mayerich
added 2D gaussian...
|
547
|
size_t channels() const{
|
c8c976a9
David Mayerich
replaced CImg wit...
|
548
|
return C();
|
8b7be670
David Mayerich
implemented savin...
|
549
550
|
}
|
86dfa80b
David Mayerich
added 2D gaussian...
|
551
|
size_t width() const{
|
c8c976a9
David Mayerich
replaced CImg wit...
|
552
|
return X();
|
8b7be670
David Mayerich
implemented savin...
|
553
554
|
}
|
86dfa80b
David Mayerich
added 2D gaussian...
|
555
|
size_t height() const{
|
c8c976a9
David Mayerich
replaced CImg wit...
|
556
|
return Y();
|
3d0b6243
David Mayerich
fixed hsiproc bug...
|
557
558
|
}
|
6d30a707
Tianshu Cheng
add cuda/array_ad...
|
559
|
T* data(){
|
c8c976a9
David Mayerich
replaced CImg wit...
|
560
|
return img;
|
6d30a707
Tianshu Cheng
add cuda/array_ad...
|
561
562
|
}
|
7b3948ab
David Mayerich
added support for...
|
563
|
//returns the size (number of values) of the image
|
c8c976a9
David Mayerich
replaced CImg wit...
|
564
|
size_t size(){ return C() * X() * Y(); }
|
d32a1854
David Mayerich
added framework f...
|
565
|
|
faef7718
David Mayerich
updates to stim::...
|
566
|
/// Returns the number of nonzero values
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
567
|
size_t nnz(){
|
faef7718
David Mayerich
updates to stim::...
|
568
|
|
c8c976a9
David Mayerich
replaced CImg wit...
|
569
|
size_t N = X() * Y() * C();
|
faef7718
David Mayerich
updates to stim::...
|
570
|
|
c8c976a9
David Mayerich
replaced CImg wit...
|
571
572
573
|
size_t nz = 0;
for(size_t n = 0; n < N; n++)
if(img[n] != 0) nz++;
|
faef7718
David Mayerich
updates to stim::...
|
574
|
|
c8c976a9
David Mayerich
replaced CImg wit...
|
575
|
return nz; //return the number of nonzero pixels
|
faef7718
David Mayerich
updates to stim::...
|
576
577
578
579
|
}
//this function returns indices of pixels that have nonzero values
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
580
|
std::vector<size_t> sparse_idx(){
|
faef7718
David Mayerich
updates to stim::...
|
581
|
|
c8c976a9
David Mayerich
replaced CImg wit...
|
582
|
std::vector<size_t> s; //allocate an array
|
faef7718
David Mayerich
updates to stim::...
|
583
584
|
s.resize(nnz()); //allocate space in the array
|
c8c976a9
David Mayerich
replaced CImg wit...
|
585
586
|
size_t N = size();
//size_t C = channels();
|
faef7718
David Mayerich
updates to stim::...
|
587
|
|
c8c976a9
David Mayerich
replaced CImg wit...
|
588
|
//T* ptr = img.data(); //get a pointer to the image data
|
faef7718
David Mayerich
updates to stim::...
|
589
|
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
590
|
size_t i = 0;
|
c8c976a9
David Mayerich
replaced CImg wit...
|
591
592
593
594
|
for(size_t n = 0; n < N; n++){
if(img[n] != 0){
s[i] = n;
i++;
|
faef7718
David Mayerich
updates to stim::...
|
595
596
597
598
599
|
}
}
return s; //return the index list
}
|
6d30a707
Tianshu Cheng
add cuda/array_ad...
|
600
|
|
1a224b6a
David Mayerich
fixed linux compa...
|
601
|
|
6d30a707
Tianshu Cheng
add cuda/array_ad...
|
602
|
/// Returns the maximum pixel value in the image
|
96f9b10f
Laila Saadatifard
change the header...
|
603
|
T maxv(){
|
c8c976a9
David Mayerich
replaced CImg wit...
|
604
605
|
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...
|
606
|
|
c8c976a9
David Mayerich
replaced CImg wit...
|
607
|
for (size_t n=0; n<N; n++){ //for every value
|
6d30a707
Tianshu Cheng
add cuda/array_ad...
|
608
|
|
c8c976a9
David Mayerich
replaced CImg wit...
|
609
610
|
if (img[n] > max_val){ //if the value is higher than the current max
max_val = img[n];
|
1a224b6a
David Mayerich
fixed linux compa...
|
611
|
}
|
6d30a707
Tianshu Cheng
add cuda/array_ad...
|
612
|
}
|
1a224b6a
David Mayerich
fixed linux compa...
|
613
|
return max_val;
|
6d30a707
Tianshu Cheng
add cuda/array_ad...
|
614
|
}
|
d32a1854
David Mayerich
added framework f...
|
615
|
|
c8c976a9
David Mayerich
replaced CImg wit...
|
616
|
/// Returns the maximum pixel value in the image
|
96f9b10f
Laila Saadatifard
change the header...
|
617
|
T minv(){
|
c8c976a9
David Mayerich
replaced CImg wit...
|
618
619
|
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...
|
620
|
|
c8c976a9
David Mayerich
replaced CImg wit...
|
621
622
623
|
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...
|
624
|
}
|
6d30a707
Tianshu Cheng
add cuda/array_ad...
|
625
626
|
}
|
1a224b6a
David Mayerich
fixed linux compa...
|
627
|
return min_val;
|
6d30a707
Tianshu Cheng
add cuda/array_ad...
|
628
629
|
}
|
a2bf1d08
David Mayerich
general bug fixes...
|
630
631
632
633
634
635
|
/// 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...
|
636
|
|
a2bf1d08
David Mayerich
general bug fixes...
|
637
638
|
return r; //return the inverted image
}
|
a2bf1d08
David Mayerich
general bug fixes...
|
639
|
|
3c17c706
David Mayerich
added a crop func...
|
640
641
642
643
644
645
646
647
648
649
650
651
652
653
|
image<T> crop(size_t x0, size_t y0, size_t w, size_t h){
image<T> result(w, h, C()); //create the output cropped image
size_t srci;
size_t dsti;
size_t line_bytes = w * C(); //calculate the number of bytes in a line
for (size_t yi = 0; yi < h; yi++) { //for each row in the cropped image
srci = (y0 + yi) * X() * C() + x0 * C(); //calculate the source index
dsti = yi * w * C(); //calculate the destination index
memcpy(&result.img[dsti], &img[srci], line_bytes); //copy the data
}
return result;
}
|
e702aa4e
David Mayerich
implemented array...
|
654
|
//crop regions given by an array of 1D index values
|
276f9b23
David Mayerich
forced matching t...
|
655
|
std::vector< image<T> > crop_idx(size_t w, size_t h, std::vector<size_t> idx) {
|
e702aa4e
David Mayerich
implemented array...
|
656
657
658
659
660
661
662
663
664
665
666
|
std::vector<image<T>> result(idx.size()); //create an array of image files to return
for (size_t i = 0; i < idx.size(); i++) { //for each specified index point
size_t y = idx[i] / X(); //calculate the y coordinate from the 1D index (center of ROI)
size_t x = idx[i] - y * X(); //calculate the x coordinate (center of ROI)
y -= w / 2; //update x and y values to reflect the lower corner of the ROI
x -= h / 2;
result[i] = crop(x, y, w, h); //get the cropped image and store it in the result array
}
return result;
}
|
66304f4f
David Mayerich
added an addition...
|
667
668
669
670
671
672
673
674
675
|
//operator functions
image<T> operator+(image<T> rhs) {
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] = img[n] + rhs.img[n]; //perform the inversion
return r; //return the inverted image
}
|
6d30a707
Tianshu Cheng
add cuda/array_ad...
|
676
|
image<T> srgb2lab(){
|
c8c976a9
David Mayerich
replaced CImg wit...
|
677
678
|
std::cout<<"ERROR stim::image::srgb2lab - function has been broken, re-implement."<<std::endl;
exit(1);
|
6d30a707
Tianshu Cheng
add cuda/array_ad...
|
679
680
681
|
}
image<T> convolve2(image<T> mask){
|
c8c976a9
David Mayerich
replaced CImg wit...
|
682
683
|
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...
|
684
|
}
|
d32a1854
David Mayerich
added framework f...
|
685
686
|
|
f186dbda
Tianshu Cheng
header file for b...
|
687
|
image<T> rotate(float angle, float cx, float cy){
|
c8c976a9
David Mayerich
replaced CImg wit...
|
688
689
|
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...
|
690
|
}
|
945ee13c
Laila Saadatifard
the get_list func...
|
691
|
|
945ee13c
Laila Saadatifard
the get_list func...
|
692
693
|
// leila's code for non_interleaving data in 3D
//create an data set from an interleaved buffer
|
9d3ba0b1
David Mayerich
added stim::hsi a...
|
694
|
void set_interleaved3(T* buffer, size_t width, size_t height, size_t depth, size_t channels = 3){
|
c8c976a9
David Mayerich
replaced CImg wit...
|
695
696
|
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...
|
697
|
}
|
1a224b6a
David Mayerich
fixed linux compa...
|
698
|
|
dbeb83f2
David Mayerich
added separable c...
|
699
|
/// Casting operator, casts every value in an image to a different data type V
|
2e5e3a26
David Mayerich
added 2D convolut...
|
700
701
|
template<typename V>
operator image<V>() {
|
dbeb83f2
David Mayerich
added separable c...
|
702
703
704
|
image<V> r(X(), Y(), C()); //create a new image
std::copy(img, img + size(), r.data()); //copy and cast the data
return r; //return the new image
|
2e5e3a26
David Mayerich
added 2D convolut...
|
705
706
|
}
|
d32a1854
David Mayerich
added framework f...
|
707
708
|
};
|
7b3948ab
David Mayerich
added support for...
|
709
710
|
}; //end namespace stim
|
d32a1854
David Mayerich
added framework f...
|
711
712
|
#endif
|