Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

with ccv_color_transform and ccv_read prototype

added two new functions, ccv_color_transform and ccv_read with 6
parameters.

with the new ccv_read interface, I should be able to implement a interp
functions that will read buffer of image data sequence and emit
ccv_dense_matrix_t.
  • Loading branch information...
commit b8d6fb22a050e58f7332f8c0c4e838bdc1d680be 1 parent d42b4f8
@liuliu authored
View
48 bin/msermatch.c
@@ -15,7 +15,7 @@ int main(int argc, char** argv)
assert(argc == 3);
ccv_enable_default_cache();
ccv_dense_matrix_t* image = 0;
- ccv_read(argv[1], &image, CCV_IO_COLOR | CCV_IO_ANY_FILE);
+ ccv_read(argv[1], &image, CCV_IO_RGB_COLOR | CCV_IO_ANY_FILE);
ccv_mser_param_t params = {
.min_area = 60,
.max_area = (int)(image->rows * image->cols * 0.3 + 0.5),
@@ -23,30 +23,34 @@ int main(int argc, char** argv)
.area_threshold = 1.01,
.min_margin = 0.003,
.max_evolution = 200,
- .edge_blur_sigma = sqrt(5.0),
+ .edge_blur_sigma = sqrt(3.0),
};
- ccv_dense_matrix_t* mser = 0;
- ccv_array_t* mser_keypoint = ccv_mser(image, 0, &mser, 0, params);
- ccv_dense_matrix_t* graph = ccv_dense_matrix_new(image->rows, image->cols, CCV_8U | CCV_C3, 0, 0);
- ccv_matrix_free(image);
- ccv_array_free(mser_keypoint);
- int i, j;
- for (i = 0; i < graph->rows; i++)
- for (j = 0; j < graph->cols; j++)
- {
- if (mser->data.i32[i * mser->cols + j] == 0)
+ if (image)
+ {
+ ccv_dense_matrix_t* yuv = 0;
+ ccv_color_transform(image, &yuv, 0, CCV_RGB_TO_YUV);
+ unsigned int elapsed_time = get_current_time();
+ ccv_dense_matrix_t* mser = 0;
+ ccv_array_t* mser_keypoint = ccv_mser(yuv, 0, &mser, 0, params);
+ elapsed_time = get_current_time() - elapsed_time;
+ printf("total : %d in time %dms\n", mser_keypoint->rnum, elapsed_time);
+ ccv_array_free(mser_keypoint);
+ ccv_make_matrix_mutable(image);
+ int i, j;
+ for (i = 0; i < image->rows; i++)
+ for (j = 0; j < image->cols; j++)
{
- graph->data.u8[i * graph->step + j * 3] =
- graph->data.u8[i * graph->step + j * 3 + 1] =
- graph->data.u8[i * graph->step + j * 3 + 2] = 255;
- } else {
- graph->data.u8[i * graph->step + j * 3] = colors[mser->data.i32[i * mser->cols + j] % 6][0];
- graph->data.u8[i * graph->step + j * 3 + 1] = colors[mser->data.i32[i * mser->cols + j] % 6][1];
- graph->data.u8[i * graph->step + j * 3 + 2] = colors[mser->data.i32[i * mser->cols + j] % 6][2];
+ if (mser->data.i32[i * mser->cols + j])
+ {
+ image->data.u8[i * image->step + j * 3] = colors[mser->data.i32[i * mser->cols + j] % 6][0];
+ image->data.u8[i * image->step + j * 3 + 1] = colors[mser->data.i32[i * mser->cols + j] % 6][1];
+ image->data.u8[i * image->step + j * 3 + 2] = colors[mser->data.i32[i * mser->cols + j] % 6][2];
+ }
}
- }
- ccv_write(graph, argv[2], 0, CCV_IO_PNG_FILE, 0);
- ccv_matrix_free(graph);
+ ccv_write(image, argv[2], 0, CCV_IO_PNG_FILE, 0);
+ ccv_matrix_free(image);
+ ccv_matrix_free(yuv);
+ }
ccv_disable_cache();
return 0;
}
View
49 lib/ccv.h
@@ -252,17 +252,31 @@ void ccv_enable_cache(size_t size);
enum {
CCV_IO_GRAY = 0x100,
- CCV_IO_COLOR = 0x300,
+ CCV_IO_RGB_COLOR = 0x300,
+};
+
+enum {
+ // read self-describe in-memory data
CCV_IO_ANY_STREAM = 0x010,
CCV_IO_PLAIN_STREAM = 0x011,
CCV_IO_DEFLATE_STREAM = 0x012,
CCV_IO_JPEG_STREAM = 0x013,
CCV_IO_PNG_STREAM = 0x014,
+ // read self-describe on-disk data
CCV_IO_ANY_FILE = 0x020,
CCV_IO_BMP_FILE = 0x021,
CCV_IO_JPEG_FILE = 0x022,
CCV_IO_PNG_FILE = 0x023,
CCV_IO_BINARY_FILE = 0x024,
+ // read not-self-describe in-memory data (a.k.a. raw data)
+ // you need to specify rows, cols, or scanline for these data
+ CCV_IO_RGB_RAW = 0x031,
+ CCV_IO_RGBA_RAW = 0x032,
+ CCV_IO_ARGB_RAW = 0x033,
+ CCV_IO_BGR_RAW = 0x034,
+ CCV_IO_BGRA_RAW = 0x035,
+ CCV_IO_ABGR_RAW = 0x036,
+ CCV_IO_GRAY_RAW = 0x037,
};
enum {
@@ -272,7 +286,14 @@ enum {
CCV_IO_ATTEMPTED,
};
-int ccv_read(const char* in, ccv_dense_matrix_t** x, int type);
+int ccv_read_impl(const char* in, ccv_dense_matrix_t** x, int type, int rows, int cols, int scanline);
+#define ccv_read_n(in, x, type, rows, cols, scanline, ...) \
+ ccv_read_impl(in, x, type, rows, cols, scanline)
+#define ccv_read(in, x, type, ...) \
+ ccv_read_n(in, x, type, ##__VA_ARGS__, 0, 0, 0)
+// this is a way to implement function-signature based dispatch, you can call either
+// ccv_read(in, x, type) or ccv_read(in, x, type, rows, cols, scanline)
+// notice that you can implement this with va_* functions, but that is not type-safe
int ccv_write(ccv_dense_matrix_t* mat, char* out, int* len, int type, void* conf);
/* basic algebra algorithms ccv_algebra.c */
@@ -455,6 +476,22 @@ void ccv_sobel(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int dx,
void ccv_gradient(ccv_dense_matrix_t* a, ccv_dense_matrix_t** theta, int ttype, ccv_dense_matrix_t** m, int mtype, int dx, int dy);
enum {
+ CCV_FLIP_X = 0x01,
+ CCV_FLIP_Y = 0x02,
+};
+
+void ccv_flip(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int btype, int type);
+void ccv_blur(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, double sigma);
+
+enum {
+ CCV_RGB_TO_YUV = 0x01,
+};
+
+void ccv_color_transform(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int flag);
+
+/* resample algorithms ccv_resample.c */
+
+enum {
CCV_INTER_AREA = 0x01,
CCV_INTER_LINEAR = 0X02,
CCV_INTER_CUBIC = 0X03,
@@ -465,14 +502,6 @@ void ccv_resample(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int btype, int
void ccv_sample_down(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int src_x, int src_y);
void ccv_sample_up(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int src_x, int src_y);
-enum {
- CCV_FLIP_X = 0x01,
- CCV_FLIP_Y = 0x02,
-};
-
-void ccv_flip(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int btype, int type);
-void ccv_blur(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, double sigma);
-
/* classic computer vision algorithms ccv_classic.c */
void ccv_hog(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int b_type, int sbin, int size);
View
465 lib/ccv_basic.c
@@ -281,429 +281,6 @@ void ccv_gradient(ccv_dense_matrix_t* a, ccv_dense_matrix_t** theta, int ttype,
ccv_matrix_free(ty);
}
-/* area interpolation resample is adopted from OpenCV */
-
-typedef struct {
- int si, di;
- unsigned int alpha;
-} ccv_int_alpha;
-
-static void _ccv_resample_area_8u(ccv_dense_matrix_t* a, ccv_dense_matrix_t* b)
-{
- ccv_int_alpha* xofs = (ccv_int_alpha*)alloca(sizeof(ccv_int_alpha) * a->cols * 2);
- int ch = ccv_clamp(CCV_GET_CHANNEL(a->type), 1, 4);
- double scale_x = (double)a->cols / b->cols;
- double scale_y = (double)a->rows / b->rows;
- // double scale = 1.f / (scale_x * scale_y);
- unsigned int inv_scale_256 = (int)(scale_x * scale_y * 0x10000);
- int dx, dy, sx, sy, i, k;
- for (dx = 0, k = 0; dx < b->cols; dx++)
- {
- double fsx1 = dx * scale_x, fsx2 = fsx1 + scale_x;
- int sx1 = (int)(fsx1 + 1.0 - 1e-6), sx2 = (int)(fsx2);
- sx1 = ccv_min(sx1, a->cols - 1);
- sx2 = ccv_min(sx2, a->cols - 1);
-
- if (sx1 > fsx1)
- {
- xofs[k].di = dx * ch;
- xofs[k].si = (sx1 - 1) * ch;
- xofs[k++].alpha = (unsigned int)((sx1 - fsx1) * 0x100);
- }
-
- for (sx = sx1; sx < sx2; sx++)
- {
- xofs[k].di = dx * ch;
- xofs[k].si = sx * ch;
- xofs[k++].alpha = 256;
- }
-
- if (fsx2 - sx2 > 1e-3)
- {
- xofs[k].di = dx * ch;
- xofs[k].si = sx2 * ch;
- xofs[k++].alpha = (unsigned int)((fsx2 - sx2) * 256);
- }
- }
- int xofs_count = k;
- unsigned int* buf = (unsigned int*)alloca(b->cols * ch * sizeof(unsigned int));
- unsigned int* sum = (unsigned int*)alloca(b->cols * ch * sizeof(unsigned int));
- for (dx = 0; dx < b->cols * ch; dx++)
- buf[dx] = sum[dx] = 0;
- dy = 0;
- for (sy = 0; sy < a->rows; sy++)
- {
- unsigned char* a_ptr = a->data.u8 + a->step * sy;
- for (k = 0; k < xofs_count; k++)
- {
- int dxn = xofs[k].di;
- unsigned int alpha = xofs[k].alpha;
- for (i = 0; i < ch; i++)
- buf[dxn + i] += a_ptr[xofs[k].si + i] * alpha;
- }
- if ((dy + 1) * scale_y <= sy + 1 || sy == a->rows - 1)
- {
- unsigned int beta = (int)(ccv_max(sy + 1 - (dy + 1) * scale_y, 0.f) * 256);
- unsigned int beta1 = 256 - beta;
- unsigned char* b_ptr = b->data.u8 + b->step * dy;
- if (beta <= 0)
- {
- for (dx = 0; dx < b->cols * ch; dx++)
- {
- b_ptr[dx] = ccv_clamp((sum[dx] + buf[dx] * 256) / inv_scale_256, 0, 255);
- sum[dx] = buf[dx] = 0;
- }
- } else {
- for (dx = 0; dx < b->cols * ch; dx++)
- {
- b_ptr[dx] = ccv_clamp((sum[dx] + buf[dx] * beta1) / inv_scale_256, 0, 255);
- sum[dx] = buf[dx] * beta;
- buf[dx] = 0;
- }
- }
- dy++;
- }
- else
- {
- for(dx = 0; dx < b->cols * ch; dx++)
- {
- sum[dx] += buf[dx] * 256;
- buf[dx] = 0;
- }
- }
- }
-}
-
-typedef struct {
- int si, di;
- float alpha;
-} ccv_decimal_alpha;
-
-static void _ccv_resample_area(ccv_dense_matrix_t* a, ccv_dense_matrix_t* b)
-{
- ccv_decimal_alpha* xofs = (ccv_decimal_alpha*)alloca(sizeof(ccv_decimal_alpha) * a->cols * 2);
- int ch = CCV_GET_CHANNEL(a->type);
- double scale_x = (double)a->cols / b->cols;
- double scale_y = (double)a->rows / b->rows;
- double scale = 1.f / (scale_x * scale_y);
- int dx, dy, sx, sy, i, k;
- for (dx = 0, k = 0; dx < b->cols; dx++)
- {
- double fsx1 = dx * scale_x, fsx2 = fsx1 + scale_x;
- int sx1 = (int)(fsx1 + 1.0 - 1e-6), sx2 = (int)(fsx2);
- sx1 = ccv_min(sx1, a->cols - 1);
- sx2 = ccv_min(sx2, a->cols - 1);
-
- if (sx1 > fsx1)
- {
- xofs[k].di = dx * ch;
- xofs[k].si = (sx1 - 1) * ch;
- xofs[k++].alpha = (float)((sx1 - fsx1) * scale);
- }
-
- for (sx = sx1; sx < sx2; sx++)
- {
- xofs[k].di = dx * ch;
- xofs[k].si = sx * ch;
- xofs[k++].alpha = (float)scale;
- }
-
- if (fsx2 - sx2 > 1e-3)
- {
- xofs[k].di = dx * ch;
- xofs[k].si = sx2 * ch;
- xofs[k++].alpha = (float)((fsx2 - sx2) * scale);
- }
- }
- int xofs_count = k;
- float* buf = (float*)alloca(b->cols * ch * sizeof(float));
- float* sum = (float*)alloca(b->cols * ch * sizeof(float));
- for (dx = 0; dx < b->cols * ch; dx++)
- buf[dx] = sum[dx] = 0;
- dy = 0;
-#define for_block(_for_get, _for_set) \
- for (sy = 0; sy < a->rows; sy++) \
- { \
- unsigned char* a_ptr = a->data.u8 + a->step * sy; \
- for (k = 0; k < xofs_count; k++) \
- { \
- int dxn = xofs[k].di; \
- float alpha = xofs[k].alpha; \
- for (i = 0; i < ch; i++) \
- buf[dxn + i] += _for_get(a_ptr, xofs[k].si + i, 0) * alpha; \
- } \
- if ((dy + 1) * scale_y <= sy + 1 || sy == a->rows - 1) \
- { \
- float beta = ccv_max(sy + 1 - (dy + 1) * scale_y, 0.f); \
- float beta1 = 1 - beta; \
- unsigned char* b_ptr = b->data.u8 + b->step * dy; \
- if (fabs(beta) < 1e-3) \
- { \
- for (dx = 0; dx < b->cols * ch; dx++) \
- { \
- _for_set(b_ptr, dx, sum[dx] + buf[dx], 0); \
- sum[dx] = buf[dx] = 0; \
- } \
- } else { \
- for (dx = 0; dx < b->cols * ch; dx++) \
- { \
- _for_set(b_ptr, dx, sum[dx] + buf[dx] * beta1, 0); \
- sum[dx] = buf[dx] * beta; \
- buf[dx] = 0; \
- } \
- } \
- dy++; \
- } \
- else \
- { \
- for(dx = 0; dx < b->cols * ch; dx++) \
- { \
- sum[dx] += buf[dx]; \
- buf[dx] = 0; \
- } \
- } \
- }
- ccv_matrix_getter(a->type, ccv_matrix_setter, b->type, for_block);
-#undef for_block
-}
-
-void ccv_resample(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int btype, int rows, int cols, int type)
-{
- ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(64, "ccv_resample(%d,%d,%d)", rows, cols, type), a->sig, 0);
- btype = (btype == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) : CCV_GET_DATA_TYPE(btype) | CCV_GET_CHANNEL(a->type);
- ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, rows, cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), btype, sig);
- ccv_object_return_if_cached(, db);
- if (a->rows == db->rows && a->cols == db->cols)
- {
- if (CCV_GET_CHANNEL(a->type) == CCV_GET_CHANNEL(db->type) && CCV_GET_DATA_TYPE(db->type) == CCV_GET_DATA_TYPE(a->type))
- memcpy(db->data.u8, a->data.u8, a->rows * a->step);
- else {
- ccv_shift(a, (ccv_matrix_t**)&db, 0, 0, 0);
- }
- return;
- }
- switch (type)
- {
- case CCV_INTER_AREA:
- if (a->rows > db->rows && a->cols > db->cols)
- {
- /* using the fast alternative (fix point scale, 0x100 to avoid overflow) */
- if (CCV_GET_DATA_TYPE(a->type) == CCV_8U && CCV_GET_DATA_TYPE(db->type) == CCV_8U && a->rows * a->cols / (db->rows * db->cols) < 0x100)
- _ccv_resample_area_8u(a, db);
- else
- _ccv_resample_area(a, db);
- break;
- }
- case CCV_INTER_LINEAR:
- break;
- case CCV_INTER_CUBIC:
- break;
- case CCV_INTER_LANCZOS:
- break;
- }
-}
-
-/* the following code is adopted from OpenCV cvPyrDown */
-void ccv_sample_down(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int src_x, int src_y)
-{
- assert(src_x >= 0 && src_y >= 0);
- ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(64, "ccv_sample_down(%d,%d)", src_x, src_y), a->sig, 0);
- type = (type == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) : CCV_GET_DATA_TYPE(type) | CCV_GET_CHANNEL(a->type);
- ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, a->rows / 2, a->cols / 2, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), type, sig);
- ccv_object_return_if_cached(, db);
- int ch = CCV_GET_CHANNEL(a->type);
- int cols0 = db->cols - 1 - src_x;
- int dy, sy = -2 + src_y, sx = src_x * ch, dx, k;
- int* tab = (int*)alloca((a->cols + src_x + 2) * ch * sizeof(int));
- for (dx = 0; dx < a->cols + src_x + 2; dx++)
- for (k = 0; k < ch; k++)
- tab[dx * ch + k] = ((dx >= a->cols) ? a->cols * 2 - 1 - dx : dx) * ch + k;
- unsigned char* buf = (unsigned char*)alloca(5 * db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int)));
- int bufstep = db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int));
- unsigned char* b_ptr = db->data.u8;
- /* why is src_y * 4 in computing the offset of row?
- * Essentially, it means sy - src_y but in a manner that doesn't result negative number.
- * notice that we added src_y before when computing sy in the first place, however,
- * it is not desirable to have that offset when we try to wrap it into our 5-row buffer (
- * because in later rearrangement, we have no src_y to backup the arrangement). In
- * such micro scope, we managed to stripe 5 addition into one shift and addition. */
-#define for_block(_for_get_a, _for_set, _for_get, _for_set_b) \
- for (dy = 0; dy < db->rows; dy++) \
- { \
- for(; sy <= dy * 2 + 2 + src_y; sy++) \
- { \
- unsigned char* row = buf + ((sy + src_y * 4 + 2) % 5) * bufstep; \
- int _sy = (sy < 0) ? -1 - sy : (sy >= a->rows) ? a->rows * 2 - 1 - sy : sy; \
- unsigned char* a_ptr = a->data.u8 + a->step * _sy; \
- for (k = 0; k < ch; k++) \
- _for_set(row, k, _for_get_a(a_ptr, sx + k, 0) * 10 + _for_get_a(a_ptr, ch + sx + k, 0) * 5 + _for_get_a(a_ptr, 2 * ch + sx + k, 0), 0); \
- for(dx = ch; dx < cols0 * ch; dx += ch) \
- for (k = 0; k < ch; k++) \
- _for_set(row, dx + k, _for_get_a(a_ptr, dx * 2 + sx + k, 0) * 6 + (_for_get_a(a_ptr, dx * 2 + sx + k - ch, 0) + _for_get_a(a_ptr, dx * 2 + sx + k + ch, 0)) * 4 + _for_get_a(a_ptr, dx * 2 + sx + k - ch * 2, 0) + _for_get_a(a_ptr, dx * 2 + sx + k + ch * 2, 0), 0); \
- x_block(_for_get_a, _for_set, _for_get, _for_set_b); \
- } \
- unsigned char* rows[5]; \
- for(k = 0; k < 5; k++) \
- rows[k] = buf + ((dy * 2 + k) % 5) * bufstep; \
- for(dx = 0; dx < db->cols * ch; dx++) \
- _for_set_b(b_ptr, dx, (_for_get(rows[2], dx, 0) * 6 + (_for_get(rows[1], dx, 0) + _for_get(rows[3], dx, 0)) * 4 + _for_get(rows[0], dx, 0) + _for_get(rows[4], dx, 0)) / 256, 0); \
- b_ptr += db->step; \
- }
- int no_8u_type = (a->type & CCV_8U) ? CCV_32S : a->type;
- if (src_x > 0)
- {
-#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
- for (dx = cols0 * ch; dx < db->cols * ch; dx += ch) \
- for (k = 0; k < ch; k++) \
- _for_set(row, dx + k, _for_get_a(a_ptr, tab[dx * 2 + sx + k], 0) * 6 + (_for_get_a(a_ptr, tab[dx * 2 + sx + k - ch], 0) + _for_get_a(a_ptr, tab[dx * 2 + sx + k + ch], 0)) * 4 + _for_get_a(a_ptr, tab[dx * 2 + sx + k - ch * 2], 0) + _for_get_a(a_ptr, tab[dx * 2 + sx + k + ch * 2], 0), 0);
- ccv_matrix_getter_a(a->type, ccv_matrix_setter_getter, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
-#undef x_block
- } else {
-#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
- for (k = 0; k < ch; k++) \
- _for_set(row, (db->cols - 1) * ch + k, _for_get_a(a_ptr, a->cols * ch + sx - ch + k, 0) * 10 + _for_get_a(a_ptr, (a->cols - 2) * ch + sx + k, 0) * 5 + _for_get_a(a_ptr, (a->cols - 3) * ch + sx + k, 0), 0);
- ccv_matrix_getter_a(a->type, ccv_matrix_setter_getter, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
-#undef x_block
- }
-#undef for_block
-}
-
-void ccv_sample_up(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int src_x, int src_y)
-{
- assert(src_x >= 0 && src_y >= 0);
- ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(64, "ccv_sample_up(%d,%d)", src_x, src_y), a->sig, 0);
- type = (type == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) : CCV_GET_DATA_TYPE(type) | CCV_GET_CHANNEL(a->type);
- ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, a->rows * 2, a->cols * 2, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), type, sig);
- ccv_object_return_if_cached(, db);
- int ch = CCV_GET_CHANNEL(a->type);
- int cols0 = a->cols - 1 - src_x;
- int y, x, sy = -1 + src_y, sx = src_x * ch, k;
- int* tab = (int*)alloca((a->cols + src_x + 2) * ch * sizeof(int));
- for (x = 0; x < a->cols + src_x + 2; x++)
- for (k = 0; k < ch; k++)
- tab[x * ch + k] = ((x >= a->cols) ? a->cols * 2 - 1 - x : x) * ch + k;
- unsigned char* buf = (unsigned char*)alloca(3 * db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int)));
- int bufstep = db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int));
- unsigned char* b_ptr = db->data.u8;
- /* why src_y * 2: the same argument as in ccv_sample_down */
-#define for_block(_for_get_a, _for_set, _for_get, _for_set_b) \
- for (y = 0; y < a->rows; y++) \
- { \
- for (; sy <= y + 1 + src_y; sy++) \
- { \
- unsigned char* row = buf + ((sy + src_y * 2 + 1) % 3) * bufstep; \
- int _sy = (sy < 0) ? -1 - sy : (sy >= a->rows) ? a->rows * 2 - 1 - sy : sy; \
- unsigned char* a_ptr = a->data.u8 + a->step * _sy; \
- if (a->cols == 1) \
- { \
- for (k = 0; k < ch; k++) \
- { \
- _for_set(row, k, _for_get_a(a_ptr, k, 0) * (G025 + G075 + G125), 0); \
- _for_set(row, k + ch, _for_get_a(a_ptr, k, 0) * (G025 + G075 + G125), 0); \
- } \
- continue; \
- } \
- if (sx == 0) \
- { \
- for (k = 0; k < ch; k++) \
- { \
- _for_set(row, k, _for_get_a(a_ptr, k + sx, 0) * (G025 + G075) + _for_get_a(a_ptr, k + sx + ch, 0) * G125, 0); \
- _for_set(row, k + ch, _for_get_a(a_ptr, k + sx, 0) * (G125 + G025) + _for_get_a(a_ptr, k + sx + ch, 0) * G075, 0); \
- } \
- } \
- /* some serious flaw in computing Gaussian weighting in previous version
- * specially, we are doing perfect upsampling (2x) so, it concerns a grid like:
- * XXYY
- * XXYY
- * in this case, to upsampling, the weight should be from distance 0.25 and 1.25, and 0.25 and 0.75
- * previously, it was mistakingly be 0.0 1.0, 0.5 0.5 (imperfect upsampling (2x - 1)) */ \
- for (x = (sx == 0) ? ch : 0; x < cols0 * ch; x += ch) \
- { \
- for (k = 0; k < ch; k++) \
- { \
- _for_set(row, x * 2 + k, _for_get_a(a_ptr, x + sx - ch + k, 0) * G075 + _for_get_a(a_ptr, x + sx + k, 0) * G025 + _for_get_a(a_ptr, x + sx + ch + k, 0) * G125, 0); \
- _for_set(row, x * 2 + ch + k, _for_get_a(a_ptr, x + sx - ch + k, 0) * G125 + _for_get_a(a_ptr, x + sx + k, 0) * G025 + _for_get_a(a_ptr, x + sx + ch + k, 0) * G075, 0); \
- } \
- } \
- x_block(_for_get_a, _for_set, _for_get, _for_set_b); \
- } \
- unsigned char* rows[3]; \
- for (k = 0; k < 3; k++) \
- rows[k] = buf + ((y + k) % 3) * bufstep; \
- for (x = 0; x < db->cols * ch; x++) \
- { \
- _for_set_b(b_ptr, x, (_for_get(rows[0], x, 0) * G075 + _for_get(rows[1], x, 0) * G025 + _for_get(rows[2], x, 0) * G125) / GALL, 0); \
- _for_set_b(b_ptr + db->step, x, (_for_get(rows[0], x, 0) * G125 + _for_get(rows[1], x, 0) * G025 + _for_get(rows[2], x, 0) * G075) / GALL, 0); \
- } \
- b_ptr += 2 * db->step; \
- }
- int no_8u_type = (a->type & CCV_8U) ? CCV_32S : a->type;
- /* unswitch if condition in manual way */
- if ((a->type & CCV_8U) || (a->type & CCV_32S) || (a->type & CCV_64S))
- {
-#define G025 (23)
-#define G075 (8)
-#define G125 (1)
-#define GALL (1024)
- if (src_x > 0)
- {
-#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
- for (x = cols0 * ch; x < a->cols * ch; x += ch) \
- for (k = 0; k < ch; k++) \
- { \
- _for_set(row, x * 2 + k, _for_get_a(a_ptr, tab[x + sx - ch + k], 0) * G075 + _for_get_a(a_ptr, tab[x + sx + k], 0) * G025 + _for_get_a(a_ptr, tab[x + sx + ch + k], 0) * G125, 0); \
- _for_set(row, x * 2 + ch + k, _for_get_a(a_ptr, tab[x + sx - ch + k], 0) * G125 + _for_get_a(a_ptr, tab[x + sx + k], 0) * G025 + _for_get_a(a_ptr, tab[x + sx + ch + k], 0) * G075, 0); \
- }
- ccv_matrix_getter_integer_only(a->type, ccv_matrix_setter_getter_integer_only, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
-#undef x_block
- } else {
-#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
- for (k = 0; k < ch; k++) \
- { \
- _for_set(row, (a->cols - 1) * 2 * ch + k, _for_get_a(a_ptr, (a->cols - 2) * ch + k, 0) * G075 + _for_get_a(a_ptr, (a->cols - 1) * ch + k, 0) * (G025 + G125), 0); \
- _for_set(row, (a->cols - 1) * 2 * ch + ch + k, _for_get_a(a_ptr, (a->cols - 2) * ch + k, 0) * G125 + _for_get_a(a_ptr, (a->cols - 1) * ch + k, 0) * (G025 + G075), 0); \
- }
- ccv_matrix_getter_integer_only(a->type, ccv_matrix_setter_getter_integer_only, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
-#undef x_block
- }
-#undef GALL
-#undef G125
-#undef G075
-#undef G025
- } else {
-#define G025 (0.705385)
-#define G075 (0.259496)
-#define G125 (0.035119)
-#define GALL (1)
- if (src_x > 0)
- {
-#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
- for (x = cols0 * ch; x < a->cols * ch; x += ch) \
- for (k = 0; k < ch; k++) \
- { \
- _for_set(row, x * 2 + k, _for_get_a(a_ptr, tab[x + sx - ch + k], 0) * G075 + _for_get_a(a_ptr, tab[x + sx + k], 0) * G025 + _for_get_a(a_ptr, tab[x + sx + ch + k], 0) * G125, 0); \
- _for_set(row, x * 2 + ch + k, _for_get_a(a_ptr, tab[x + sx - ch + k], 0) * G125 + _for_get_a(a_ptr, tab[x + sx + k], 0) * G025 + _for_get_a(a_ptr, tab[x + sx + ch + k], 0) * G075, 0); \
- }
- ccv_matrix_getter_float_only(a->type, ccv_matrix_setter_getter_float_only, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
-#undef x_block
- } else {
-#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
- for (k = 0; k < ch; k++) \
- { \
- _for_set(row, (a->cols - 1) * 2 * ch + k, _for_get_a(a_ptr, (a->cols - 2) * ch + k, 0) * G075 + _for_get_a(a_ptr, (a->cols - 1) * ch + k, 0) * (G025 + G125), 0); \
- _for_set(row, (a->cols - 1) * 2 * ch + ch + k, _for_get_a(a_ptr, (a->cols - 2) * ch + k, 0) * G125 + _for_get_a(a_ptr, (a->cols - 1) * ch + k, 0) * (G025 + G075), 0); \
- }
- ccv_matrix_getter_float_only(a->type, ccv_matrix_setter_getter_float_only, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
-#undef x_block
- }
-#undef GALL
-#undef G125
-#undef G075
-#undef G025
- }
-#undef for_block
-}
-
void _ccv_flip_y_self(ccv_dense_matrix_t* a)
{
int i;
@@ -845,3 +422,45 @@ void ccv_blur(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, double si
ccv_matrix_typeof_setter_getter(no_8u_type, ccv_matrix_setter_getter, db->type, for_block);
#undef for_block
}
+
+static void _ccv_rgb_to_yuv(ccv_dense_matrix_t* a, ccv_dense_matrix_t* b)
+{
+ unsigned char* a_ptr = a->data.u8;
+ unsigned char* b_ptr = b->data.u8;
+ int i, j;
+#define for_block(_for_get, _for_set_b, _for_get_b) \
+ for (i = 0; i < a->rows; i++) \
+ { \
+ for (j = 0; j < a->cols; j++) \
+ { \
+ _for_set_b(b_ptr, j * 3, (_for_get(a_ptr, j * 3, 0) * 1225 + _for_get(a_ptr, j * 3 + 1, 0) * 2404 + _for_get(a_ptr, j * 3 + 2, 0) * 467) / 4096, 0); \
+ _for_set_b(b_ptr, j * 3 + 1, (_for_get(a_ptr, j * 3 + 2, 0) - _for_get_b(b_ptr, j * 3, 0)) * 2015 / 4096 + 128, 0); \
+ _for_set_b(b_ptr, j * 3 + 2, (_for_get(a_ptr, j * 3, 0) - _for_get_b(b_ptr, j * 3, 0)) * 3592 / 4096 + 128, 0); \
+ } \
+ a_ptr += a->step; \
+ b_ptr += b->step; \
+ }
+ ccv_matrix_getter(a->type, ccv_matrix_setter_getter, b->type, for_block);
+#undef for_block
+}
+
+void ccv_color_transform(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int flag)
+{
+ ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(64, "ccv_color_transform(%d)", flag), a->sig, 0);
+ assert(flag == CCV_RGB_TO_YUV);
+ switch (flag)
+ {
+ case CCV_RGB_TO_YUV:
+ assert(CCV_GET_CHANNEL(a->type) == CCV_C3);
+ type = (type == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_C3 : CCV_GET_DATA_TYPE(type) | CCV_C3;
+ break;
+ }
+ ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, a->rows, a->cols, CCV_ALL_DATA_TYPE | CCV_C3, type, sig);
+ ccv_object_return_if_cached(, db);
+ switch (flag)
+ {
+ case CCV_RGB_TO_YUV:
+ _ccv_rgb_to_yuv(a, db);
+ break;
+ }
+}
View
42 lib/ccv_io.c
@@ -1,37 +1,31 @@
#include "ccv.h"
#include "ccv_internal.h"
-#ifdef HAVE_LIBJPEG
-#include <jpeglib.h>
-#endif
-
#ifdef HAVE_LIBPNG
- #ifdef __APPLE__
- #include "TargetConditionals.h"
- #if TARGET_OS_IPHONE
- // iOS
- #elif TARGET_IPHONE_SIMULATOR
- // iOS Simulator
- #elif TARGET_OS_MAC
- #include <zlib.h>
- #include <png.h>
- #else
- // Unsupported platform
- #endif
- #else
- #include <libpng/png.h>
- #endif
+#ifdef __APPLE__
+#include "TargetConditionals.h"
+#if TARGET_OS_IPHONE
+// iOS
+#elif TARGET_IPHONE_SIMULATOR
+// iOS Simulator
+#elif TARGET_OS_MAC
+#include <zlib.h>
+#include <png.h>
+#else
+// Unsupported platform
#endif
-
-#ifdef HAVE_LIBJPEG
-#include "io/_ccv_io_libjpeg.c"
+#else
+#include <libpng/png.h>
#endif
-#ifdef HAVE_LIBPNG
#include "io/_ccv_io_libpng.c"
#endif
+#ifdef HAVE_LIBJPEG
+#include <jpeglib.h>
+#include "io/_ccv_io_libjpeg.c"
+#endif
#include "io/_ccv_io_bmp.c"
#include "io/_ccv_io_binary.c"
-int ccv_read(const char* in, ccv_dense_matrix_t** x, int type)
+int ccv_read_impl(const char* in, ccv_dense_matrix_t** x, int type, int rows, int cols, int scanline)
{
FILE* fd = 0;
int ctype = (type & 0xF00) ? CCV_8U | ((type & 0xF00) >> 8) : 0;
View
234 lib/ccv_mser.c
@@ -106,15 +106,15 @@ static double chitab3[] = { 0, 0.0150057, 0.0239478, 0.0315227,
static void _ccv_mscr_chi(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int dx, int dy)
{
- assert((dx == 1 && dy == 0) || (dx == 0 && dy == 1));
+ assert((dx == 1 && dy == 0) || (dx == 0 && dy == 1) || (dx * dy == 1) || (dx * dy == -1));
ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(64, "ccv_mscr_chi(%d,%d)", dx, dy), a->sig, 0);
type = (CCV_GET_DATA_TYPE(type) == CCV_64F) ? CCV_64F | CCV_C1 : CCV_32F | CCV_C1;
- ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, a->rows - dy, a->cols - dx, CCV_C1 | CCV_32F | CCV_64F, type, sig);
+ ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, a->rows - abs(dy), a->cols - abs(dx), CCV_C1 | CCV_32F | CCV_64F, type, sig);
ccv_object_return_if_cached(, db);
int i, j, k, ch = CCV_GET_CHANNEL(a->type);
unsigned char *aptr = a->data.u8;
unsigned char *bptr = db->data.u8;
- if (dx == 1)
+ if (dx == 1 && dy == 0)
{
#define for_block(_for_set_b, _for_get_a) \
for (i = 0; i < db->rows; i++) \
@@ -124,28 +124,60 @@ static void _ccv_mscr_chi(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int typ
double v = (double)((_for_get_a(aptr, j * ch + ch, 0) - _for_get_a(aptr, j * ch, 0)) * (_for_get_a(aptr, j * ch + ch, 0) - _for_get_a(aptr, j * ch, 0))) / (double)(_for_get_a(aptr, j * ch, 0) + _for_get_a(aptr, j * ch + ch, 0) + 1e-10); \
for (k = 1; k < ch; k++) \
v += (double)((_for_get_a(aptr, j * ch + ch + k, 0) - _for_get_a(aptr, j * ch + k, 0)) * (_for_get_a(aptr, j * ch + ch + k, 0) - _for_get_a(aptr, j * ch + k, 0))) / (double)(_for_get_a(aptr, j * ch + k, 0) + _for_get_a(aptr, j * ch + ch + k, 0) + 1e-10); \
- _for_set_b(bptr, j, v, 0); \
+ _for_set_b(bptr, j, sqrt(v), 0); \
} \
aptr += a->step; \
bptr += db->step; \
}
- ccv_matrix_setter(db->type, ccv_matrix_getter, a->type, for_block);
+ ccv_matrix_setter_float_only(db->type, ccv_matrix_getter, a->type, for_block);
#undef for_block
- } else if (dy == 1) {
+ } else if (dy == 1 && dx == 0) {
#define for_block(_for_set_b, _for_get_a) \
for (i = 0; i < db->rows; i++) \
{ \
for (j = 0; j < db->cols; j++) \
{ \
- double v = (double)((_for_get_a(aptr, j * ch + a->step, 0) - _for_get_a(aptr, j * ch, 0)) * (_for_get_a(aptr, j * ch + a->step, 0) - _for_get_a(aptr, j * ch, 0))) / (double)(_for_get_a(aptr, j * ch, 0) + _for_get_a(aptr, j * ch + a->step, 0) + 1e-10); \
+ double v = (double)((_for_get_a(aptr + a->step, j * ch, 0) - _for_get_a(aptr, j * ch, 0)) * (_for_get_a(aptr + a->step, j * ch, 0) - _for_get_a(aptr, j * ch, 0))) / (double)(_for_get_a(aptr, j * ch, 0) + _for_get_a(aptr + a->step, j * ch, 0) + 1e-10); \
for (k = 1; k < ch; k++) \
- v += (double)((_for_get_a(aptr, j * ch + a->step + k, 0) - _for_get_a(aptr, j * ch + k, 0)) * (_for_get_a(aptr, j * ch + a->step + k, 0) - _for_get_a(aptr, j * ch + k, 0))) / (double)(_for_get_a(aptr, j * ch + k, 0) + _for_get_a(aptr, j * ch + a->step + k, 0) + 1e-10); \
- _for_set_b(bptr, j, v, 0); \
+ v += (double)((_for_get_a(aptr + a->step, j * ch + k, 0) - _for_get_a(aptr, j * ch + k, 0)) * (_for_get_a(aptr + a->step, j * ch + k, 0) - _for_get_a(aptr, j * ch + k, 0))) / (double)(_for_get_a(aptr, j * ch + k, 0) + _for_get_a(aptr + a->step, j * ch + k, 0) + 1e-10); \
+ _for_set_b(bptr, j, sqrt(v), 0); \
} \
aptr += a->step; \
bptr += db->step; \
}
- ccv_matrix_setter(db->type, ccv_matrix_getter, a->type, for_block);
+ ccv_matrix_setter_float_only(db->type, ccv_matrix_getter, a->type, for_block);
+#undef for_block
+ } else if (dx * dy == 1) {
+#define for_block(_for_set_b, _for_get_a) \
+ for (i = 0; i < db->rows; i++) \
+ { \
+ for (j = 0; j < db->cols; j++) \
+ { \
+ double v = (double)((_for_get_a(aptr + a->step, j * ch + ch, 0) - _for_get_a(aptr, j * ch, 0)) * (_for_get_a(aptr + a->step, j * ch + ch, 0) - _for_get_a(aptr, j * ch, 0))) / (double)(_for_get_a(aptr, j * ch, 0) + _for_get_a(aptr + a->step, j * ch + ch, 0) + 1e-10); \
+ for (k = 1; k < ch; k++) \
+ v += (double)((_for_get_a(aptr + a->step, j * ch + ch + k, 0) - _for_get_a(aptr, j * ch + k, 0)) * (_for_get_a(aptr + a->step, j * ch + ch + k, 0) - _for_get_a(aptr, j * ch + k, 0))) / (double)(_for_get_a(aptr, j * ch + k, 0) + _for_get_a(aptr + a->step, j * ch + ch + k, 0) + 1e-10); \
+ _for_set_b(bptr, j, sqrt(v * 0.5), 0); \
+ } \
+ aptr += a->step; \
+ bptr += db->step; \
+ }
+ ccv_matrix_setter_float_only(db->type, ccv_matrix_getter, a->type, for_block);
+#undef for_block
+ } else if (dx * dy == -1) {
+#define for_block(_for_set_b, _for_get_a) \
+ for (i = 0; i < db->rows; i++) \
+ { \
+ for (j = 0; j < db->cols; j++) \
+ { \
+ double v = (double)((_for_get_a(aptr + a->step, j * ch, 0) - _for_get_a(aptr, j * ch + ch, 0)) * (_for_get_a(aptr + a->step, j * ch, 0) - _for_get_a(aptr, j * ch + ch, 0))) / (double)(_for_get_a(aptr, j * ch + ch, 0) + _for_get_a(aptr + a->step, j * ch, 0) + 1e-10); \
+ for (k = 1; k < ch; k++) \
+ v += (double)((_for_get_a(aptr + a->step, j * ch + k, 0) - _for_get_a(aptr, j * ch + ch + k, 0)) * (_for_get_a(aptr + a->step, j * ch + k, 0) - _for_get_a(aptr, j * ch + ch + k, 0))) / (double)(_for_get_a(aptr, j * ch + ch + k, 0) + _for_get_a(aptr + a->step, j * ch + k, 0) + 1e-10); \
+ _for_set_b(bptr, j, sqrt(v * 0.5), 0); \
+ } \
+ aptr += a->step; \
+ bptr += db->step; \
+ }
+ ccv_matrix_setter_float_only(db->type, ccv_matrix_getter, a->type, for_block);
#undef for_block
}
}
@@ -157,21 +189,25 @@ typedef struct ccv_mscr_node {
// double link list
struct ccv_mscr_node* prev;
struct ccv_mscr_node* next;
+ ccv_point_t point;
+ int root;
+} ccv_mscr_node_t;
+
+typedef struct {
+ int size;
int rank;
int reinit;
int step_now;
int last_size;
- int size;
int prev_size;
double chi;
double prev_chi;
double min_slope;
- ccv_point_t point;
ccv_point_t min_point;
ccv_point_t max_point;
int last_mscr_area;
int mscr_area;
-} ccv_mscr_node_t;
+} ccv_mscr_root_t; // extended structure for ccv_mscr_node_t
typedef struct {
double chi;
@@ -192,16 +228,20 @@ static CCV_IMPLEMENT_QSORT(_ccv_mscr_edge_qsort, ccv_mscr_edge_t, less_than)
static void _ccv_mscr_init_node(ccv_mscr_node_t* node, int x, int y)
{
- node->rank = 0;
- node->reinit = 0x7FFFFFFF;
+ node->prev = node->next = node->shortcut = node; // endless double link list
node->point.x = x;
node->point.y = y;
- node->min_point = node->max_point = node->point;
- node->step_now = 0;
- node->chi = node->prev_chi = 0;
- node->last_size = node->size = node->prev_size = 1;
- node->prev = node->next = node->shortcut = node; // endless double link list
- node->last_mscr_area = node->mscr_area = -1;
+ node->root = -1;
+}
+
+static void _ccv_mscr_init_root(ccv_mscr_root_t* root, ccv_mscr_node_t* node)
+{
+ root->reinit = 0x7FFFFFFF;
+ root->min_point = root->max_point = node->point;
+ root->step_now = 0;
+ root->chi = root->prev_chi = 0;
+ root->last_size = root->size = root->prev_size = 1;
+ root->last_mscr_area = root->mscr_area = -1;
}
static ccv_mscr_node_t* _ccv_mscr_find_root(ccv_mscr_node_t* node)
@@ -232,6 +272,7 @@ static ccv_mscr_node_t* _ccv_mscr_find_root(ccv_mscr_node_t* node)
static void _ccv_mscr(ccv_dense_matrix_t* a, ccv_dense_matrix_t* h, ccv_dense_matrix_t* b, ccv_array_t* seq, ccv_mser_param_t params)
{
+ /* using 8-neighbor, as the inventor does for his default implementation */
ccv_dense_matrix_t* dx = 0;
_ccv_mscr_chi(a, &dx, CCV_32F, 1, 0);
ccv_dense_matrix_t* bdx = 0;
@@ -242,20 +283,23 @@ static void _ccv_mscr(ccv_dense_matrix_t* a, ccv_dense_matrix_t* h, ccv_dense_ma
ccv_dense_matrix_t* bdy = 0;
ccv_blur(dy, &bdy, 0, params.edge_blur_sigma);
ccv_matrix_free(dy);
+ ccv_dense_matrix_t* dxy = 0;
+ _ccv_mscr_chi(a, &dxy, CCV_32F, 1, 1);
+ ccv_dense_matrix_t* bdxy = 0;
+ ccv_blur(dxy, &bdxy, 0, params.edge_blur_sigma);
+ ccv_matrix_free(dxy);
+ ccv_dense_matrix_t* dxy2 = 0;
+ _ccv_mscr_chi(a, &dxy2, CCV_32F, 1, -1);
+ ccv_dense_matrix_t* bdxy2 = 0;
+ ccv_blur(dxy2, &bdxy2, 0, params.edge_blur_sigma);
+ ccv_matrix_free(dxy2);
int i, j;
ccv_mscr_node_t* node = (ccv_mscr_node_t*)ccmalloc(sizeof(ccv_mscr_node_t) * a->rows * a->cols);
+ ccv_mscr_edge_t* edge = (ccv_mscr_edge_t*)ccmalloc(sizeof(ccv_mscr_edge_t) * (bdx->rows * bdx->cols + bdy->rows * bdy->cols + bdxy->rows * bdxy->cols + bdxy2->rows * bdxy2->cols));
ccv_mscr_node_t* pnode = node;
- for (i = 0; i < a->rows; i++)
- for (j = 0; j < a->cols; j++)
- {
- _ccv_mscr_init_node(pnode, j, i);
- ++pnode;
- }
- ccv_mscr_edge_t* edge = (ccv_mscr_edge_t*)ccmalloc(sizeof(ccv_mscr_edge_t) * (bdx->rows * bdx->cols + bdy->rows * bdy->cols));
ccv_mscr_edge_t* pedge = edge;
/* generate edge graph and sort them */
double mean = 0;
- pnode = node;
float* bdx_ptr = bdx->data.f32;
assert(bdx->cols == a->cols - 1);
for (i = 0; i < bdx->rows; i++)
@@ -265,8 +309,10 @@ static void _ccv_mscr(ccv_dense_matrix_t* a, ccv_dense_matrix_t* h, ccv_dense_ma
mean += pedge->chi = bdx_ptr[j];
pedge->node[0] = pnode + j;
pedge->node[1] = pnode + j + 1;
+ _ccv_mscr_init_node(pnode + j, j, i); // init node in this for-loop
++pedge;
}
+ _ccv_mscr_init_node(pnode + bdx->cols, bdx->cols, i);
pnode += a->cols;
bdx_ptr += bdx->cols;
}
@@ -285,14 +331,47 @@ static void _ccv_mscr(ccv_dense_matrix_t* a, ccv_dense_matrix_t* h, ccv_dense_ma
pnode += a->cols;
bdy_ptr += bdy->cols;
}
- _ccv_mscr_edge_qsort(edge, bdx->rows * bdx->cols + bdy->rows * bdy->cols, 0);
+ assert(bdxy->rows == a->rows - 1 && bdxy->cols == a->cols - 1);
+ pnode = node;
+ float* bdxy_ptr = bdxy->data.f32;
+ for (i = 0; i < bdxy->rows; i++)
+ {
+ for (j = 0; j < bdxy->cols; j++)
+ {
+ mean += pedge->chi = bdxy_ptr[j];
+ pedge->node[0] = pnode + j;
+ pedge->node[1] = pnode + a->cols + j + 1;
+ ++pedge;
+ }
+ pnode += a->cols;
+ bdxy_ptr += bdxy->cols;
+ }
+ assert(bdxy2->rows == a->rows - 1 && bdxy2->cols == a->cols - 1);
+ pnode = node;
+ float* bdxy2_ptr = bdxy2->data.f32;
+ for (i = 0; i < bdxy2->rows; i++)
+ {
+ for (j = 0; j < bdxy2->cols; j++)
+ {
+ mean += pedge->chi = bdxy2_ptr[j];
+ pedge->node[0] = pnode + j + 1;
+ pedge->node[1] = pnode + a->cols + j;
+ ++pedge;
+ }
+ pnode += a->cols;
+ bdxy2_ptr += bdxy2->cols;
+ }
+ mean /= (double)(bdx->rows * bdx->cols + bdy->rows * bdy->cols + bdxy->rows * bdxy->cols + bdxy2->rows * bdxy2->cols);
+ ccv_mscr_edge_t* edge_end = edge + bdx->rows * bdx->cols + bdy->rows * bdy->cols + bdxy->rows * bdxy->cols + bdxy2->rows * bdxy2->cols;
ccv_matrix_free(bdx);
ccv_matrix_free(bdy);
+ ccv_matrix_free(bdxy);
+ ccv_matrix_free(bdxy2);
+ _ccv_mscr_edge_qsort(edge, edge_end - edge, 0);
/* evolute on the edge graph */
int seq_no = 0;
pedge = edge;
- ccv_mscr_edge_t* edge_end = edge + bdx->rows * bdx->cols + bdy->rows * bdy->cols;
- mean /= (double)(bdx->rows * bdx->cols + bdy->rows * bdy->cols);
+ ccv_array_t* mscr_root_list = ccv_array_new(sizeof(ccv_mscr_root_t), 64, 0);
ccv_array_t* mscr_area_list = ccv_array_new(sizeof(ccv_mscr_area_t), 64, 0);
for (i = 0; (i < params.max_evolution) && (pedge < edge_end); i++)
{
@@ -303,41 +382,68 @@ static void _ccv_mscr(ccv_dense_matrix_t* a, ccv_dense_matrix_t* h, ccv_dense_ma
// to process all the edges in the list that chi < thres
while (pedge < edge_end && pedge->chi < thres)
{
- ccv_mscr_node_t* root0 = _ccv_mscr_find_root(pedge->node[0]);
- ccv_mscr_node_t* root1 = _ccv_mscr_find_root(pedge->node[1]);
- if (root0 != root1)
+ ccv_mscr_node_t* node0 = _ccv_mscr_find_root(pedge->node[0]);
+ ccv_mscr_node_t* node1 = _ccv_mscr_find_root(pedge->node[1]);
+ if (node0 != node1)
{
- if (root1->rank > root0->rank)
+ ccv_mscr_root_t* root0 = (node0->root >= 0) ? (ccv_mscr_root_t*)ccv_array_get(mscr_root_list, node0->root) : 0;
+ ccv_mscr_root_t* root1 = (node1->root >= 0) ? (ccv_mscr_root_t*)ccv_array_get(mscr_root_list, node1->root) : 0;
+#define swap_node_and_root() \
+ do { \
+ ccv_mscr_node_t* node = node0; \
+ node0 = node1; \
+ node1 = node; \
+ ccv_mscr_root_t* root = root0; \
+ root0 = root1; \
+ root1 = root; \
+ } while (0) // to force it function-like (must include ;)
+ if (root0 && root1)
{
- ccv_mscr_node_t* root = root0;
- root0 = root1;
- root1 = root;
- } else if (root1->rank == root0->rank) {
- if (root1->size > root0->size)
- {
- ccv_mscr_node_t* root = root0;
- root0 = root1;
- root1 = root;
+ if (root1->rank > root0->rank)
+ swap_node_and_root();
+ else if (root1->rank == root0->rank) {
+ if (root1->size > root0->size)
+ swap_node_and_root();
+ ++root0->rank;
}
- ++root0->rank;
+ } else if (root1 && !root0)
+ swap_node_and_root();
+ if (!root0)
+ {
+ ccv_mscr_root_t root;
+ ccv_array_push(mscr_root_list, &root);
+ root0 = (ccv_mscr_root_t*)ccv_array_get(mscr_root_list, mscr_root_list->rnum - 1);
+ node0->root = mscr_root_list->rnum - 1;
+ _ccv_mscr_init_root(root0, node0);
}
+ if (root1 && root1->last_mscr_area >= 0 && root0->last_mscr_area == -1)
+ root0->last_mscr_area = root1->last_mscr_area;
if (root0->step_now < i)
/* faithful record the last size for area threshold check */
{
root0->last_size = root0->size;
root0->step_now = i;
}
- root1->shortcut = root0;
- root0->size += root1->size;
- root0->min_point.x = ccv_min(root0->min_point.x, root1->min_point.x);
- root0->min_point.y = ccv_min(root0->min_point.y, root1->min_point.y);
- root0->max_point.x = ccv_max(root0->max_point.x, root1->max_point.x);
- root0->max_point.y = ccv_max(root0->max_point.y, root1->max_point.y);
- root0->prev->next = root1;
- ccv_mscr_node_t* prev = root0->prev;
- root0->prev = root1->prev;
- root1->prev->next = root0; // consider self-referencing
- root1->prev = prev;
+ node1->shortcut = node0;
+ node0->prev->next = node1;
+ ccv_mscr_node_t* prev = node0->prev;
+ node0->prev = node1->prev;
+ node1->prev->next = node0; // consider self-referencing
+ node1->prev = prev;
+ if (root1)
+ {
+ root0->size += root1->size;
+ root0->min_point.x = ccv_min(root0->min_point.x, root1->min_point.x);
+ root0->min_point.y = ccv_min(root0->min_point.y, root1->min_point.y);
+ root0->max_point.x = ccv_max(root0->max_point.x, root1->max_point.x);
+ root0->max_point.y = ccv_max(root0->max_point.y, root1->max_point.y);
+ } else {
+ ++root0->size;
+ root0->min_point.x = ccv_min(root0->min_point.x, node1->point.x);
+ root0->min_point.y = ccv_min(root0->min_point.y, node1->point.y);
+ root0->max_point.x = ccv_max(root0->max_point.x, node1->point.x);
+ root0->max_point.y = ccv_max(root0->max_point.y, node1->point.y);
+ }
/* insert one endless double link list to another, see illustration:
* 0->1->2->3->4->5->0
* a->b->c->d->a
@@ -374,21 +480,22 @@ static void _ccv_mscr(ccv_dense_matrix_t* a, ccv_dense_matrix_t* h, ccv_dense_ma
{
if (i > root0->reinit + 1 && root0->size >= params.min_area && root0->size <= params.max_area)
{
- if (root0->last_mscr_area < 0 || /* I added the diversity check for MSCR, as most MSER algorithm does */
- (double)(root0->size - ((ccv_mscr_area_t*)ccv_array_get(mscr_area_list, root0->last_mscr_area))->size) / (double)((ccv_mscr_area_t*)ccv_array_get(mscr_area_list, root0->last_mscr_area))->size > params.min_diversity)
+ ccv_mscr_area_t* last_mscr_area = (root0->last_mscr_area >= 0) ? (ccv_mscr_area_t*)ccv_array_get(mscr_area_list, root0->last_mscr_area) : 0;
+ if (!last_mscr_area || /* I added the diversity check for MSCR, as most MSER algorithm does */
+ (double)(root0->size - last_mscr_area->size) / (double)last_mscr_area->size > params.min_diversity)
{
if (root0->mscr_area >= 0)
{
ccv_mscr_area_t* mscr_area = (ccv_mscr_area_t*)ccv_array_get(mscr_area_list, root0->mscr_area);
- mscr_area->head = root0;
- mscr_area->tail = root0->prev;
+ mscr_area->head = node0;
+ mscr_area->tail = node0->prev;
mscr_area->margin = 0;
mscr_area->size = root0->size;
mscr_area->seq_no = 0;
} else {
ccv_mscr_area_t mscr_area = {
- .head = root0,
- .tail = root0->prev,
+ .head = node0,
+ .tail = node0->prev,
.margin = 0,
.size = root0->size,
.seq_no = 0,
@@ -405,6 +512,7 @@ static void _ccv_mscr(ccv_dense_matrix_t* a, ccv_dense_matrix_t* h, ccv_dense_ma
++pedge;
}
}
+ ccv_array_free(mscr_root_list);
assert(seq->rsize == sizeof(ccv_mser_keypoint_t));
ccv_zero(b);
unsigned char* b_ptr = b->data.u8;
View
425 lib/ccv_resample.c
@@ -0,0 +1,425 @@
+#include "ccv.h"
+#include "ccv_internal.h"
+
+/* area interpolation resample is adopted from OpenCV */
+
+typedef struct {
+ int si, di;
+ unsigned int alpha;
+} ccv_int_alpha;
+
+static void _ccv_resample_area_8u(ccv_dense_matrix_t* a, ccv_dense_matrix_t* b)
+{
+ ccv_int_alpha* xofs = (ccv_int_alpha*)alloca(sizeof(ccv_int_alpha) * a->cols * 2);
+ int ch = ccv_clamp(CCV_GET_CHANNEL(a->type), 1, 4);
+ double scale_x = (double)a->cols / b->cols;
+ double scale_y = (double)a->rows / b->rows;
+ // double scale = 1.f / (scale_x * scale_y);
+ unsigned int inv_scale_256 = (int)(scale_x * scale_y * 0x10000);
+ int dx, dy, sx, sy, i, k;
+ for (dx = 0, k = 0; dx < b->cols; dx++)
+ {
+ double fsx1 = dx * scale_x, fsx2 = fsx1 + scale_x;
+ int sx1 = (int)(fsx1 + 1.0 - 1e-6), sx2 = (int)(fsx2);
+ sx1 = ccv_min(sx1, a->cols - 1);
+ sx2 = ccv_min(sx2, a->cols - 1);
+
+ if (sx1 > fsx1)
+ {
+ xofs[k].di = dx * ch;
+ xofs[k].si = (sx1 - 1) * ch;
+ xofs[k++].alpha = (unsigned int)((sx1 - fsx1) * 0x100);
+ }
+
+ for (sx = sx1; sx < sx2; sx++)
+ {
+ xofs[k].di = dx * ch;
+ xofs[k].si = sx * ch;
+ xofs[k++].alpha = 256;
+ }
+
+ if (fsx2 - sx2 > 1e-3)
+ {
+ xofs[k].di = dx * ch;
+ xofs[k].si = sx2 * ch;
+ xofs[k++].alpha = (unsigned int)((fsx2 - sx2) * 256);
+ }
+ }
+ int xofs_count = k;
+ unsigned int* buf = (unsigned int*)alloca(b->cols * ch * sizeof(unsigned int));
+ unsigned int* sum = (unsigned int*)alloca(b->cols * ch * sizeof(unsigned int));
+ for (dx = 0; dx < b->cols * ch; dx++)
+ buf[dx] = sum[dx] = 0;
+ dy = 0;
+ for (sy = 0; sy < a->rows; sy++)
+ {
+ unsigned char* a_ptr = a->data.u8 + a->step * sy;
+ for (k = 0; k < xofs_count; k++)
+ {
+ int dxn = xofs[k].di;
+ unsigned int alpha = xofs[k].alpha;
+ for (i = 0; i < ch; i++)
+ buf[dxn + i] += a_ptr[xofs[k].si + i] * alpha;
+ }
+ if ((dy + 1) * scale_y <= sy + 1 || sy == a->rows - 1)
+ {
+ unsigned int beta = (int)(ccv_max(sy + 1 - (dy + 1) * scale_y, 0.f) * 256);
+ unsigned int beta1 = 256 - beta;
+ unsigned char* b_ptr = b->data.u8 + b->step * dy;
+ if (beta <= 0)
+ {
+ for (dx = 0; dx < b->cols * ch; dx++)
+ {
+ b_ptr[dx] = ccv_clamp((sum[dx] + buf[dx] * 256) / inv_scale_256, 0, 255);
+ sum[dx] = buf[dx] = 0;
+ }
+ } else {
+ for (dx = 0; dx < b->cols * ch; dx++)
+ {
+ b_ptr[dx] = ccv_clamp((sum[dx] + buf[dx] * beta1) / inv_scale_256, 0, 255);
+ sum[dx] = buf[dx] * beta;
+ buf[dx] = 0;
+ }
+ }
+ dy++;
+ }
+ else
+ {
+ for(dx = 0; dx < b->cols * ch; dx++)
+ {
+ sum[dx] += buf[dx] * 256;
+ buf[dx] = 0;
+ }
+ }
+ }
+}
+
+typedef struct {
+ int si, di;
+ float alpha;
+} ccv_decimal_alpha;
+
+static void _ccv_resample_area(ccv_dense_matrix_t* a, ccv_dense_matrix_t* b)
+{
+ ccv_decimal_alpha* xofs = (ccv_decimal_alpha*)alloca(sizeof(ccv_decimal_alpha) * a->cols * 2);
+ int ch = CCV_GET_CHANNEL(a->type);
+ double scale_x = (double)a->cols / b->cols;
+ double scale_y = (double)a->rows / b->rows;
+ double scale = 1.f / (scale_x * scale_y);
+ int dx, dy, sx, sy, i, k;
+ for (dx = 0, k = 0; dx < b->cols; dx++)
+ {
+ double fsx1 = dx * scale_x, fsx2 = fsx1 + scale_x;
+ int sx1 = (int)(fsx1 + 1.0 - 1e-6), sx2 = (int)(fsx2);
+ sx1 = ccv_min(sx1, a->cols - 1);
+ sx2 = ccv_min(sx2, a->cols - 1);
+
+ if (sx1 > fsx1)
+ {
+ xofs[k].di = dx * ch;
+ xofs[k].si = (sx1 - 1) * ch;
+ xofs[k++].alpha = (float)((sx1 - fsx1) * scale);
+ }
+
+ for (sx = sx1; sx < sx2; sx++)
+ {
+ xofs[k].di = dx * ch;
+ xofs[k].si = sx * ch;
+ xofs[k++].alpha = (float)scale;
+ }
+
+ if (fsx2 - sx2 > 1e-3)
+ {
+ xofs[k].di = dx * ch;
+ xofs[k].si = sx2 * ch;
+ xofs[k++].alpha = (float)((fsx2 - sx2) * scale);
+ }
+ }
+ int xofs_count = k;
+ float* buf = (float*)alloca(b->cols * ch * sizeof(float));
+ float* sum = (float*)alloca(b->cols * ch * sizeof(float));
+ for (dx = 0; dx < b->cols * ch; dx++)
+ buf[dx] = sum[dx] = 0;
+ dy = 0;
+#define for_block(_for_get, _for_set) \
+ for (sy = 0; sy < a->rows; sy++) \
+ { \
+ unsigned char* a_ptr = a->data.u8 + a->step * sy; \
+ for (k = 0; k < xofs_count; k++) \
+ { \
+ int dxn = xofs[k].di; \
+ float alpha = xofs[k].alpha; \
+ for (i = 0; i < ch; i++) \
+ buf[dxn + i] += _for_get(a_ptr, xofs[k].si + i, 0) * alpha; \
+ } \
+ if ((dy + 1) * scale_y <= sy + 1 || sy == a->rows - 1) \
+ { \
+ float beta = ccv_max(sy + 1 - (dy + 1) * scale_y, 0.f); \
+ float beta1 = 1 - beta; \
+ unsigned char* b_ptr = b->data.u8 + b->step * dy; \
+ if (fabs(beta) < 1e-3) \
+ { \
+ for (dx = 0; dx < b->cols * ch; dx++) \
+ { \
+ _for_set(b_ptr, dx, sum[dx] + buf[dx], 0); \
+ sum[dx] = buf[dx] = 0; \
+ } \
+ } else { \
+ for (dx = 0; dx < b->cols * ch; dx++) \
+ { \
+ _for_set(b_ptr, dx, sum[dx] + buf[dx] * beta1, 0); \
+ sum[dx] = buf[dx] * beta; \
+ buf[dx] = 0; \
+ } \
+ } \
+ dy++; \
+ } \
+ else \
+ { \
+ for(dx = 0; dx < b->cols * ch; dx++) \
+ { \
+ sum[dx] += buf[dx]; \
+ buf[dx] = 0; \
+ } \
+ } \
+ }
+ ccv_matrix_getter(a->type, ccv_matrix_setter, b->type, for_block);
+#undef for_block
+}
+
+void ccv_resample(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int btype, int rows, int cols, int type)
+{
+ ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(64, "ccv_resample(%d,%d,%d)", rows, cols, type), a->sig, 0);
+ btype = (btype == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) : CCV_GET_DATA_TYPE(btype) | CCV_GET_CHANNEL(a->type);
+ ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, rows, cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), btype, sig);
+ ccv_object_return_if_cached(, db);
+ if (a->rows == db->rows && a->cols == db->cols)
+ {
+ if (CCV_GET_CHANNEL(a->type) == CCV_GET_CHANNEL(db->type) && CCV_GET_DATA_TYPE(db->type) == CCV_GET_DATA_TYPE(a->type))
+ memcpy(db->data.u8, a->data.u8, a->rows * a->step);
+ else {
+ ccv_shift(a, (ccv_matrix_t**)&db, 0, 0, 0);
+ }
+ return;
+ }
+ switch (type)
+ {
+ case CCV_INTER_AREA:
+ if (a->rows > db->rows && a->cols > db->cols)
+ {
+ /* using the fast alternative (fix point scale, 0x100 to avoid overflow) */
+ if (CCV_GET_DATA_TYPE(a->type) == CCV_8U && CCV_GET_DATA_TYPE(db->type) == CCV_8U && a->rows * a->cols / (db->rows * db->cols) < 0x100)
+ _ccv_resample_area_8u(a, db);
+ else
+ _ccv_resample_area(a, db);
+ break;
+ }
+ case CCV_INTER_LINEAR:
+ break;
+ case CCV_INTER_CUBIC:
+ break;
+ case CCV_INTER_LANCZOS:
+ break;
+ }
+}
+
+/* the following code is adopted from OpenCV cvPyrDown */
+void ccv_sample_down(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int src_x, int src_y)
+{
+ assert(src_x >= 0 && src_y >= 0);
+ ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(64, "ccv_sample_down(%d,%d)", src_x, src_y), a->sig, 0);
+ type = (type == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) : CCV_GET_DATA_TYPE(type) | CCV_GET_CHANNEL(a->type);
+ ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, a->rows / 2, a->cols / 2, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), type, sig);
+ ccv_object_return_if_cached(, db);
+ int ch = CCV_GET_CHANNEL(a->type);
+ int cols0 = db->cols - 1 - src_x;
+ int dy, sy = -2 + src_y, sx = src_x * ch, dx, k;
+ int* tab = (int*)alloca((a->cols + src_x + 2) * ch * sizeof(int));
+ for (dx = 0; dx < a->cols + src_x + 2; dx++)
+ for (k = 0; k < ch; k++)
+ tab[dx * ch + k] = ((dx >= a->cols) ? a->cols * 2 - 1 - dx : dx) * ch + k;
+ unsigned char* buf = (unsigned char*)alloca(5 * db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int)));
+ int bufstep = db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int));
+ unsigned char* b_ptr = db->data.u8;
+ /* why is src_y * 4 in computing the offset of row?
+ * Essentially, it means sy - src_y but in a manner that doesn't result negative number.
+ * notice that we added src_y before when computing sy in the first place, however,
+ * it is not desirable to have that offset when we try to wrap it into our 5-row buffer (
+ * because in later rearrangement, we have no src_y to backup the arrangement). In
+ * such micro scope, we managed to stripe 5 addition into one shift and addition. */
+#define for_block(_for_get_a, _for_set, _for_get, _for_set_b) \
+ for (dy = 0; dy < db->rows; dy++) \
+ { \
+ for(; sy <= dy * 2 + 2 + src_y; sy++) \
+ { \
+ unsigned char* row = buf + ((sy + src_y * 4 + 2) % 5) * bufstep; \
+ int _sy = (sy < 0) ? -1 - sy : (sy >= a->rows) ? a->rows * 2 - 1 - sy : sy; \
+ unsigned char* a_ptr = a->data.u8 + a->step * _sy; \
+ for (k = 0; k < ch; k++) \
+ _for_set(row, k, _for_get_a(a_ptr, sx + k, 0) * 10 + _for_get_a(a_ptr, ch + sx + k, 0) * 5 + _for_get_a(a_ptr, 2 * ch + sx + k, 0), 0); \
+ for(dx = ch; dx < cols0 * ch; dx += ch) \
+ for (k = 0; k < ch; k++) \
+ _for_set(row, dx + k, _for_get_a(a_ptr, dx * 2 + sx + k, 0) * 6 + (_for_get_a(a_ptr, dx * 2 + sx + k - ch, 0) + _for_get_a(a_ptr, dx * 2 + sx + k + ch, 0)) * 4 + _for_get_a(a_ptr, dx * 2 + sx + k - ch * 2, 0) + _for_get_a(a_ptr, dx * 2 + sx + k + ch * 2, 0), 0); \
+ x_block(_for_get_a, _for_set, _for_get, _for_set_b); \
+ } \
+ unsigned char* rows[5]; \
+ for(k = 0; k < 5; k++) \
+ rows[k] = buf + ((dy * 2 + k) % 5) * bufstep; \
+ for(dx = 0; dx < db->cols * ch; dx++) \
+ _for_set_b(b_ptr, dx, (_for_get(rows[2], dx, 0) * 6 + (_for_get(rows[1], dx, 0) + _for_get(rows[3], dx, 0)) * 4 + _for_get(rows[0], dx, 0) + _for_get(rows[4], dx, 0)) / 256, 0); \
+ b_ptr += db->step; \
+ }
+ int no_8u_type = (a->type & CCV_8U) ? CCV_32S : a->type;
+ if (src_x > 0)
+ {
+#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
+ for (dx = cols0 * ch; dx < db->cols * ch; dx += ch) \
+ for (k = 0; k < ch; k++) \
+ _for_set(row, dx + k, _for_get_a(a_ptr, tab[dx * 2 + sx + k], 0) * 6 + (_for_get_a(a_ptr, tab[dx * 2 + sx + k - ch], 0) + _for_get_a(a_ptr, tab[dx * 2 + sx + k + ch], 0)) * 4 + _for_get_a(a_ptr, tab[dx * 2 + sx + k - ch * 2], 0) + _for_get_a(a_ptr, tab[dx * 2 + sx + k + ch * 2], 0), 0);
+ ccv_matrix_getter_a(a->type, ccv_matrix_setter_getter, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
+#undef x_block
+ } else {
+#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
+ for (k = 0; k < ch; k++) \
+ _for_set(row, (db->cols - 1) * ch + k, _for_get_a(a_ptr, a->cols * ch + sx - ch + k, 0) * 10 + _for_get_a(a_ptr, (a->cols - 2) * ch + sx + k, 0) * 5 + _for_get_a(a_ptr, (a->cols - 3) * ch + sx + k, 0), 0);
+ ccv_matrix_getter_a(a->type, ccv_matrix_setter_getter, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
+#undef x_block
+ }
+#undef for_block
+}
+
+void ccv_sample_up(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, int src_x, int src_y)
+{
+ assert(src_x >= 0 && src_y >= 0);
+ ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(64, "ccv_sample_up(%d,%d)", src_x, src_y), a->sig, 0);
+ type = (type == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) : CCV_GET_DATA_TYPE(type) | CCV_GET_CHANNEL(a->type);
+ ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, a->rows * 2, a->cols * 2, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), type, sig);
+ ccv_object_return_if_cached(, db);
+ int ch = CCV_GET_CHANNEL(a->type);
+ int cols0 = a->cols - 1 - src_x;
+ int y, x, sy = -1 + src_y, sx = src_x * ch, k;
+ int* tab = (int*)alloca((a->cols + src_x + 2) * ch * sizeof(int));
+ for (x = 0; x < a->cols + src_x + 2; x++)
+ for (k = 0; k < ch; k++)
+ tab[x * ch + k] = ((x >= a->cols) ? a->cols * 2 - 1 - x : x) * ch + k;
+ unsigned char* buf = (unsigned char*)alloca(3 * db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int)));
+ int bufstep = db->cols * ch * ccv_max(CCV_GET_DATA_TYPE_SIZE(db->type), sizeof(int));
+ unsigned char* b_ptr = db->data.u8;
+ /* why src_y * 2: the same argument as in ccv_sample_down */
+#define for_block(_for_get_a, _for_set, _for_get, _for_set_b) \
+ for (y = 0; y < a->rows; y++) \
+ { \
+ for (; sy <= y + 1 + src_y; sy++) \
+ { \
+ unsigned char* row = buf + ((sy + src_y * 2 + 1) % 3) * bufstep; \
+ int _sy = (sy < 0) ? -1 - sy : (sy >= a->rows) ? a->rows * 2 - 1 - sy : sy; \
+ unsigned char* a_ptr = a->data.u8 + a->step * _sy; \
+ if (a->cols == 1) \
+ { \
+ for (k = 0; k < ch; k++) \
+ { \
+ _for_set(row, k, _for_get_a(a_ptr, k, 0) * (G025 + G075 + G125), 0); \
+ _for_set(row, k + ch, _for_get_a(a_ptr, k, 0) * (G025 + G075 + G125), 0); \
+ } \
+ continue; \
+ } \
+ if (sx == 0) \
+ { \
+ for (k = 0; k < ch; k++) \
+ { \
+ _for_set(row, k, _for_get_a(a_ptr, k + sx, 0) * (G025 + G075) + _for_get_a(a_ptr, k + sx + ch, 0) * G125, 0); \
+ _for_set(row, k + ch, _for_get_a(a_ptr, k + sx, 0) * (G125 + G025) + _for_get_a(a_ptr, k + sx + ch, 0) * G075, 0); \
+ } \
+ } \
+ /* some serious flaw in computing Gaussian weighting in previous version
+ * specially, we are doing perfect upsampling (2x) so, it concerns a grid like:
+ * XXYY
+ * XXYY
+ * in this case, to upsampling, the weight should be from distance 0.25 and 1.25, and 0.25 and 0.75
+ * previously, it was mistakingly be 0.0 1.0, 0.5 0.5 (imperfect upsampling (2x - 1)) */ \
+ for (x = (sx == 0) ? ch : 0; x < cols0 * ch; x += ch) \
+ { \
+ for (k = 0; k < ch; k++) \
+ { \
+ _for_set(row, x * 2 + k, _for_get_a(a_ptr, x + sx - ch + k, 0) * G075 + _for_get_a(a_ptr, x + sx + k, 0) * G025 + _for_get_a(a_ptr, x + sx + ch + k, 0) * G125, 0); \
+ _for_set(row, x * 2 + ch + k, _for_get_a(a_ptr, x + sx - ch + k, 0) * G125 + _for_get_a(a_ptr, x + sx + k, 0) * G025 + _for_get_a(a_ptr, x + sx + ch + k, 0) * G075, 0); \
+ } \
+ } \
+ x_block(_for_get_a, _for_set, _for_get, _for_set_b); \
+ } \
+ unsigned char* rows[3]; \
+ for (k = 0; k < 3; k++) \
+ rows[k] = buf + ((y + k) % 3) * bufstep; \
+ for (x = 0; x < db->cols * ch; x++) \
+ { \
+ _for_set_b(b_ptr, x, (_for_get(rows[0], x, 0) * G075 + _for_get(rows[1], x, 0) * G025 + _for_get(rows[2], x, 0) * G125) / GALL, 0); \
+ _for_set_b(b_ptr + db->step, x, (_for_get(rows[0], x, 0) * G125 + _for_get(rows[1], x, 0) * G025 + _for_get(rows[2], x, 0) * G075) / GALL, 0); \
+ } \
+ b_ptr += 2 * db->step; \
+ }
+ int no_8u_type = (a->type & CCV_8U) ? CCV_32S : a->type;
+ /* unswitch if condition in manual way */
+ if ((a->type & CCV_8U) || (a->type & CCV_32S) || (a->type & CCV_64S))
+ {
+#define G025 (23)
+#define G075 (8)
+#define G125 (1)
+#define GALL (1024)
+ if (src_x > 0)
+ {
+#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
+ for (x = cols0 * ch; x < a->cols * ch; x += ch) \
+ for (k = 0; k < ch; k++) \
+ { \
+ _for_set(row, x * 2 + k, _for_get_a(a_ptr, tab[x + sx - ch + k], 0) * G075 + _for_get_a(a_ptr, tab[x + sx + k], 0) * G025 + _for_get_a(a_ptr, tab[x + sx + ch + k], 0) * G125, 0); \
+ _for_set(row, x * 2 + ch + k, _for_get_a(a_ptr, tab[x + sx - ch + k], 0) * G125 + _for_get_a(a_ptr, tab[x + sx + k], 0) * G025 + _for_get_a(a_ptr, tab[x + sx + ch + k], 0) * G075, 0); \
+ }
+ ccv_matrix_getter_integer_only(a->type, ccv_matrix_setter_getter_integer_only, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
+#undef x_block
+ } else {
+#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
+ for (k = 0; k < ch; k++) \
+ { \
+ _for_set(row, (a->cols - 1) * 2 * ch + k, _for_get_a(a_ptr, (a->cols - 2) * ch + k, 0) * G075 + _for_get_a(a_ptr, (a->cols - 1) * ch + k, 0) * (G025 + G125), 0); \
+ _for_set(row, (a->cols - 1) * 2 * ch + ch + k, _for_get_a(a_ptr, (a->cols - 2) * ch + k, 0) * G125 + _for_get_a(a_ptr, (a->cols - 1) * ch + k, 0) * (G025 + G075), 0); \
+ }
+ ccv_matrix_getter_integer_only(a->type, ccv_matrix_setter_getter_integer_only, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
+#undef x_block
+ }
+#undef GALL
+#undef G125
+#undef G075
+#undef G025
+ } else {
+#define G025 (0.705385)
+#define G075 (0.259496)
+#define G125 (0.035119)
+#define GALL (1)
+ if (src_x > 0)
+ {
+#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
+ for (x = cols0 * ch; x < a->cols * ch; x += ch) \
+ for (k = 0; k < ch; k++) \
+ { \
+ _for_set(row, x * 2 + k, _for_get_a(a_ptr, tab[x + sx - ch + k], 0) * G075 + _for_get_a(a_ptr, tab[x + sx + k], 0) * G025 + _for_get_a(a_ptr, tab[x + sx + ch + k], 0) * G125, 0); \
+ _for_set(row, x * 2 + ch + k, _for_get_a(a_ptr, tab[x + sx - ch + k], 0) * G125 + _for_get_a(a_ptr, tab[x + sx + k], 0) * G025 + _for_get_a(a_ptr, tab[x + sx + ch + k], 0) * G075, 0); \
+ }
+ ccv_matrix_getter_float_only(a->type, ccv_matrix_setter_getter_float_only, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
+#undef x_block
+ } else {
+#define x_block(_for_get_a, _for_set, _for_get, _for_set_b) \
+ for (k = 0; k < ch; k++) \
+ { \
+ _for_set(row, (a->cols - 1) * 2 * ch + k, _for_get_a(a_ptr, (a->cols - 2) * ch + k, 0) * G075 + _for_get_a(a_ptr, (a->cols - 1) * ch + k, 0) * (G025 + G125), 0); \
+ _for_set(row, (a->cols - 1) * 2 * ch + ch + k, _for_get_a(a_ptr, (a->cols - 2) * ch + k, 0) * G125 + _for_get_a(a_ptr, (a->cols - 1) * ch + k, 0) * (G025 + G075), 0); \
+ }
+ ccv_matrix_getter_float_only(a->type, ccv_matrix_setter_getter_float_only, no_8u_type, ccv_matrix_setter_b, db->type, for_block);
+#undef x_block
+ }
+#undef GALL
+#undef G125
+#undef G075
+#undef G025
+ }
+#undef for_block
+}
View
2  lib/makefile
@@ -14,7 +14,7 @@ all: libccv.a
clean:
rm -f *.o 3rdparty/sha1/*.o 3rdparty/kissfft/*.o libccv.a
-libccv.a: ccv_cache.o ccv_memory.o 3rdparty/sha1/sha1.o 3rdparty/kissfft/kiss_fft.o 3rdparty/kissfft/kiss_fftnd.o 3rdparty/kissfft/kiss_fftr.o 3rdparty/kissfft/kiss_fftndr.o 3rdparty/kissfft/kissf_fft.o 3rdparty/kissfft/kissf_fftnd.o 3rdparty/kissfft/kissf_fftr.o 3rdparty/kissfft/kissf_fftndr.o ccv_io.o ccv_numeric.o ccv_algebra.o ccv_util.o ccv_basic.o ccv_classic.o ccv_daisy.o ccv_sift.o ccv_bbf.o ccv_mser.o ccv_swt.o ccv_dpm.o
+libccv.a: ccv_cache.o ccv_memory.o 3rdparty/sha1/sha1.o 3rdparty/kissfft/kiss_fft.o 3rdparty/kissfft/kiss_fftnd.o 3rdparty/kissfft/kiss_fftr.o 3rdparty/kissfft/kiss_fftndr.o 3rdparty/kissfft/kissf_fft.o 3rdparty/kissfft/kissf_fftnd.o 3rdparty/kissfft/kissf_fftr.o 3rdparty/kissfft/kissf_fftndr.o ccv_io.o ccv_numeric.o ccv_algebra.o ccv_util.o ccv_basic.o ccv_resample.o ccv_classic.o ccv_daisy.o ccv_sift.o ccv_bbf.o ccv_mser.o ccv_swt.o ccv_dpm.o
ar rcs $@ $^
ccv_io.o: ccv_io.c ccv.h ccv_internal.h io/*.c
View
BIN  samples/puzzle.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Please sign in to comment.
Something went wrong with that request. Please try again.