Skip to content

Commit 6f79855

Browse files
committed
added ccv_filter unit test. find a bug in ccv_normalize, should
affect the accuracy of sift impl, and now sift should be much more accurate (200% improve due to the bug fix)
1 parent 8b73713 commit 6f79855

File tree

9 files changed

+54
-9
lines changed

9 files changed

+54
-9
lines changed

bin/siftmatch.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ int main(int argc, char** argv)
1818
unsigned int elapsed_time = get_current_time();
1919
ccv_sift_param_t param;
2020
param.noctaves = 3;
21-
param.nlevels = 8;
21+
param.nlevels = 6;
2222
param.up2x = 1;
2323
param.edge_threshold = 10;
2424
param.norm_threshold = 0;
@@ -56,7 +56,7 @@ int main(int argc, char** argv)
5656
mind2 = d;
5757
}
5858
}
59-
if (mind < mind2 * 0.6)
59+
if (mind < mind2 * 0.36)
6060
{
6161
ccv_keypoint_t* op = (ccv_keypoint_t*)ccv_array_get(obj_keypoints, i);
6262
ccv_keypoint_t* kp = (ccv_keypoint_t*)ccv_array_get(image_keypoints, minj);

lib/ccv.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -361,8 +361,8 @@ int ccv_serialize(ccv_dense_matrix_t* mat, char* out, int* len, int type, void*
361361
double ccv_trace(ccv_matrix_t* mat);
362362

363363
enum {
364-
CCV_L2_NORM = 0x00,
365-
CCV_L1_NORM = 0x01,
364+
CCV_L2_NORM = 0x01,
365+
CCV_L1_NORM = 0x02,
366366
};
367367

368368
double ccv_norm(ccv_matrix_t* mat, int type);

lib/ccv_algebra.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,32 @@ double ccv_normalize(ccv_matrix_t* a, ccv_matrix_t** b, int btype, int l_type)
2424
btype = (btype == 0) ? CCV_GET_DATA_TYPE(da->type) | CCV_C1 : CCV_GET_DATA_TYPE(btype) | CCV_C1;
2525
ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, da->rows, da->cols, CCV_ALL_DATA_TYPE | CCV_C1, btype, sig);
2626
ccv_cache_return(db, 0);
27-
double sum = 0;
27+
double sum = 0, inv;
2828
int i, j;
2929
unsigned char* a_ptr = da->data.ptr;
3030
unsigned char* b_ptr = db->data.ptr;
3131
switch (l_type)
3232
{
33+
case CCV_L1_NORM:
34+
#define for_block(__for_set, __for_get) \
35+
for (i = 0; i < da->rows; i++) \
36+
{ \
37+
for (j = 0; j < da->cols; j++) \
38+
sum += __for_get(a_ptr, j, 0); \
39+
a_ptr += da->step; \
40+
} \
41+
inv = 1.0 / sum; \
42+
a_ptr = da->data.ptr; \
43+
for (i = 0; i < da->rows; i++) \
44+
{ \
45+
for (j = 0; j < da->cols; j++) \
46+
__for_set(b_ptr, j, __for_get(a_ptr, j, 0) * inv, 0); \
47+
a_ptr += da->step; \
48+
b_ptr += db->step; \
49+
}
50+
ccv_matrix_setter(db->type, ccv_matrix_getter, da->type, for_block);
51+
#undef for_block
52+
break;
3353
case CCV_L2_NORM:
3454
#define for_block(__for_set, __for_get) \
3555
for (i = 0; i < da->rows; i++) \
@@ -39,7 +59,7 @@ double ccv_normalize(ccv_matrix_t* a, ccv_matrix_t** b, int btype, int l_type)
3959
a_ptr += da->step; \
4060
} \
4161
sum = sqrt(sum); \
42-
double inv = 1.0 / sqrt(sum); \
62+
inv = 1.0 / sum; \
4363
a_ptr = da->data.ptr; \
4464
for (i = 0; i < da->rows; i++) \
4565
{ \

samples/nature.png

812 KB
Loading

test/algebra.tests.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ TEST_CASE("vector L2 normalize")
4949
for (i = 0; i < 10; i++)
5050
dmt->data.fl[i] = i;
5151
ccv_normalize(dmt, (ccv_matrix_t**)&dmt, 0, CCV_L2_NORM);
52-
float hm[10] = {0.000000, 0.243382, 0.486764, 0.730147, 0.973529, 1.216911, 1.460293, 1.703675, 1.947057, 2.190440};
52+
float hm[10] = {0.000000, 0.059235, 0.118470, 0.177705, 0.236940, 0.296174, 0.355409, 0.414644, 0.473879, 0.533114};
5353
REQUIRE_ARRAY_EQ_WITH_TOLERANCE(float, hm, dmt->data.fl, 10, 1e-6, "10d vector L2 normalize failure");
5454
ccv_matrix_free(dmt);
5555
ccv_garbage_collect();

test/data/nature.filter.bin

1.83 MB
Binary file not shown.

test/numeric.tests.c

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "ccv.h"
22
#include "case.h"
3+
#include "ccv_case.h"
34

45
int rosenbrock(const ccv_dense_matrix_t* x, double* f, ccv_dense_matrix_t* df, void* data)
56
{
@@ -40,8 +41,32 @@ TEST_CASE("minimize rosenbrock")
4041
ccv_garbage_collect();
4142
}
4243

43-
TEST_CASE("fftw-based filter on Gaussian kernel")
44+
double gaussian(double x, double y, void* data)
4445
{
46+
return exp(-(x * x + y * y) / 20);
47+
}
48+
49+
TEST_CASE("FFTW-based filter on Gaussian kernel")
50+
{
51+
ccv_dense_matrix_t* image = 0;
52+
ccv_unserialize("../samples/nature.png", &image, CCV_SERIAL_ANY_FILE);
53+
ccv_dense_matrix_t* gray = ccv_dense_matrix_new(image->rows, image->cols, CCV_32F | CCV_C1, 0, 0);
54+
ccv_dense_matrix_t* kernel = ccv_dense_matrix_new(10, 10, CCV_32F | CCV_C1, 0, 0);
55+
/* grayscale conversion, at this point, ccv doesn't support grayscale conversion yet */
56+
int i, j;
57+
for (i = 0; i < image->rows; i++)
58+
for (j = 0; j < image->cols; j++)
59+
gray->data.fl[i * gray->cols + j] = (image->data.ptr[i * image->step + j * 3] * 29 + image->data.ptr[i * image->step + j * 3 + 1] * 61 + image->data.ptr[i * image->step + j * 3 + 2] * 10) / 100;
60+
ccv_filter_kernel(kernel, gaussian, 0);
61+
ccv_normalize(kernel, (ccv_matrix_t**)&kernel, 0, CCV_L1_NORM);
62+
ccv_dense_matrix_t* x = 0;
63+
ccv_filter(gray, kernel, (ccv_matrix_t**)&x, 0);
64+
REQUIRE_MATRIX_FILE_EQ(x, "data/nature.filter.bin", "should apply Gaussian filter with FFTW on nature.png with sigma = sqrt(10)");
65+
ccv_matrix_free(image);
66+
ccv_matrix_free(gray);
67+
ccv_matrix_free(kernel);
68+
ccv_matrix_free(x);
69+
ccv_garbage_collect();
4570
}
4671

4772
#include "case_main.h"

test/util.tests.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ TEST_CASE("compress sparse matrix")
123123
TEST_CASE("matrix slice")
124124
{
125125
ccv_dense_matrix_t* image = 0;
126-
ccv_unserialize("data/chessbox.png", &image, CCV_SERIAL_ANY_FILE);
126+
ccv_unserialize("../samples/chessbox.png", &image, CCV_SERIAL_ANY_FILE);
127127
ccv_dense_matrix_t* b = 0;
128128
ccv_slice(image, (ccv_matrix_t**)&b, 0, 33, 41, 111, 91);
129129
REQUIRE_MATRIX_FILE_EQ(b, "data/chessbox.slice.bin", "should have data/chessbox.png sliced at (33, 41) with 111 x 91");

0 commit comments

Comments
 (0)