/* * 45°回転したIntegral Image */ void nv_integral_tilted(nv_matrix_t *integral, const nv_matrix_t *img, int channel) { int row, col, scol, srow; int erow = img->rows + 1; int ecol = img->cols + 1; nv_matrix_t *prev_tilted = nv_matrix_alloc(img->cols + 1, 1); NV_ASSERT( integral->rows - 1 == img->rows && integral->cols - 1 == img->cols ); nv_matrix_zero(prev_tilted); nv_matrix_zero(integral); for (scol = img->cols; scol > 0; --scol) { float tilted_sum = 0.0f; for (row = 1, col = scol; row < erow && col < ecol; ++row, ++col) { float tilted_val = NV_MAT3D_V(img, row - 1, col - 1, channel); if (col + 1 == ecol) { NV_MAT3D_V(integral, row, col, 0) = NV_MAT3D_V(integral, row - 1, col, 0) + tilted_sum + tilted_val; } else { NV_MAT3D_V(integral, row, col, 0) = NV_MAT3D_V(integral, row - 1, col + 1, 0) + NV_MAT_V(prev_tilted, 0, col) + tilted_sum + tilted_val; } tilted_sum += tilted_val; NV_MAT_V(prev_tilted, 0, col) = tilted_sum; } } for (srow = 2; srow < erow; ++srow) { float tilted_sum = 0.0f; for (row = srow, col = 1; row < erow && col < ecol; ++row, ++col) { float tilted_val = NV_MAT3D_V(img, row - 1, col - 1, channel); if (col + 1 == ecol) { NV_MAT3D_V(integral, row, col, 0) = NV_MAT3D_V(integral, row - 1, col, 0) + tilted_sum + tilted_val; } else { NV_MAT3D_V(integral, row, col, 0) = NV_MAT3D_V(integral, row - 1, col + 1, 0) + NV_MAT_V(prev_tilted, 0, col) + tilted_sum + tilted_val; } tilted_sum += tilted_val; NV_MAT_V(prev_tilted, 0, col) = tilted_sum; } } nv_matrix_free(&prev_tilted); }
/* * Integral Image * 積分画像 */ void nv_integral(nv_matrix_t *integral, const nv_matrix_t *img, int channel) { int row, col; int erow = img->rows + 1; int ecol = img->cols + 1; NV_ASSERT( integral->rows - 1 == img->rows && integral->cols - 1 == img->cols ); nv_matrix_zero(integral); for (row = 1; row < erow; ++row) { float col_sum = 0.0f; for (col = 1; col < ecol; ++col) { float col_val = NV_MAT3D_V(img, row - 1, col - 1, channel); NV_MAT3D_V(integral, row, col, 0) = NV_MAT3D_V(integral, row - 1, col, 0) + col_sum + col_val; col_sum += col_val; } } }
void nv_pstable_hash(const nv_pstable_t *ps, nv_pstable_hash_t *hash, const nv_matrix_t *vec, int vec_m) { int k, l; float r_fac = 1.0f / ps->r; NV_ASSERT(ps->a->n == vec->n); memset(hash, 0, sizeof(nv_pstable_hash_t) * ps->l); for (l = 0; l < ps->l; ++l) { for (k = 0; k < ps->k; ++k) { /* s = (ax + b) / r */ float s = nv_vector_dot(ps->a, NV_MAT_M(ps->a, l, k), vec, vec_m); s += NV_MAT3D_V(ps->b, l, k, 0); s *= r_fac; hash[l] = hash[l] * 33 + (int)s; } } }
void nv_matrix3d_print(FILE *out, const nv_matrix_t *mat, int channel) { int row, col; fprintf(out, "("); for (row = 0; row < mat->rows; ++row) { if (row != 0) { fprintf(out, ",\n"); } fprintf(out, "[ "); for (col = 0; col < mat->cols; ++col) { if (col != 0) { fprintf(out, ", "); } fprintf(out, "%10E", NV_MAT3D_V(mat, row, col, channel)); } fprintf(out, "]"); } fprintf(out, ");\n"); }
otama_image_t * otama_image_load_rgb8(int width, int height, const void *data) { otama_image_t *p = nv_alloc_type(otama_image_t, 1); int x, y, c; const uint8_t *d = (const uint8_t *)data; p->has_id = 0; p->image = nv_matrix3d_alloc(3, height, width); memset(&p->id, 0, sizeof(otama_id_t)); // TODO: insert for (y = 0; y < height; ++y) { for (x = 0; x < height; ++x) { for (c = 0; c < 3; ++c) { NV_MAT3D_V(p->image, y, x, 2 - c) = (float)*d++; } } } return p; }
void nv_face_haarlike(nv_face_haarlike_normalize_e normalize_type, nv_matrix_t *feature, int feature_m, const nv_matrix_t *sum, int x, int y, int width, int height) { int ix, iy, n; float v, vmax, vmin; float xscale = width / 32.0f; float yscale = height / 32.0f; float ystep = yscale; float xstep = xscale; int hystep = (32 - 8) / 2 * 8; int sy = NV_ROUND_INT(4.0f * ystep); int sx = NV_ROUND_INT(4.0f * xstep); int hy, hx; nv_vector_zero(feature, feature_m); // level1 #ifdef _OPENMP //#pragma omp parallel for private(ix) #endif for (iy = 0, hy = 0; iy < 32-8; iy += 2, ++hy) { int py = y + NV_ROUND_INT(ystep * iy); int ey = py + NV_ROUND_INT(8.0f * ystep); const float pty = (ey - py) * 255.0f; for (ix = 0, hx = 0; ix < 32-8; ix += 2, ++hx) { int px = x + NV_ROUND_INT(xstep * ix); int ex = px + NV_ROUND_INT(8.0f * xstep); float p1, p2, area, ptx; // 全エリア area = NV_MAT3D_V(sum, ey, ex, 0) - NV_MAT3D_V(sum, ey, px, 0) - (NV_MAT3D_V(sum, py, ex, 0) - NV_MAT3D_V(sum, py, px, 0)); // 1 // [+] // [-] p1 = NV_MAT3D_V(sum, py + sy, ex, 0) - NV_MAT3D_V(sum, py + sy, px, 0) - (NV_MAT3D_V(sum, py, ex, 0) - NV_MAT3D_V(sum, py, px, 0)); p2 = area - p1; ptx = (ex - px) * 255.0f; p1 /= ((py + sy) - py) * ptx; p2 /= (ey - (py + sy)) * ptx; if (p1 > p2) { NV_MAT_V(feature, feature_m, hy * hystep + hx * 8 + 0) = p1 - p2; } else { NV_MAT_V(feature, feature_m, hy * hystep + hx * 8 + 1) = p2 - p1; } // 2 // [+][-] p1 = NV_MAT3D_V(sum, ey, px + sx, 0) - NV_MAT3D_V(sum, ey, px, 0) - (NV_MAT3D_V(sum, py, px + sx, 0) - NV_MAT3D_V(sum, py, px, 0)); p2 = area - p1; p1 /= ((px + sx) - px) * pty; p2 /= (ex - (px + sx)) * pty; if (p1 > p2) { NV_MAT_V(feature, feature_m, hy * hystep + hx * 8 + 2) = p1 - p2; } else { NV_MAT_V(feature, feature_m, hy * hystep + hx * 8 + 3) = p2 - p1; } // 3 p1 = nv_face_haarlike_diagonal_filter(1, sum, px, py, xscale, yscale); if (p1 > 0.0f) { NV_MAT_V(feature, feature_m, hy * hystep + hx * 8 + 4) = p1; } else { NV_MAT_V(feature, feature_m, hy * hystep + hx * 8 + 5) = -p1; } // 4 p1 = nv_face_haarlike_diagonal_filter(2, sum, px, py, xscale, yscale); if (p1 > 0.0f) { NV_MAT_V(feature, feature_m, hy * hystep + hx * 8 + 6) = p1; } else { NV_MAT_V(feature, feature_m, hy * hystep + hx * 8 + 7) = -p1; } } } // 正規化 switch (normalize_type) { case NV_NORMALIZE_MAX: // Maximum=1.0 vmax = 0.0f; vmin = FLT_MAX; for (n = 0; n < feature->n; ++n) { if (NV_MAT_V(feature, feature_m, n) > vmax) { vmax = NV_MAT_V(feature, feature_m, n); } if (NV_MAT_V(feature, feature_m, n) != 0.0f && NV_MAT_V(feature, feature_m, n) < vmin) { vmin = NV_MAT_V(feature, feature_m, n); } } if (vmax != 0.0f && vmax > vmin) { v = 1.0f / (vmax - vmin); for (n = 0; n < feature->n; ++n) { if (NV_MAT_V(feature, feature_m, n) != 0.0f) { NV_MAT_V(feature, feature_m, n) = (NV_MAT_V(feature, feature_m, n) - vmin) * v; } } } break; case NV_NORMALIZE_NORM: // Vector Norm=1.0 v = 0.0f; for (n = 0; n < feature->n; ++n) { v += NV_MAT_V(feature, feature_m, n) * NV_MAT_V(feature, feature_m, n); } if (v != 0.0) { v = 1.0f / sqrtf(v); for (n = 0; n < feature->n; ++n) { NV_MAT_V(feature, feature_m, n) *= v; } } break; case NV_NORMALIZE_NONE: default: break; } }
void nv_shapecontext_feature(nv_shapecontext_t *sctx, const nv_matrix_t *img, float r ) { int m, row, col, pc, i, l; nv_matrix_t *edge = nv_matrix3d_alloc(1, img->rows, img->cols); nv_matrix_t *points = nv_matrix_alloc(2, img->m); int *rand_idx = (int *)nv_malloc(sizeof(int) * img->m); float u_x, u_y, p_x, p_y, r_e; int pn; // 細線化 nv_matrix_zero(points); nv_shapecontext_edge_image(edge, img); pc = 0; u_x = 0.0f; u_y = 0.0f; for (row = 0; row < edge->rows; ++row) { for (col = 0; col < edge->cols; ++col) { if (NV_MAT3D_V(edge, row, col, 0) > 50.0f) { NV_MAT_V(points, pc, 0) = (float)row; NV_MAT_V(points, pc, 1) = (float)col; ++pc; u_y += (float)row; u_x += (float)col; } } } u_x /= pc; u_y /= pc; // 指定数の特徴にする(ランダム) pn = NV_MIN(pc, sctx->sctx->list); nv_shuffle_index(rand_idx, 0, pc); #if 1 { float max_x, max_y; if (pc < sctx->sctx->list) { // 足りないときはランダムに増やす for (i = pc; i < sctx->sctx->list; ++i) { rand_idx[i] = (int)(nv_rand() * pn); } } pc = pn = sctx->sctx->list; // 半径を求める max_x = 0.0f; max_y = 0.0f; for (m = 0; m < pn; ++m) { float yd = fabsf(NV_MAT_V(points, rand_idx[m], 0) - u_y); float xd = fabsf(NV_MAT_V(points, rand_idx[m], 1) - u_x); max_x = NV_MAX(max_x, xd); max_y = NV_MAX(max_y, yd); } r = (float)img->rows/2.0f;//NV_MAX(max_x, max_y) * 1.0f; } #endif // log(r) = 5の基底定数を求める r_e = powf(r, 1.0f / NV_SC_LOG_R_BIN); // histgramを計算する sctx->n = pn; nv_matrix_zero(sctx->sctx); nv_matrix_zero(sctx->tan_angle); for (l = 0; l < pn; ++l) { // tangent angle #if 0 float max_bin = 0.0f, min_bin = FLT_MAX; float tan_angle = tangent_angle( r, NV_MAT_V(points, rand_idx[l], 0), NV_MAT_V(points, rand_idx[l], 1), points, pc); #else float tan_angle = 0.0f; #endif p_y = NV_MAT_V(points, rand_idx[l], 0); p_x = NV_MAT_V(points, rand_idx[l], 1); NV_MAT_V(sctx->tan_angle, l, 0) = tan_angle; NV_MAT_V(sctx->coodinate, l, 0) = p_y; NV_MAT_V(sctx->coodinate, l, 1) = p_x; NV_MAT_V(sctx->radius, l, 0) = r; // shape context for (i = 0; i < pn; ++i) { // # i ≠ l判定はとりあえずしない float xd = NV_MAT_V(points, rand_idx[i], 1) - p_x; float yd = NV_MAT_V(points, rand_idx[i], 0) - p_y; //int row = i / img->rows; //int col = i % img->rows; //float xd = col - p_x; //float yd = row - p_y; float theta; float log_r = logf(sqrtf(xd * xd + yd * yd)) / logf(r_e); float atan_r = atan2f(xd, yd); //if (NV_MAT3D_V(img, row, col, 0) == 0.0f) { // continue; //} if (i == l) { continue; } if (atan_r < 0.0f) { atan_r = 2.0f * NV_PI + atan_r; } if (tan_angle > 0.0f) { if (atan_r + tan_angle > 2.0f * NV_PI) { atan_r = atan_r + tan_angle - 2.0f * NV_PI; } else { atan_r += tan_angle; } } else { if (atan_r + tan_angle < 0.0f) { atan_r = 2.0f * NV_PI + (atan_r + tan_angle); } else { atan_r += tan_angle; } } theta = atan_r / (2.0f * NV_PI / NV_SC_THETA_BIN); if (theta < NV_SC_THETA_BIN && log_r < NV_SC_LOG_R_BIN) { NV_MAT3D_LIST_V(sctx->sctx, l, (int)log_r, (int)theta, 0) += 1.0f; } } #if 0 for (row = 0; row < NV_SC_LOG_R_BIN; ++row) { for (col = 0; col < NV_SC_THETA_BIN; ++col) { max_bin = NV_MAX(max_bin, NV_MAT3D_LIST_V(sctx->sctx, l, row, col, 0)); min_bin = NV_MIN(min_bin, NV_MAT3D_LIST_V(sctx->sctx, l, row, col, 0)); } } if (max_bin > 0.0f) { for (row = 0; row < NV_SC_LOG_R_BIN; ++row) { for (col = 0; col < NV_SC_THETA_BIN; ++col) { NV_MAT3D_LIST_V(sctx->sctx, l, row, col, 0) = (NV_MAT3D_LIST_V(sctx->sctx, l, row, col, 0) - min_bin) / (max_bin - min_bin); } } } #endif } nv_matrix_free(&edge); nv_matrix_free(&points); nv_free(rand_idx); }