Commit 6dcc460e79106d5240be259023155d84ea07dae2
1 parent
7fab7a98
cPb+tPb
Showing
17 changed files
with
844 additions
and
13 deletions
Show diff stats
CMakeLists.txt
... | ... | @@ -7,6 +7,9 @@ project(bsds500) |
7 | 7 | #set the module directory |
8 | 8 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}") |
9 | 9 | |
10 | +#find OpenCV | |
11 | +find_package(OpenCV REQUIRED ) | |
12 | + | |
10 | 13 | #set up CUDA |
11 | 14 | find_package(CUDA REQUIRED) |
12 | 15 | |
... | ... | @@ -20,6 +23,7 @@ find_package(Threads) |
20 | 23 | find_package(X11) |
21 | 24 | |
22 | 25 | include_directories( |
26 | + ${OpenCV_INCLUDE_DIRS} | |
23 | 27 | ${STIM_INCLUDE_DIRS} |
24 | 28 | ) |
25 | 29 | |
... | ... | @@ -41,6 +45,7 @@ cuda_add_executable(bsds500 |
41 | 45 | target_link_libraries(bsds500 |
42 | 46 | #${CUDA_cufft_LIBRARY} |
43 | 47 | #${CUDA_cublas_LIBRARY} |
48 | + ${OpenCV_LIBS} | |
44 | 49 | ${CMAKE_THREAD_LIBS_INIT} |
45 | 50 | ${X11_LIBRARIES} |
46 | 51 | ) |
... | ... | @@ -48,5 +53,6 @@ target_link_libraries(bsds500 |
48 | 53 | #copy an image test case |
49 | 54 | configure_file(data/101085.bmp 101085.bmp COPYONLY) |
50 | 55 | configure_file(data/101087.bmp 101087.bmp COPYONLY) |
56 | +configure_file(data/101087_square.bmp 101087_square.bmp COPYONLY) | |
51 | 57 | configure_file(data/slice00.bmp slice00.bmp COPYONLY) |
52 | 58 | configure_file(data/slice00_500_500.bmp slice00_500_500.bmp COPYONLY) | ... | ... |
1 | +#include <stim/image/image.h> | |
2 | +//#include <cmath> | |
3 | +#include <stim/visualization/colormap.h> | |
4 | +#include <stim/image/image_contour_detection.h> | |
5 | + | |
6 | +void array_abs(float* img, unsigned int N); | |
7 | +void array_multiply(float* lhs, float rhs, unsigned int N); | |
8 | +void array_cos(float* ptr1, float* cpu_out, unsigned int N); | |
9 | +void array_sin(float* ptr1, float* cpu_out, unsigned int N); | |
10 | +void array_atan(float* ptr1, float* cpu_out, unsigned int N); | |
11 | +void array_divide(float* ptr1, float* ptr2,float* cpu_quotient, unsigned int N); | |
12 | +void array_multiply(float* ptr1, float* ptr2, float* product, unsigned int N); | |
13 | +void array_add(float* ptr1, float* ptr2, float* sum, unsigned int N); | |
14 | + | |
15 | +/// This function uses odd-symmetric gaussian derivative filter to evaluate | |
16 | +/// the max probability of a contour on one scale, given an one-channel image | |
17 | + | |
18 | +/// @param img is an one-channel image | |
19 | +/// @param r is an array of radii for different scaled discs(filters) | |
20 | +/// @param sigma_n is the number of standard deviations used to define the sigma | |
21 | + | |
22 | +stim::image<float> Pb(stim::image<float> image, int r, unsigned int sigma_n){ | |
23 | + | |
24 | + unsigned int w = image.width(); // get the width of picture | |
25 | + unsigned int h = image.height(); // get the height of picture | |
26 | + unsigned N = w * h; // get the number of pixels of picture | |
27 | + int winsize = 2 * r + 1; // set the winsdow size of disc(filter) | |
28 | + | |
29 | + stim::image<float> I(w, h, 1, 2); // allocate space for return image of Gd1 | |
30 | + stim::image<float> theta(w, h); // allocate space for theta matrix | |
31 | + stim::image<float> cos(w, h); // allocate space for cos(theta) | |
32 | + stim::image<float> sin(w, h); // allocate space for sin(theta) | |
33 | + stim::image<float> temp(w, h); // allocate space for temp | |
34 | + stim::image<float> Ix(w, h); // allocate space for Ix | |
35 | + stim::image<float> Iy(w, h); // allocate space for Iy | |
36 | + stim::image<float> Pb(w, h); // allocate space for Pb | |
37 | + | |
38 | + I = Gd1(image, r, sigma_n); // calculate the Ix, Iy | |
39 | + Ix = I.channel(0); | |
40 | + array_abs(Ix.data(), N); //get |Ix|; | |
41 | + //stim::cpu2image(Ix.data(), "data_output/Pb_Ix_0924.bmp", w, h, stim::cmBrewer); | |
42 | + Iy = I.channel(1); | |
43 | + array_abs(Iy.data(), N); //get |Iy|; | |
44 | + //stim::cpu2image(Iy.data(), "data_output/Pb_Iy_0924.bmp", w, h, stim::cmBrewer); | |
45 | + | |
46 | + array_divide(Iy.data(), Ix.data(), temp.data(), N); //temp = Iy./Ix | |
47 | + array_atan(temp.data(), theta.data(), N); //theta = atan(temp) | |
48 | + array_cos(theta.data(), cos.data(), N); //cos = cos(theta) | |
49 | + array_sin(theta.data(), sin.data(), N); //sin = sin(theta) | |
50 | + array_multiply(Ix.data(), cos.data(), Ix.data(), N); //Ix = Ix.*cos | |
51 | + array_multiply(Iy.data(), sin.data(), Iy.data(), N); //Iy = Iy.*sin | |
52 | + array_add(Ix.data(), Iy.data(), Pb.data(), N); //Pb = Ix + Iy; | |
53 | + | |
54 | + float max = Pb.maxv(); // get the maximum of Pb used for normalization | |
55 | + array_multiply(Pb.data(), 1/max, N); // normalize the Pb | |
56 | + | |
57 | + //stim::cpu2image(Pb.data(), "data_output/Pb_0924.bmp", w, h, stim::cmBrewer); show the Pb(optional) | |
58 | + | |
59 | + return Pb; | |
60 | + | |
61 | +} | |
0 | 62 | \ No newline at end of file | ... | ... |
1 | +#include <stim/image/image.h> | |
2 | +#include <cmath> | |
3 | +#include <stim/visualization/colormap.h> | |
4 | +#include <stim/image/image_contour_detection.h> | |
5 | +#include <sstream> | |
6 | + | |
7 | + | |
8 | +void array_multiply(float* lhs, float rhs, unsigned int N); | |
9 | +void array_add(float* ptr1, float* ptr2, float* sum, unsigned int N); | |
10 | + | |
11 | +/// This function evaluates the cPb given an multi-channel image | |
12 | + | |
13 | +/// @param img is the multi-channel image | |
14 | +/// @param r is an array of radii for different scaled discs(filters) | |
15 | +/// @param alpha is is an array of weights for different scaled discs(filters) | |
16 | +/// @param s is the number of scales | |
17 | + | |
18 | +stim::image<float> cPb(stim::image<float> img, int* r, float* alpha, int s){ | |
19 | + | |
20 | + unsigned int w = img.width(); // get the width of picture | |
21 | + unsigned int h = img.height(); // get the height of picture | |
22 | + unsigned int c = img.channels(); // get the channels of picture | |
23 | + | |
24 | + | |
25 | + stim::image<float> cPb(w, h, 1); // allocate space for cPb | |
26 | + unsigned size = cPb.size(); // get the size of cPb | |
27 | + memset ( cPb.data(), 0, size * sizeof(float)); // initialize all the pixels of cPb to 0 | |
28 | + | |
29 | + | |
30 | + unsigned int N = w * h; // get the number of pixels | |
31 | + int sigma_n = 3; // set the number of standard deviations used to define the sigma | |
32 | + | |
33 | + std::ostringstream ss; // (optional) set the stream to designate the test result file | |
34 | + | |
35 | + stim::image<float> temp; // set the temporary image to store the addtion result | |
36 | + | |
37 | + for (int i = 0; i < c; i++){ | |
38 | + for (int j = 0; j < s; j++){ | |
39 | + | |
40 | + ss << "data_output/cPb_slice"<< i*s + j << ".bmp"; // set the name for test result file (optional) | |
41 | + std::string sss = ss.str(); | |
42 | + | |
43 | + // get the gaussian gradient by convolving each image slice with the mask | |
44 | + temp = Pb(img.channel(i), r[i*s + j], sigma_n); | |
45 | + | |
46 | + // output the test result of each slice (optional) | |
47 | + //stim::cpu2image(temp.data(), sss, w, h, stim::cmBrewer); | |
48 | + | |
49 | + // multiply each gaussian gradient with its weight | |
50 | + array_multiply(temp.data(), alpha[i*s + j], N); | |
51 | + | |
52 | + // add up all the weighted gaussian gradients | |
53 | + array_add(cPb.data(), temp.data(), cPb.data(), N); | |
54 | + | |
55 | + ss.str(""); //(optional) clear the space for stream | |
56 | + | |
57 | + } | |
58 | + } | |
59 | + | |
60 | + float max = cPb.maxv(); // get the maximum of cPb used for normalization | |
61 | + array_multiply(cPb.data(), 1/max, N); // normalize the cPb | |
62 | + | |
63 | + // output the test result of cPb (optional) | |
64 | + //stim::cpu2image(cPb.data(), "data_output/cPb_0916.bmp", w, h, stim::cmBrewer); | |
65 | + | |
66 | + return cPb; | |
67 | +} | ... | ... |
cudafunc.cu
1 | 1 | #include <stim/cuda/arraymath.cuh> |
2 | - | |
3 | -/*void blur(float* image, float sigma, unsigned int x, unsigned int y){ | |
4 | - | |
5 | - stim::cuda::cpu_gaussian_blur_2d<float>(image, sigma, x, y); | |
6 | -}*/ | |
2 | +#include <stim/cuda/templates/conv2.cuh> | |
3 | +#include <stim/cuda/templates/conv2sep.cuh> | |
4 | +#include <stim/cuda/templates/chi_gradient.cuh> | |
7 | 5 | |
8 | 6 | void array_multiply(float* lhs, float rhs, unsigned int N){ |
9 | 7 | |
... | ... | @@ -16,6 +14,12 @@ void array_add(float* ptr1, float* ptr2, float* sum, unsigned int N){ |
16 | 14 | |
17 | 15 | } |
18 | 16 | |
17 | +void array_multiply(float* ptr1, float* ptr2, float* product, unsigned int N){ | |
18 | + | |
19 | + stim::cuda::cpu_add(ptr1, ptr2, product, N); | |
20 | + | |
21 | +} | |
22 | + | |
19 | 23 | void conv2(float* img, float* mask, float* cpu_copy, unsigned int w, unsigned int h, unsigned int M){ |
20 | 24 | |
21 | 25 | stim::cuda::cpu_conv2(img, mask, cpu_copy, w, h, M); |
... | ... | @@ -28,3 +32,41 @@ void array_abs(float* img, unsigned int N){ |
28 | 32 | |
29 | 33 | } |
30 | 34 | |
35 | +void conv2_sep(float* img, unsigned int x, unsigned int y, float* kernel0, unsigned int k0, float* kernel1, unsigned int k1){ | |
36 | + | |
37 | + stim::cuda::cpu_conv2sep(img, x, y, kernel0, k0, kernel1, k1); | |
38 | + | |
39 | +} | |
40 | + | |
41 | +void array_cos(float* ptr1, float* cpu_out, unsigned int N){ | |
42 | + | |
43 | + stim::cuda::cpu_cos(ptr1, cpu_out, N); | |
44 | + | |
45 | +} | |
46 | + | |
47 | +void array_sin(float* ptr1, float* cpu_out, unsigned int N){ | |
48 | + | |
49 | + stim::cuda::cpu_sin(ptr1, cpu_out, N); | |
50 | + | |
51 | +} | |
52 | + | |
53 | +void array_atan(float* ptr1, float* cpu_out, unsigned int N){ | |
54 | + | |
55 | + stim::cuda::cpu_atan(ptr1, cpu_out, N); | |
56 | + | |
57 | +} | |
58 | + | |
59 | +void array_divide(float* ptr1, float* ptr2,float* cpu_quotient, unsigned int N){ | |
60 | + | |
61 | + stim::cuda::cpu_divide(ptr1, ptr2, cpu_quotient, N); | |
62 | + | |
63 | +} | |
64 | + | |
65 | +void chi_grad(float* img, float* cpu_copy, unsigned int w, unsigned int h, int r, unsigned int bin_n, unsigned int bin_size, float theta){ | |
66 | + | |
67 | + stim::cuda::cpu_chi_grad(img, cpu_copy, w, h, r, bin_n, bin_size, theta); | |
68 | + | |
69 | +} | |
70 | + | |
71 | + | |
72 | + | ... | ... |
1 | +#include <stim/image/image.h> | |
2 | +//#include <cmath> | |
3 | +#include <stim/visualization/colormap.h> | |
4 | +#include <stim/image/image_contour_detection.h> | |
5 | + | |
6 | +/// This function generates the first-order gaussian derivative filter gx gy, | |
7 | +/// convolves the image with gx gy, | |
8 | +/// and returns an image class which channel(0) is Ix and channel(1) is Iy | |
9 | + | |
10 | +/// @param img is the one-channel image | |
11 | +/// @param r is an array of radii for different scaled discs(filters) | |
12 | +/// @param sigma_n is the number of standard deviations used to define the sigma | |
13 | + | |
14 | +void conv2_sep(float* img, unsigned int x, unsigned int y, float* kernel0, unsigned int k0, float* kernel1, unsigned int k1); | |
15 | +//void array_abs(float* img, unsigned int N); | |
16 | + | |
17 | +stim::image<float> Gd1(stim::image<float> image, int r, unsigned int sigma_n){ | |
18 | + | |
19 | + unsigned int w = image.width(); // get the width of picture | |
20 | + unsigned int h = image.height(); // get the height of picture | |
21 | + unsigned N = w * h; // get the number of pixels of picture | |
22 | + int winsize = 2 * r + 1; // set the winsdow size of disc(filter) | |
23 | + float sigma = float(r)/float(sigma_n); // calculate the sigma used in gaussian function | |
24 | + | |
25 | + stim::image<float> I(w, h, 1, 2); // allocate space for return image class | |
26 | + stim::image<float> Ix(w, h); // allocate space for Ix | |
27 | + stim::image<float> Iy(w, h); // allocate space for Iy | |
28 | + Ix = image; // initialize Ix | |
29 | + Iy = image; // initialize Iy | |
30 | + | |
31 | + float* array_x1; | |
32 | + array_x1 = new float[winsize]; //allocate space for the 1D x-oriented gaussian derivative filter array_x1 for gx | |
33 | + float* array_y1; | |
34 | + array_y1 = new float[winsize]; //allocate space for the 1D y-oriented gaussian derivative filter array_y1 for gx | |
35 | + float* array_x2; | |
36 | + array_x2 = new float[winsize]; //allocate space for the 1D x-oriented gaussian derivative filter array_x2 for gy | |
37 | + float* array_y2; | |
38 | + array_y2 = new float[winsize]; //allocate space for the 1D y-oriented gaussian derivative filter array_y2 for gy | |
39 | + | |
40 | + | |
41 | + for (int i = 0; i < winsize; i++){ | |
42 | + | |
43 | + int x = i - r; //range of x | |
44 | + int y = i - r; //range of y | |
45 | + | |
46 | + // create the 1D x-oriented gaussian derivative filter array_x1 for gx | |
47 | + array_x1[i] = (-1) * x * exp((-1)*(pow(x, 2))/(2*pow(sigma, 2))); | |
48 | + // create the 1D y-oriented gaussian derivative filter array_y1 for gx | |
49 | + array_y1[i] = exp((-1)*(pow(y, 2))/(2*pow(sigma, 2))); | |
50 | + // create the 1D x-oriented gaussian derivative filter array_x2 for gy | |
51 | + array_x2[i] = exp((-1)*(pow(x, 2))/(2*pow(sigma, 2))); | |
52 | + // create the 1D y-oriented gaussian derivative filter array_y2 for gy | |
53 | + array_y2[i] = (-1) * y * exp((-1)*(pow(y, 2))/(2*pow(sigma, 2))); | |
54 | + } | |
55 | + | |
56 | + //stim::cpu2image(array_x1, "data_output/array_x1_0915.bmp", winsize, 1, stim::cmBrewer); // (optional) show the mask result | |
57 | + //stim::cpu2image(array_y1, "data_output/array_y1_0915.bmp", winsize, 1, stim::cmBrewer); // (optional) show the mask result | |
58 | + //stim::cpu2image(array_x2, "data_output/array_x2_0915.bmp", winsize, 1, stim::cmBrewer); // (optional) show the mask result | |
59 | + //stim::cpu2image(array_y2, "data_output/array_y2_0915.bmp", winsize, 1, stim::cmBrewer); // (optional) show the mask result | |
60 | + | |
61 | + // get Ix by convolving the image with gx | |
62 | + conv2_sep(Ix.data(), w, h, array_x1, winsize, array_y1, winsize); | |
63 | + | |
64 | + //stim::cpu2image(Ix.data(), "data_output/Ix_0915.bmp", w, h, stim::cmBrewer); | |
65 | + // get Iy by convolving the image with gy | |
66 | + conv2_sep(Iy.data(), w, h, array_x2, winsize, array_y2, winsize); | |
67 | + | |
68 | + //stim::cpu2image(Iy.data(), "data_output/Iy_0915.bmp", w, h, stim::cmBrewer); | |
69 | + | |
70 | + delete [] array_x1; //free the memory of array_x1 | |
71 | + delete [] array_y1; //free the memory of array_y1 | |
72 | + delete [] array_x2; //free the memory of array_x2 | |
73 | + delete [] array_y2; //free the memory of array_y2 | |
74 | + | |
75 | + I.set_channel(0, Ix.data()); | |
76 | + I.set_channel(1, Iy.data()); | |
77 | + | |
78 | + return I; | |
79 | + | |
80 | +} | |
0 | 81 | \ No newline at end of file | ... | ... |
1 | +#include <stim/image/image.h> | |
2 | +//#include <cmath> | |
3 | +#include <stim/visualization/colormap.h> | |
4 | +#include <stim/image/image_contour_detection.h> | |
5 | + | |
6 | +/// This function generates the second-order gaussian derivative filter gxx gyy, | |
7 | +/// convolves the image with gxx gyy, | |
8 | +/// and returns an image class which channel(0) is Ixx and channel(1) is Iyy | |
9 | + | |
10 | +/// @param img is the one-channel image | |
11 | +/// @param r is an array of radii for different scaled discs(filters) | |
12 | +/// @param sigma_n is the number of standard deviations used to define the sigma | |
13 | + | |
14 | +void conv2_sep(float* img, unsigned int x, unsigned int y, float* kernel0, unsigned int k0, float* kernel1, unsigned int k1); | |
15 | +//void array_abs(float* img, unsigned int N); | |
16 | + | |
17 | +stim::image<float> Gd2(stim::image<float> image, int r, unsigned int sigma_n){ | |
18 | + | |
19 | + unsigned int w = image.width(); // get the width of picture | |
20 | + unsigned int h = image.height(); // get the height of picture | |
21 | + unsigned N = w * h; // get the number of pixels of picture | |
22 | + int winsize = 2 * r + 1; // set the winsdow size of disc(filter) | |
23 | + float sigma = float(r)/float(sigma_n); // calculate the sigma used in gaussian function | |
24 | + | |
25 | + stim::image<float> I(w, h, 1, 2); // allocate space for return image class | |
26 | + stim::image<float> Ixx(w, h); // allocate space for Ixx | |
27 | + stim::image<float> Iyy(w, h); // allocate space for Iyy | |
28 | + Ixx = image; // initialize Ixx | |
29 | + Iyy = image; // initialize Iyy | |
30 | + | |
31 | + float* array_x1; | |
32 | + array_x1 = new float[winsize]; //allocate space for the 1D x-oriented gaussian derivative filter array_x1 for gxx | |
33 | + float* array_y1; | |
34 | + array_y1 = new float[winsize]; //allocate space for the 1D y-oriented gaussian derivative filter array_y1 for gxx | |
35 | + float* array_x2; | |
36 | + array_x2 = new float[winsize]; //allocate space for the 1D x-oriented gaussian derivative filter array_x2 for gyy | |
37 | + float* array_y2; | |
38 | + array_y2 = new float[winsize]; //allocate space for the 1D y-oriented gaussian derivative filter array_y2 for gyy | |
39 | + | |
40 | + | |
41 | + for (int i = 0; i < winsize; i++){ | |
42 | + | |
43 | + int x = i - r; //range of x | |
44 | + int y = i - r; //range of y | |
45 | + | |
46 | + // create the 1D x-oriented gaussian derivative filter array_x1 for gxx | |
47 | + array_x1[i] = (-1) * (1 - pow(x, 2)) * exp((-1)*(pow(x, 2))/(2*pow(sigma, 2))); | |
48 | + // create the 1D y-oriented gaussian derivative filter array_y1 for gxx | |
49 | + array_y1[i] = exp((-1)*(pow(y, 2))/(2*pow(sigma, 2))); | |
50 | + // create the 1D x-oriented gaussian derivative filter array_x2 for gyy | |
51 | + array_x2[i] = exp((-1)*(pow(x, 2))/(2*pow(sigma, 2))); | |
52 | + // create the 1D y-oriented gaussian derivative filter array_y2 for gyy | |
53 | + array_y2[i] = (-1) * (1 - pow(y, 2)) * exp((-1)*(pow(y, 2))/(2*pow(sigma, 2))); | |
54 | + } | |
55 | + | |
56 | + //stim::cpu2image(array_x1, "data_output/array_x1_0915.bmp", winsize, 1, stim::cmBrewer); // (optional) show the mask result | |
57 | + //stim::cpu2image(array_y1, "data_output/array_y1_0915.bmp", winsize, 1, stim::cmBrewer); // (optional) show the mask result | |
58 | + //stim::cpu2image(array_x2, "data_output/array_x2_0915.bmp", winsize, 1, stim::cmBrewer); // (optional) show the mask result | |
59 | + //stim::cpu2image(array_y2, "data_output/array_y2_0915.bmp", winsize, 1, stim::cmBrewer); // (optional) show the mask result | |
60 | + | |
61 | + // get Ixx by convolving the image with gxx | |
62 | + conv2_sep(Ixx.data(), w, h, array_x1, winsize, array_y1, winsize); | |
63 | + | |
64 | + //stim::cpu2image(Ixx.data(), "data_output/Ixx_0915.bmp", w, h, stim::cmBrewer); | |
65 | + // get Iyy by convolving the image with gyy | |
66 | + conv2_sep(Iyy.data(), w, h, array_x2, winsize, array_y2, winsize); | |
67 | + | |
68 | + //stim::cpu2image(Iyy.data(), "data_output/Iyy_0915.bmp", w, h, stim::cmBrewer); | |
69 | + | |
70 | + delete [] array_x1; //free the memory of array_x1 | |
71 | + delete [] array_y1; //free the memory of array_y1 | |
72 | + delete [] array_x2; //free the memory of array_x2 | |
73 | + delete [] array_y2; //free the memory of array_y2 | |
74 | + | |
75 | + I.set_channel(0, Ixx.data()); | |
76 | + I.set_channel(1, Iyy.data()); | |
77 | + | |
78 | + return I; | |
79 | + | |
80 | +} | |
0 | 81 | \ No newline at end of file | ... | ... |
1 | +#include <stim/image/image.h> | |
2 | +#include <cmath> | |
3 | +#include <stim/visualization/colormap.h> | |
4 | +#include <stim/image/image_contour_detection.h> | |
5 | + | |
6 | +#define PI 3.1415926 | |
7 | + | |
8 | +void array_multiply(float* lhs, float rhs, unsigned int N); | |
9 | +void array_add(float* ptr1, float* ptr2, float* sum, unsigned int N); | |
10 | +void array_abs(float* img, unsigned int N); | |
11 | + | |
12 | +/// This function evaluates the center-surround(Laplacian of Gaussian) gaussian derivative gradient of an one-channel image | |
13 | + | |
14 | +/// @param img is the one-channel image | |
15 | +/// @param r is an array of radii for different scaled discs(filters) | |
16 | +/// @param sigma_n is the number of standard deviations used to define the sigma | |
17 | + | |
18 | +stim::image<float> Gd_center(stim::image<float> image, int r, unsigned int sigma_n){ | |
19 | + | |
20 | + unsigned int w = image.width(); // get the width of picture | |
21 | + unsigned int h = image.height(); // get the height of picture | |
22 | + unsigned N = w * h; // get the number of pixels of picture | |
23 | + int winsize = 2 * r + 1; // set the winsdow size of disc(filter) | |
24 | + | |
25 | + stim::image<float> I(w, h, 1, 2); // allocate space for return image of Gd2 | |
26 | + stim::image<float> Ixx(w, h); // allocate space for Ixx | |
27 | + stim::image<float> Iyy(w, h); // allocate space for Iyy | |
28 | + stim::image<float> Gd_center(w, h); // allocate space for Pb | |
29 | + | |
30 | + I = Gd2(image, r, sigma_n); // calculate the Ixx, Iyy | |
31 | + Ixx = I.channel(0); | |
32 | + Iyy = I.channel(1); | |
33 | + | |
34 | + array_add(Ixx.data(), Iyy.data(), Gd_center.data(), N); //Gd_center = Ixx + Iyy; | |
35 | + array_abs(Gd_center.data(), N); | |
36 | + | |
37 | + //stim::cpu2image(Gd_center.data(), "data_output/Gd_center_0919.bmp", w, h, stim::cmBrewer); | |
38 | + | |
39 | + return Gd_center; | |
40 | + | |
41 | +} | ... | ... |
1 | +#include <stim/image/image.h> | |
2 | +#include <cmath> | |
3 | +#include <stim/visualization/colormap.h> | |
4 | +#include <stim/image/image_contour_detection.h> | |
5 | + | |
6 | +/// This function evaluates the theta-dependent even-symmetric gaussian derivative gradient of an one-channel image | |
7 | + | |
8 | +/// @param img is the one-channel image | |
9 | +/// @param r is an array of radii for different scaled discs(filters) | |
10 | +/// @param sigma_n is the number of standard deviations used to define the sigma | |
11 | +/// @param theta is angle used for computing the gradient | |
12 | + | |
13 | +void conv2(float* img, float* mask, float* cpu_copy, unsigned int w, unsigned int h, unsigned int M); | |
14 | +void array_abs(float* img, unsigned int N); | |
15 | + | |
16 | +stim::image<float> Gd_even(stim::image<float> image, int r, unsigned int sigma_n, float theta){ | |
17 | + | |
18 | + unsigned int w = image.width(); // get the width of picture | |
19 | + unsigned int h = image.height(); // get the height of picture | |
20 | + unsigned N = w * h; // get the number of pixels of picture | |
21 | + int winsize = 2 * r + 1; // set the winsdow size of disc(filter) | |
22 | + float sigma = float(r)/float(sigma_n); // calculate the sigma used in gaussian function | |
23 | + | |
24 | + stim::image<float> I(w, h, 1, 2); // allocate space for return image class | |
25 | + stim::image<float> Gd_even_theta(w, h); // allocate space for Gd_even_theta | |
26 | + stim::image<float> mask_x(winsize, winsize); // allocate space for x-axis-oriented filter | |
27 | + stim::image<float> mask_r(winsize, winsize); // allocate space for theta-oriented filter | |
28 | + | |
29 | + for (int j = 0; j < winsize; j++){ | |
30 | + for (int i = 0; i< winsize; i++){ | |
31 | + | |
32 | + int x = i - r; //range of x | |
33 | + int y = j - r; //range of y | |
34 | + | |
35 | + // create the x-oriented gaussian derivative filter mask_x | |
36 | + mask_x.data()[j*winsize + i] = (-1) * (1 - pow(x, 2)) * exp((-1)*(pow(x, 2))/(2*pow(sigma, 2))) * exp((-1)*(pow(y, 2))/(2*pow(sigma, 2))); | |
37 | + | |
38 | + } | |
39 | + } | |
40 | + | |
41 | + mask_r = mask_x.rotate(theta, r, r); | |
42 | + //mask_r = mask_x.rotate(45, r, r); | |
43 | + //stim::cpu2image(mask_r.data(), "data_output/mask_r_0919.bmp", winsize, winsize, stim::cmBrewer); | |
44 | + | |
45 | + // do the 2D convolution with image and mask | |
46 | + conv2(image.data(), mask_r.data(), Gd_even_theta.data(), w, h, winsize); | |
47 | + array_abs(Gd_even_theta.data(), N); | |
48 | + | |
49 | + //stim::cpu2image(Gd_even_theta.data(), "data_output/Gd_even_theta_0919.bmp", w, h, stim::cmGrayscale); | |
50 | + | |
51 | + return Gd_even_theta; | |
52 | +} | |
0 | 53 | \ No newline at end of file | ... | ... |
1 | +#include <stim/image/image.h> | |
2 | +#include <cmath> | |
3 | +#include <stim/visualization/colormap.h> | |
4 | +#include <stim/image/image_contour_detection.h> | |
5 | + | |
6 | +#define PI 3.1415926 | |
7 | + | |
8 | +void array_multiply(float* lhs, float rhs, unsigned int N); | |
9 | +void array_add(float* ptr1, float* ptr2, float* sum, unsigned int N); | |
10 | +void array_abs(float* img, unsigned int N); | |
11 | + | |
12 | +/// This function evaluates the theta-dependent odd symmetric gaussian derivative gradient of an one-channel image | |
13 | + | |
14 | +/// @param img is the one-channel image | |
15 | +/// @param r is an array of radii for different scaled discs(filters) | |
16 | +/// @param sigma_n is the number of standard deviations used to define the sigma | |
17 | +/// @param theta is angle used for computing the gradient | |
18 | + | |
19 | +stim::image<float> Gd_odd(stim::image<float> image, int r, unsigned int sigma_n, float theta){ | |
20 | + | |
21 | + float theta_r = (theta * PI)/180; //change angle unit from degree to rad | |
22 | + | |
23 | + unsigned int w = image.width(); // get the width of picture | |
24 | + unsigned int h = image.height(); // get the height of picture | |
25 | + unsigned N = w * h; // get the number of pixels of picture | |
26 | + int winsize = 2 * r + 1; // set the winsdow size of disc(filter) | |
27 | + | |
28 | + stim::image<float> I(w, h, 1, 2); // allocate space for return image of Gd1 | |
29 | + stim::image<float> Ix(w, h); // allocate space for Ix | |
30 | + stim::image<float> Iy(w, h); // allocate space for Iy | |
31 | + stim::image<float> Gd_odd_theta(w, h); // allocate space for Pb | |
32 | + | |
33 | + I = Gd1(image, r, sigma_n); // calculate the Ix, Iy | |
34 | + Ix = I.channel(0); | |
35 | + Iy = I.channel(1); | |
36 | + | |
37 | + array_multiply(Ix.data(), cos(theta_r), N); //Ix = Ix*cos(theta_r) | |
38 | + array_multiply(Iy.data(), sin(theta_r), N); //Iy = Iy*sin(theta_r) | |
39 | + array_add(Ix.data(), Iy.data(), Gd_odd_theta.data(), N); //Gd_odd_theta = Ix + Iy; | |
40 | + array_abs(Gd_odd_theta.data(), N); | |
41 | + | |
42 | + //stim::cpu2image(I.channel(0).data(), "data_output/Gd_odd_x_0919.bmp", w, h, stim::cmBrewer); | |
43 | + //stim::cpu2image(I.channel(1).data(), "data_output/Gd_odd_y_0919.bmp", w, h, stim::cmBrewer); | |
44 | + //stim::cpu2image(Gd_odd_theta.data(), "data_output/Gd_odd_theta_0919.bmp", w, h, stim::cmBrewer); | |
45 | + | |
46 | + return Gd_odd_theta; | |
47 | + | |
48 | +} | ... | ... |
1 | +#include <stim/image/image.h> | |
2 | +//#include <cmath> | |
3 | +#include <stim/visualization/colormap.h> | |
4 | +#include <stim/image/image_contour_detection.h> | |
5 | +#include <opencv2/opencv.hpp> | |
6 | +#include <iostream> | |
7 | + | |
8 | +/// This function use cvkmeans to cluster given textons | |
9 | + | |
10 | +/// @param testons is a multi-channel image | |
11 | +/// @param k is the number of clusters | |
12 | + | |
13 | +stim::image<float> kmeans(stim::image<float> textons, unsigned int K){ | |
14 | + | |
15 | + unsigned int w = textons.width(); // get the width of picture | |
16 | + unsigned int h = textons.height(); // get the height of picture | |
17 | + unsigned int feature_n = textons.channels(); // get the spectrum of picture | |
18 | + unsigned int N = w * h; // get the number of pixels | |
19 | + | |
20 | + float* sample1 = (float*) malloc(sizeof(float) * N * feature_n); //allocate the space for textons | |
21 | + | |
22 | + //reallocate a multi-channel texton image to a single-channel image | |
23 | + for(unsigned int c = 0; c < feature_n; c++){ | |
24 | + | |
25 | + stim::image<float> temp; | |
26 | + temp = textons.channel(c); | |
27 | + | |
28 | + for(unsigned int j = 0; j < N; j++){ | |
29 | + | |
30 | + sample1[c + j * feature_n] = temp.data()[j]; | |
31 | + } | |
32 | + } | |
33 | + | |
34 | + | |
35 | + cv::Mat sample2(N, feature_n, CV_32F, sample1); //copy image to cv::mat | |
36 | + | |
37 | + //(optional) show the test result | |
38 | + //imshow("sample2", sample2); | |
39 | + | |
40 | + | |
41 | + cv::TermCriteria criteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, 0.1); // set stop-criteria for kmeans iteration | |
42 | + cv::Mat labels(N, 1, CV_8U, cvScalarAll(0)); // allocate space for kmeans output | |
43 | + cv::Mat centers; // allocate space for kmeans output | |
44 | + | |
45 | + unsigned int test_times = 2; // set the number of times of trying kmeans, it will return the best result | |
46 | + | |
47 | + cv::kmeans(sample2, K, labels, criteria, test_times, cv::KMEANS_PP_CENTERS, centers); // kmeans clustering | |
48 | + | |
49 | + //(optional) show the test result | |
50 | + //imwrite( "data_output/labels_1D.bmp", labels); | |
51 | + | |
52 | + stim::image<float> texture(w, h, 1, 1); // allocate space for texture | |
53 | + | |
54 | + for(unsigned int i = 0; i < N; i++){ // reshape the labels from iD array to image | |
55 | + | |
56 | + texture.data()[i] = labels.at<int>(i); | |
57 | + | |
58 | + } | |
59 | + | |
60 | + //texture.save("data_output/kmeans_test0924_2.bmp"); | |
61 | + | |
62 | + //(optional) show the test result | |
63 | + //stim::cpu2image(texture.data(), "data_output/kmeans_test.bmp", w, h, stim::cmBrewer); | |
64 | + | |
65 | + return texture; | |
66 | + | |
67 | +} | |
0 | 68 | \ No newline at end of file | ... | ... |
1 | +#include <stim/image/image.h> | |
2 | +#include <cmath> | |
3 | +#include <stim/visualization/colormap.h> | |
4 | +#include <stim/image/image_contour_detection.h> | |
5 | +#include <iostream> | |
6 | +#include <stim/visualization/colormap.h> | |
7 | + | |
8 | +/// calculate the cPb, tPb and mPb given a multi-channel image | |
9 | + | |
10 | +void array_multiply(float* lhs, float rhs, unsigned int N); | |
11 | +void array_add(float* ptr1, float* ptr2, float* sum, unsigned int N); | |
12 | + | |
13 | +int main() | |
14 | +{ | |
15 | + stim::image<float> image; // generate an image object | |
16 | + | |
17 | + image.load("101085.bmp"); // load the input image | |
18 | + //image.load("slice00_500_500.bmp"); // load the input image | |
19 | + image = image.channel(0); // get the first channel of black-and-white image | |
20 | + | |
21 | + | |
22 | + unsigned int w = image.width(); // get the width of picture | |
23 | + unsigned int h = image.height(); // get the height of picture | |
24 | + unsigned int N = w * h; // get the number of pixels | |
25 | + int c = image.channels(); // get the number if channels of picture | |
26 | + int s = 3; // set the number of scales | |
27 | + int r1[3] = {3,5,10}; // set an array of radii for different scaled discs(filters) for cPb, the length of r is c*s | |
28 | + int r2[3] = {5,10,20}; // set an array of radii for different scaled discs(filters) for tPb, the length of r is c*s | |
29 | + float alpha[3] = {1,1,1}; // set an array of weights for different scaled discs(filters) | |
30 | + unsigned int theta_n = 8; // set the number of angles used in filter orientation | |
31 | + unsigned int bin_n = 16; // set the number of bins used in chi-distance | |
32 | + unsigned int K = 16; // set the number of cludters, K should be multiple of bin_n | |
33 | + | |
34 | + stim::image<float> img_cPb(w, h); // allocate the space for cPb | |
35 | + stim::image<float> img_tPb(w, h); // allocate the space for tPb | |
36 | + stim::image<float> img_mPb(w, h); // allocate the space for tPb | |
37 | + | |
38 | + std::cout<<"imagesize: "<< w <<"*"<< h <<'\n'; | |
39 | + | |
40 | + //*******************cPb******************** | |
41 | + std::cout<<"begin cPb"<<'\n'; | |
42 | + | |
43 | + | |
44 | + std::clock_t start1; // (optional) set the timer to calculate the total time | |
45 | + start1 = std::clock(); // (optional) set timer start point | |
46 | + | |
47 | + img_cPb = cPb(image, r1, alpha, s); | |
48 | + | |
49 | + // show the cPb (optional) | |
50 | + stim::cpu2image(img_cPb.data(), "data_output/img_cPb_0925.bmp", w, h, stim::cmBrewer); | |
51 | + | |
52 | + double duration1 = ( std::clock() - start1 ) / (double) CLOCKS_PER_SEC; // (optional) calculate the total time | |
53 | + std::cout<<"cPb time: "<< duration1 <<"s"<<'\n'; // (optional) show the total time | |
54 | + | |
55 | + | |
56 | + //*******************tPb******************** | |
57 | + std::cout<<"begin tPb"<<'\n'; | |
58 | + | |
59 | + | |
60 | + std::clock_t start2; // (optional) set the timer to calculate the total time | |
61 | + start2 = std::clock(); // (optional) set timer start point | |
62 | + | |
63 | + img_tPb = tPb(image, r2, alpha, theta_n, bin_n, s, K); | |
64 | + | |
65 | + // show the tPb (optional) | |
66 | + stim::cpu2image(img_tPb.data(), "data_output/img_tPb_0925.bmp", w, h, stim::cmBrewer); | |
67 | + | |
68 | + double duration2 = ( std::clock() - start2 ) / (double) CLOCKS_PER_SEC; // (optional) calculate the total time | |
69 | + std::cout<<"tPb time: "<< duration2 <<"s"<<'\n'; // (optional) show the total time | |
70 | + | |
71 | + | |
72 | + //******************************************* | |
73 | + | |
74 | + double duration3 = ( std::clock() - start1 ) / (double) CLOCKS_PER_SEC; // (optional) calculate the total time | |
75 | + std::cout<<"total running time: "<< duration3 <<"s"<<'\n'; // (optional) show the total time | |
76 | + | |
77 | + //******************mPb********************** | |
78 | + // set parameters for linear combination | |
79 | + float a = 1; | |
80 | + float b = 0.5; | |
81 | + | |
82 | + // create mPb by linearly combined cPb and tPb | |
83 | + array_multiply(img_cPb.data(), a, N); | |
84 | + array_multiply(img_tPb.data(), b, N); | |
85 | + array_add(img_cPb.data(), img_tPb.data(), img_mPb.data(), N); | |
86 | + | |
87 | + // show the mPb (optional) | |
88 | + stim::cpu2image(img_mPb.data(), "data_output/img_mPb_0925.bmp", w, h, stim::cmBrewer); | |
89 | + | |
90 | + return 0; | |
91 | + | |
92 | +} | ... | ... |
fun_mPb_theta.cpp renamed to old version/fun_mPb_theta.cpp
func_mPb.cpp renamed to old version/func_mPb.cpp
... | ... | @@ -11,6 +11,7 @@ |
11 | 11 | /// @param r is an array of radii for different scaled discs(filters) |
12 | 12 | /// @param alpha is an array of weights for different scaled discs(filters) |
13 | 13 | /// @param s is the number of scales |
14 | + | |
14 | 15 | stim::image<float> func_mPb(stim::image<float> img, unsigned int theta_n, int* r, float* alpha, int s){ |
15 | 16 | |
16 | 17 | std::clock_t start; // (optional) set the timer to calculate the total time |
... | ... | @@ -34,8 +35,8 @@ stim::image<float> func_mPb(stim::image<float> img, unsigned int theta_n, int* r |
34 | 35 | |
35 | 36 | for (unsigned int n = 0; n < theta_n; n++){ |
36 | 37 | |
37 | - ss << "data_output/mPb_theta"<< n << "_0911.bmp"; // (optional) set the name for test result file | |
38 | - std::string sss = ss.str(); // (optional) | |
38 | + //ss << "data_output/mPb_theta"<< n << "_0911.bmp"; // (optional) set the name for test result file | |
39 | + //std::string sss = ss.str(); // (optional) | |
39 | 40 | float theta = 180 * ((float)n/theta_n); // calculate the even-splited angle for each mPb_theta |
40 | 41 | |
41 | 42 | mPb_theta = func_mPb_theta(img, theta, r, alpha, s); // calculate the mPb_theta |
... | ... | @@ -50,7 +51,7 @@ stim::image<float> func_mPb(stim::image<float> img, unsigned int theta_n, int* r |
50 | 51 | unsigned long idx = n * w * h * 1; //index for the nth mPb_theta |
51 | 52 | |
52 | 53 | |
53 | - stim::cpu2image(mPb_theta.data(), sss, w, h, stim::cmBrewer); // (optional) output the nth mPb_theta | |
54 | + //stim::cpu2image(mPb_theta.data(), sss, w, h, stim::cmBrewer); // (optional) output the nth mPb_theta | |
54 | 55 | |
55 | 56 | for(unsigned long i = 0; i < N; i++){ |
56 | 57 | |
... | ... | @@ -65,11 +66,11 @@ stim::image<float> func_mPb(stim::image<float> img, unsigned int theta_n, int* r |
65 | 66 | } |
66 | 67 | |
67 | 68 | |
68 | - ss.str(""); //(optional) clear the space for stream | |
69 | + //ss.str(""); //(optional) clear the space for stream | |
69 | 70 | |
70 | 71 | } |
71 | 72 | |
72 | - stim::cpu2image(mPb.data(), "data_output/mPb_500_0911_neat.bmp", w, h, stim::cmBrewer); // output the mPb | |
73 | + stim::cpu2image(mPb.data(), "data_output/mPb_500_0914_neat.bmp", w, h, stim::cmBrewer); // output the mPb | |
73 | 74 | |
74 | 75 | double duration2 = ( std::clock() - start ) / (double) CLOCKS_PER_SEC; // (optional) calculate the total time |
75 | 76 | std::cout<<"total time:"<< duration2 <<"s"<<'\n'; // (optional) show the total time | ... | ... |
gauss_derivative_odd.cpp renamed to old version/gauss_derivative_odd.cpp
... | ... | @@ -12,7 +12,7 @@ void array_multiply(float* lhs, float rhs, unsigned int N); |
12 | 12 | |
13 | 13 | /// @param img is the one-channel image |
14 | 14 | /// @param r is an array of radii for different scaled discs(filters) |
15 | -// @param sigma_n is the number of standard deviations used to define the sigma | |
15 | +/// @param sigma_n is the number of standard deviations used to define the sigma | |
16 | 16 | /// @param theta is angle used for computing the gradient |
17 | 17 | |
18 | 18 | stim::image<float> gaussian_derivative_filter_odd(stim::image<float> image, int r, unsigned int sigma_n, float theta){ |
... | ... | @@ -28,8 +28,12 @@ stim::image<float> gaussian_derivative_filter_odd(stim::image<float> image, int |
28 | 28 | stim::image<float> mask_theta(winsize, winsize);// allocate space for theta-oriented filter |
29 | 29 | stim::image<float> derivative_theta(w, h); // allocate space for theta-oriented gradient |
30 | 30 | |
31 | + stim::image<float> mask_r; | |
32 | + | |
33 | + | |
31 | 34 | float theta_r = (theta * PI)/180; //change angle unit from degree to rad |
32 | 35 | |
36 | + //*************inseparable convolution**************** | |
33 | 37 | for (int j = 0; j < winsize; j++){ |
34 | 38 | for (int i = 0; i< winsize; i++){ |
35 | 39 | |
... | ... | @@ -46,14 +50,37 @@ stim::image<float> gaussian_derivative_filter_odd(stim::image<float> image, int |
46 | 50 | } |
47 | 51 | } |
48 | 52 | |
53 | + mask_r = mask_x.rotate(90, r, r); | |
54 | + stim::cpu2image(mask_r.data(), "data_output/mask_r90_0915.bmp", winsize, winsize, stim::cmBrewer); | |
55 | + //stim::cpu2image(mask_theta.data(), "data_output/mask_0911_2.bmp", winsize, winsize, stim::cmBrewer); // (optional) show the mask result | |
56 | + | |
57 | + // do the 2D convolution with image and mask | |
58 | + conv2(image.data(), mask_theta.data(), derivative_theta.data(), w, h, winsize); | |
59 | + //*********************************************************/ | |
60 | + | |
61 | + /*************separable convolution**************** | |
62 | + for (int i = 0; i < winsize; i++){ | |
63 | + | |
64 | + int x = i - r; //range of x | |
65 | + int y = i - r; //range of y | |
66 | + | |
67 | + // create the 1D x-oriented gaussian derivative filter array_x | |
68 | + array_x[i] = exp((-1)*(pow(x, 2))/(2*pow(sigma, 2))); | |
69 | + // create the 1D y-oriented gaussian derivative filter array_y | |
70 | + array_y[i] = (-1) * y * exp((-1)*(pow(y, 2))/(2*pow(sigma, 2))); | |
71 | + | |
72 | + | |
73 | + } | |
74 | + | |
49 | 75 | //stim::cpu2image(mask_theta.data(), "data_output/mask_0911_2.bmp", winsize, winsize, stim::cmBrewer); // (optional) show the mask result |
50 | 76 | |
51 | 77 | // do the 2D convolution with image and mask |
52 | 78 | conv2(image.data(), mask_theta.data(), derivative_theta.data(), w, h, winsize); |
79 | + //*********************************************************/ | |
53 | 80 | |
54 | 81 | array_abs(derivative_theta.data(), N); // get the absolute value for each pixel (why slower than the "for loop" method sometimes?) |
55 | 82 | |
56 | - float max = derivative_theta.max(); // get the maximum of gradient used for normalization | |
83 | + float max = derivative_theta.maxv(); // get the maximum of gradient used for normalization | |
57 | 84 | array_multiply(derivative_theta.data(), 1/max, N); // normalize the gradient |
58 | 85 | |
59 | 86 | ... | ... |
test_main.cpp renamed to old version/test_main - Copy.cpp
... | ... | @@ -3,19 +3,27 @@ |
3 | 3 | #include <stim/visualization/colormap.h> |
4 | 4 | #include <stim/image/image_contour_detection.h> |
5 | 5 | #include <iostream> |
6 | +#include <stim/visualization/colormap.h> | |
7 | + | |
6 | 8 | /// calculate the mPb given a multi-channel image |
7 | 9 | |
8 | 10 | int main() |
9 | 11 | { |
10 | 12 | stim::image<float> img; // generate an image object |
13 | + //stim::image<float> img_r; | |
11 | 14 | |
12 | - img.load("slice00_500_500.bmp"); // load the input image | |
15 | + //img.load("slice00_500_500.bmp"); // load the input image | |
16 | + img.load("101087_square.bmp"); // load the input image | |
13 | 17 | img = img.channel(0); // get the first channel of black-and-white image |
14 | 18 | |
15 | 19 | unsigned int w = img.width(); // get the width of picture |
16 | 20 | unsigned int h = img.height(); // get the height of picture |
17 | 21 | int c = img.channels(); // get the number if channels of picture |
18 | 22 | int s = 3; // set the number of scales |
23 | + | |
24 | + //img_r = img.rotate(45, w/2, h/2); | |
25 | + //stim::cpu2image(img_r.data(), "data_output/rotate_0915.bmp", w, h, stim::cmBrewer); | |
26 | + | |
19 | 27 | |
20 | 28 | int r[3] = {3,5,10}; // set an array of radii for different scaled discs(filters) |
21 | 29 | float alpha[3] = {1,1,1}; // set an array of weights for different scaled discs(filters) | ... | ... |
1 | +#include <stim/image/image.h> | |
2 | +#include <cmath> | |
3 | +#include <stim/visualization/colormap.h> | |
4 | +#include <stim/image/image_contour_detection.h> | |
5 | +#include <sstream> | |
6 | + | |
7 | + | |
8 | +void array_multiply(float* lhs, float rhs, unsigned int N); | |
9 | +void array_add(float* ptr1, float* ptr2, float* sum, unsigned int N); | |
10 | +void chi_grad(float* img, float* cpu_copy, unsigned int w, unsigned int h, int r, unsigned int bin_n, unsigned int bin_size, float theta); | |
11 | + | |
12 | +/// This function evaluates the tPb given a grayscale image | |
13 | + | |
14 | +/// @param img is the multi-channel image | |
15 | +/// @param theta_n is the number of angles used for computing oriented chi-gradient | |
16 | +/// @param r is an array of radii for different scaled discs(filters) | |
17 | +/// @param alpha is is an array of weights for different scaled discs(filters) | |
18 | +/// @param s is the number of scales | |
19 | +/// @param K is the number of clusters | |
20 | + | |
21 | +stim::image<float> tPb(stim::image<float> img, int* r, float* alpha, unsigned int theta_n, unsigned int bin_n, int s, unsigned K){ | |
22 | + | |
23 | + unsigned int w = img.width(); // get the width of picture | |
24 | + unsigned int h = img.height(); // get the height of picture | |
25 | + unsigned int N = w * h; // get the number of pixels | |
26 | + | |
27 | + stim::image<float> img_textons(w, h, 1, theta_n*2+1); // allocate space for img_textons | |
28 | + stim::image<float> img_texture(w, h, 1, 1); // allocate space for img_texture | |
29 | + stim::image<float> tPb_theta(w, h, 1, 1); // allocate space for tPb_theta | |
30 | + stim::image<float> tPb(w, h, 1, 1); // allocate space for tPb | |
31 | + unsigned size = tPb_theta.size(); // get the size of tPb_theta | |
32 | + memset (tPb.data(), 0, size * sizeof(float)); // initialize all the pixels of tPb to 0 | |
33 | + stim::image<float> temp(w, h, 1, 1); // set the temporary image to store the addtion result | |
34 | + | |
35 | + std::ostringstream ss; // (optional) set the stream to designate the test result file | |
36 | + | |
37 | + | |
38 | + img_textons = textons(img, theta_n); | |
39 | + | |
40 | + img_texture = kmeans(img_textons, K); // changing kmeans result into float type is required | |
41 | + | |
42 | + stim::cpu2image(img_texture.data(), "data_output/texture_0925.bmp", w, h, stim::cmBrewer); | |
43 | + | |
44 | + | |
45 | + unsigned int max1 = img_texture.maxv(); // get the maximum of Pb used for normalization | |
46 | + unsigned int bin_size = (max1 + 1)/bin_n; // (whether"+1" or not depends on kmeans result) | |
47 | + | |
48 | + for (int i = 0; i < theta_n; i++){ | |
49 | + | |
50 | + float theta = 180 * ((float)i/theta_n); // calculate the even-splited angle for each tPb_theta | |
51 | + | |
52 | + memset (tPb_theta.data(), 0, size * sizeof(float)); // initialize all the pixels of tPb_theta to 0 | |
53 | + | |
54 | + //ss << "data_output/0922tPb_theta"<< theta << ".bmp"; // set the name for test result file (optional) | |
55 | + //std::string sss = ss.str(); | |
56 | + | |
57 | + for (int j = 0; j < s; j++){ | |
58 | + | |
59 | + // get the chi-gradient by convolving each image slice with the mask | |
60 | + chi_grad(img_texture.data(), temp.data(), w, h, r[j], bin_n, bin_size, theta); | |
61 | + | |
62 | + float max2 = temp.maxv(); // get the maximum of tPb_theta used for normalization | |
63 | + array_multiply(temp.data(), 1/max2, N); // normalize the tPb_theta | |
64 | + | |
65 | + //output the test result of each slice (optional) | |
66 | + //stim::cpu2image(temp.data(), "data_output/tPb_slice0924_2.bmp", w, h, stim::cmBrewer); | |
67 | + | |
68 | + // multiply each chi-gradient with its weight | |
69 | + array_multiply(temp.data(), alpha[j], N); | |
70 | + | |
71 | + // add up all the weighted chi-gradients | |
72 | + array_add(tPb_theta.data(), temp.data(), tPb_theta.data(), N); | |
73 | + | |
74 | + | |
75 | + } | |
76 | + | |
77 | + //ss.str(""); //(optional) clear the space for stream | |
78 | + | |
79 | + for(unsigned long ti = 0; ti < N; ti++){ | |
80 | + | |
81 | + if(tPb_theta.data()[ti] > tPb.data()[ti]){ //get the maximum value among all tPb_theta for ith pixel | |
82 | + tPb.data()[ti] = tPb_theta.data()[ti]; | |
83 | + } | |
84 | + | |
85 | + else{ | |
86 | + } | |
87 | + } | |
88 | + } | |
89 | + | |
90 | + float max3 = tPb.maxv(); // get the maximum of tPb used for normalization | |
91 | + array_multiply(tPb.data(), 1/max3, N); // normalize the tPb | |
92 | + | |
93 | + //output the test result of tPb (optional) | |
94 | + //stim::cpu2image(tPb.data(), "data_output/tPb_0922.bmp", w, h, stim::cmBrewer); | |
95 | + | |
96 | + return tPb; | |
97 | +} | ... | ... |
1 | +#include <stim/image/image.h> | |
2 | +//#include <cmath> | |
3 | +#include <stim/visualization/colormap.h> | |
4 | +#include <stim/image/image_contour_detection.h> | |
5 | +#include <sstream> | |
6 | + | |
7 | +/// This function convolve the grayscale image with a set of oriented Gaussian | |
8 | +/// derivative filters, and return a texton image with (theta_n*2+1) channels | |
9 | + | |
10 | +/// @param image is an one-channel grayscale image | |
11 | +/// @param theta_n is the number of angles used for computing the gradient | |
12 | + | |
13 | +stim::image<float> textons(stim::image<float> image, unsigned int theta_n){ | |
14 | + | |
15 | + unsigned int w = image.width(); // get the width of picture | |
16 | + unsigned int h = image.height(); // get the height of picture | |
17 | + unsigned N = w * h; // get the number of pixels of picture | |
18 | + | |
19 | + stim::image<float> textons(w, h, 1, theta_n*2+1); // allocate space for textons | |
20 | + stim::image<float> temp(w, h); // allocate space for temp | |
21 | + | |
22 | + unsigned int r_odd = 3; // set disc radii for odd-symmetric filter | |
23 | + unsigned int sigma_n_odd = 3; // set sigma_n for odd-symmetric filter | |
24 | + unsigned int r_even = 3; // set disc radii for even-symmetric filter | |
25 | + unsigned int sigma_n_even = 3; // set sigma_n for even-symmetric filter | |
26 | + unsigned int r_center = 3; // set disc radii for center-surround filter | |
27 | + unsigned int sigma_n_center = 3; // set sigma_n for center-surround filter | |
28 | + | |
29 | + //std::ostringstream ss1, ss2; // (optional) set the stream to designate the test result file | |
30 | + | |
31 | + for (unsigned int i = 0; i < theta_n; i++){ | |
32 | + | |
33 | + //ss1 << "data_output/textons_channel_"<< i << ".bmp"; // set the name for test result file (optional) | |
34 | + //std::string sss1 = ss1.str(); | |
35 | + //ss2 << "data_output/textons_channel_"<< i+theta_n << ".bmp"; // set the name for test result file (optional) | |
36 | + //std::string sss2 = ss2.str(); | |
37 | + | |
38 | + float theta = 180 * ((float)i/theta_n); // calculate the even-splited angle for each oriented filter | |
39 | + | |
40 | + temp = Gd_odd(image, r_odd, sigma_n_odd, theta); // return Gd_odd to temp | |
41 | + //stim::cpu2image(temp.data(), sss1, w, h, stim::cmBrewer); | |
42 | + textons.set_channel(i, temp.data()); // copy temp to ith channel of textons | |
43 | + | |
44 | + temp = Gd_even(image, r_even, sigma_n_even, theta); // return Gd_even to temp | |
45 | + //stim::cpu2image(temp.data(), sss2, w, h, stim::cmBrewer); | |
46 | + textons.set_channel(i + theta_n, temp.data()); // copy temp to (i+theta_n)th channel of textons | |
47 | + | |
48 | + //ss1.str(""); //(optional) clear the space for stream | |
49 | + //ss2.str(""); //(optional) clear the space for stream | |
50 | + | |
51 | + } | |
52 | + | |
53 | + temp = Gd_center(image, r_center, sigma_n_center); // return Gd_center to temp | |
54 | + //stim::cpu2image(temp.data(), "data_output/textons_channel_16.bmp", w, h, stim::cmBrewer); | |
55 | + textons.set_channel(theta_n*2, temp.data()); // copy temp to (theta_n*2)th channel of textons | |
56 | + | |
57 | + return textons; | |
58 | + | |
59 | +} | |
60 | + | |
61 | + | |
0 | 62 | \ No newline at end of file | ... | ... |