Skip to content
Browse files

finished sift, more test needed

  • Loading branch information...
1 parent 2b0d9df commit d8fab74b8cd877327c96bfb9a1538d4d1d2e9970 @liuliu committed Sep 24, 2010
Showing with 198 additions and 7 deletions.
  1. +10 −0 COPYING
  2. +1 −1 bin/makefile
  3. +78 −0 bin/siftmatch.c
  4. +2 −0 lib/ccv.h
  5. +42 −0 lib/ccv_algebra.c
  6. +45 −4 lib/ccv_sift.c
  7. +1 −1 test/makefile
  8. +17 −0 test/normalize_test.c
  9. +2 −1 test/sift_test.c
View
10 COPYING
@@ -0,0 +1,10 @@
+Copyright (c) 2010, Liu Liu
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+* Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
View
2 bin/makefile
@@ -2,7 +2,7 @@ CC = gcc
LDFLAGS = -L"../lib" -L"/opt/ati-stream-sdk/lib/x86_64" -pthread -lccv -ljpeg -lpng -lfftw3 -lz -lgsl -lblas -lm -lgomp -lOpenCL
CXXFLAGS = -O3 -msse2 -Wall -I"../lib" -fopenmp -D USE_OPENMP -D USE_OPENCL
-TARGETS = sgfdetect sgfcreate sgffmt sgfopt
+TARGETS = sgfdetect sgfcreate sgffmt sgfopt siftmatch
all: libccv.a $(TARGETS)
View
78 bin/siftmatch.c
@@ -0,0 +1,78 @@
+#include "ccv.h"
+#include <sys/time.h>
+
+unsigned int get_current_time()
+{
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+int main(int argc, char** argv)
+{
+ assert(argc == 3);
+ ccv_dense_matrix_t* object = 0;
+ ccv_dense_matrix_t* image = 0;
+ ccv_unserialize(argv[1], &object, CCV_SERIAL_GRAY | CCV_SERIAL_ANY_FILE);
+ ccv_unserialize(argv[2], &image, CCV_SERIAL_GRAY | CCV_SERIAL_ANY_FILE);
+ unsigned int elapsed_time = get_current_time();
+ ccv_sift_param_t param;
+ param.noctaves = 3;
+ param.nlevels = 6;
+ param.edge_threshold = 10;
+ param.norm_threshold = 0;
+ param.peak_threshold = 0;
+ ccv_array_t* obj_keypoints = 0;
+ ccv_dense_matrix_t* obj_desc = 0;
+ ccv_sift(object, &obj_keypoints, &obj_desc, 0, param);
+ ccv_array_t* image_keypoints = 0;
+ ccv_dense_matrix_t* image_desc = 0;
+ ccv_sift(image, &image_keypoints, &image_desc, 0, param);
+ printf("elpased time : %d\n", get_current_time() - elapsed_time);
+ int i, j, k;
+ ccv_dense_matrix_t* imx = ccv_dense_matrix_new(image->rows, image->cols, CCV_8U | CCV_C1, 0, 0);
+ memset(imx->data.ptr, 0, imx->rows * imx->step);
+ for (i = 0; i < obj_keypoints->rnum; i++)
+ {
+ float* odesc = obj_desc->data.fl + i * 128;
+ int minj = -1;
+ double mind = 1e6, mind2 = 1e6;
+ for (j = 0; j < image_keypoints->rnum; j++)
+ {
+ float* idesc = image_desc->data.fl + j * 128;
+ double d = 0;
+ for (k = 0; k < 128; k++)
+ {
+ d += (odesc[k] - idesc[k]) * (odesc[k] - idesc[k]);
+ if (d > mind2)
+ break;
+ }
+ if (d < mind)
+ {
+ mind2 = mind;
+ mind = d;
+ minj = j;
+ } else if (d < mind2) {
+ mind2 = d;
+ }
+ }
+ if (mind < mind2 * 0.6)
+ {
+ ccv_keypoint_t* kp = (ccv_keypoint_t*)ccv_array_get(image_keypoints, minj);
+ int ix = (int)(kp->x + 0.5);
+ int iy = (int)(kp->y + 0.5);
+ imx->data.ptr[ix + iy * imx->step] = 255;
+ }
+ }
+ int len;
+ ccv_serialize(imx, "match.png", &len, CCV_SERIAL_PNG_FILE, 0);
+ ccv_array_free(obj_keypoints);
+ ccv_array_free(image_keypoints);
+ ccv_matrix_free(obj_desc);
+ ccv_matrix_free(image_desc);
+ ccv_matrix_free(object);
+ ccv_matrix_free(image);
+ ccv_garbage_collect();
+ return 0;
+}
+
View
2 lib/ccv.h
@@ -365,6 +365,7 @@ enum {
};
double ccv_norm(ccv_matrix_t* mat, int type);
+double ccv_normalize(ccv_matrix_t* a, ccv_matrix_t** b, int btype, int l_type);
double ccv_dot(ccv_matrix_t* a, ccv_matrix_t* b);
double ccv_sum(ccv_matrix_t* mat);
void ccv_zero(ccv_matrix_t* mat);
@@ -532,6 +533,7 @@ typedef struct {
int nlevels;
float edge_threshold;
float peak_threshold;
+ float norm_threshold;
} ccv_sift_param_t;
void ccv_sift(ccv_dense_matrix_t* a, ccv_array_t** keypoints, ccv_dense_matrix_t** desc, int type, ccv_sift_param_t params);
View
42 lib/ccv_algebra.c
@@ -13,6 +13,48 @@ double ccv_norm(ccv_matrix_t* mat, int type)
return 0;
}
+double ccv_normalize(ccv_matrix_t* a, ccv_matrix_t** b, int btype, int l_type)
+{
+ ccv_dense_matrix_t* da = ccv_get_dense_matrix(a);
+ assert(CCV_GET_CHANNEL(da->type) == CCV_C1);
+ char identifier[20];
+ memset(identifier, 0, 20);
+ snprintf(identifier, 20, "ccv_normalize(%d)", l_type);
+ uint64_t sig = (da->sig == 0) ? 0 : ccv_matrix_generate_signature(identifier, 20, da->sig, 0);
+ btype = (btype == 0) ? CCV_GET_DATA_TYPE(da->type) | CCV_C1 : CCV_GET_DATA_TYPE(btype) | CCV_C1;
+ ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, da->rows, da->cols, CCV_ALL_DATA_TYPE | CCV_C1, btype, sig);
+ ccv_cache_return(db, );
+ double sum = 0;
+ int i, j;
+ unsigned char* a_ptr = da->data.ptr;
+ unsigned char* b_ptr = db->data.ptr;
+ switch (l_type)
+ {
+ case CCV_L2_NORM:
+#define for_block(__for_set, __for_get) \
+ for (i = 0; i < da->rows; i++) \
+ { \
+ for (j = 0; j < da->cols; j++) \
+ sum += __for_get(a_ptr, j, 0) * __for_get(a_ptr, j, 0); \
+ a_ptr += da->step; \
+ } \
+ sum = sqrt(sum); \
+ double inv = 1.0 / sqrt(sum); \
+ a_ptr = da->data.ptr; \
+ for (i = 0; i < da->rows; i++) \
+ { \
+ for (j = 0; j < da->cols; j++) \
+ __for_set(b_ptr, j, __for_get(a_ptr, j, 0) * inv, 0); \
+ a_ptr += da->step; \
+ b_ptr += db->step; \
+ }
+ ccv_matrix_setter(db->type, ccv_matrix_getter, da->type, for_block);
+#undef for_block
+ break;
+ }
+ return sum;
+}
+
double ccv_sum(ccv_matrix_t* mat)
{
ccv_dense_matrix_t* dmt = ccv_get_dense_matrix(mat);
View
49 lib/ccv_sift.c
@@ -1,4 +1,13 @@
-/* The code is adopted from VLFeat, which is licenced under GPLv2 */
+/* The code is adopted from VLFeat with heavily rewrite.
+ * The original code is licenced under GPLv2, should be compatible
+ * with New BSD Licence used by ccv. The original Copyright:
+ *
+ * AUTORIGHTS
+ * Copyright (C) 2007-10 Andrea Vedaldi and Brian Fulkerson
+ *
+ * This file is part of VLFeat, available under the terms of the
+ * GNU GPLv2, or (at your option) any later version.
+ */
#include "ccv.h"
@@ -362,7 +371,8 @@ void ccv_sift(ccv_dense_matrix_t* a, ccv_array_t** _keypoints, ccv_dense_matrix_
float dy = kp->y / ds;
int ix = (int)(dx + 0.5);
int iy = (int)(dy + 0.5);
- int wz = ccv_max((int)(3.0 * kp->regular.scale + 0.5), 1);
+ double SBP = 3.0 * kp->regular.scale;
+ int wz = ccv_max((int)(SBP * sqrt(2.0) * 2.5 + 0.5), 1);
ccv_dense_matrix_t* tho = th[kp->octave * (params.nlevels - 3) + kp->level - 1];
ccv_dense_matrix_t* mdo = md[kp->octave * (params.nlevels - 3) + kp->level - 1];
assert(tho->rows == mdo->rows && tho->cols == mdo->cols);
@@ -371,16 +381,47 @@ void ccv_sift(ccv_dense_matrix_t* a, ccv_array_t** _keypoints, ccv_dense_matrix_
float* magnitude = mdo->data.fl + ccv_max(iy - wz, 0) * mdo->cols;
float ca = cos(kp->regular.angle);
float sa = sin(kp->regular.angle);
+ float sigmaw = 2.0;
+ /* sidenote: NBP = 4, NBO = 8 */
for (y = ccv_max(iy - wz, 0); y <= ccv_min(iy + wz, tho->rows - 1); y++)
{
for (x = ccv_max(ix - wz, 0); x <= ccv_min(ix + wz, tho->cols - 1); x++)
{
- float nx = (ca * (x - dx) + sa * (y - dy)) / wz;
- float ny = (-sa * (x - dx) + ca * (y - dy)) / wz;
+ float nx = (ca * (x - dx) + sa * (y - dy)) / SBP;
+ float ny = (-sa * (x - dx) + ca * (y - dy)) / SBP;
+ float nt = 8.0 * __ccv_mod_2pi(theta[x] * CCV_PI / 180.0 - kp->regular.angle) / (2.0 * CCV_PI);
+ float weight = __ccv_expn((nx * nx + ny * ny) / (2.0 * sigmaw * sigmaw));
+ int binx = __ccv_floor(nx - 0.5);
+ int biny = __ccv_floor(ny - 0.5);
+ int bint = __ccv_floor(nt);
+ float rbinx = nx - (binx + 0.5);
+ float rbiny = ny - (biny + 0.5);
+ float rbint = nt - bint;
+ int dbinx, dbiny, dbint;
+ /* Distribute the current sample into the 8 adjacent bins*/
+ for(dbinx = 0; dbinx < 2; dbinx++)
+ for(dbiny = 0; dbiny < 2; dbiny++)
+ for(dbint = 0; dbint < 2; dbint++)
+ if (binx + dbinx >= -2 && binx + dbinx < 2 && biny + dbiny >= -2 && biny + dbiny < 2)
+ fdesc[(2 + biny + dbiny) * 32 + (2 + binx + dbinx) * 8 + (bint + dbint) % 8] += weight * magnitude[x] * fabs(1 - dbinx - rbinx) * fabs(1 - dbiny - rbiny) * fabs(1 - dbint - rbint);
}
theta += tho->cols;
magnitude += mdo->cols;
}
+ ccv_dense_matrix_t tm = ccv_dense_matrix(1, 128, CCV_32F | CCV_C1, fdesc, 0);
+ ccv_dense_matrix_t* tmp = &tm;
+ double norm = ccv_normalize(&tm, &tmp, 0, CCV_L2_NORM);
+ int num = (ccv_min(iy + wz, tho->rows - 1) - ccv_max(iy - wz, 0) + 1) * (ccv_min(ix + wz, tho->cols - 1) - ccv_max(ix - wz, 0) + 1);
+ if (params.norm_threshold && norm < params.norm_threshold * num)
+ {
+ for (j = 0; j < 128; j++)
+ fdesc[j] = 0;
+ } else {
+ for (j = 0; j < 128; j++)
+ if (fdesc[j] > 0.2)
+ fdesc[j] = 0.2;
+ ccv_normalize(&tm, &tmp, 0, CCV_L2_NORM);
+ }
fdesc += 128;
}
}
View
2 test/makefile
@@ -2,7 +2,7 @@ CC = clang
LDFLAGS = -L"../lib" -pthread -static -lccv -ljpeg -lpng -lfftw3 -lz -lgsl -lblas -lm # -lgslcblas
CXXFLAGS = -O3 -msse2 -Wall -I"../lib"
-TARGETS = sobel_test hog_test cache_test sparse_matrix_test io_test filter_test algebra_test compress_matrix_test atan2_test resample_test sample_down_test daisy_test array_test group_test slice_test flip_test minimize_test gc_test blur_test sift_test
+TARGETS = sobel_test hog_test cache_test sparse_matrix_test io_test filter_test algebra_test compress_matrix_test atan2_test resample_test sample_down_test daisy_test array_test group_test slice_test flip_test minimize_test gc_test blur_test sift_test normalize_test sift_match
all: $(TARGETS)
View
17 test/normalize_test.c
@@ -0,0 +1,17 @@
+#include "ccv.h"
+#include <assert.h>
+
+int main(int argc, char** argv)
+{
+ int i;
+ ccv_dense_matrix_t* dmt = ccv_dense_matrix_new(1, 10, CCV_32F | CCV_C1, 0, 0);
+ for (i = 0; i < 10; i++)
+ dmt->data.fl[i] = i;
+ ccv_normalize(dmt, &dmt, 0, CCV_L2_NORM);
+ for (i = 0; i < 10; i++)
+ printf("%f ", dmt->data.fl[i]);
+ printf("\n");
+ ccv_matrix_free(dmt);
+ ccv_garbage_collect();
+ return 0;
+}
View
3 test/sift_test.c
@@ -26,13 +26,14 @@ int main(int argc, char** argv)
param.noctaves = 3;
param.nlevels = 6;
param.edge_threshold = 10;
+ param.norm_threshold = 0;
param.peak_threshold = 0;
ccv_array_t* keypoints = 0;
ccv_sift(image, &keypoints, 0, 0, param);
printf("%d\n", keypoints->rnum);
ccv_dense_matrix_t* imx = ccv_dense_matrix_new(image->rows, image->cols, CCV_8U | CCV_C1, 0, 0);
memset(imx->data.ptr, 0, imx->rows * imx->step);
- int i;
+ int i, j;
for (i = 0; i < keypoints->rnum; i++)
{
ccv_keypoint_t* kp = (ccv_keypoint_t*)ccv_array_get(keypoints, i);

0 comments on commit d8fab74

Please sign in to comment.
Something went wrong with that request. Please try again.