ccv_nnc_symbolic_graph_t* ccv_nnc_symbolic_graph_from_while_symbol(const ccv_nnc_symbolic_graph_t* const graph, const ccv_nnc_graph_exec_symbol_t while_symbol) { assert(graph->sub_graphs); assert(while_symbol.graph == graph); assert(while_symbol.d < graph->exec_symbol_info->rnum); ccv_nnc_graph_exec_symbol_info_t* symbol_info = (ccv_nnc_graph_exec_symbol_info_t*)ccv_array_get(graph->exec_symbol_info, while_symbol.d); assert(symbol_info->graph_ref <= graph->sub_graphs->rnum); return *(ccv_nnc_symbolic_graph_t**)ccv_array_get(graph->sub_graphs, symbol_info->graph_ref - 1); }
int main(int argc, char** argv) { assert(argc >= 3); int i; ccv_enable_default_cache(); ccv_dense_matrix_t* image = 0; ccv_icf_classifier_cascade_t* cascade = ccv_icf_read_classifier_cascade(argv[2]); ccv_read(argv[1], &image, CCV_IO_ANY_FILE | CCV_IO_RGB_COLOR); if (image != 0) { unsigned int elapsed_time = get_current_time(); ccv_array_t* seq = ccv_icf_detect_objects(image, &cascade, 1, ccv_icf_default_params); elapsed_time = get_current_time() - elapsed_time; for (i = 0; i < seq->rnum; i++) { ccv_comp_t* comp = (ccv_comp_t*)ccv_array_get(seq, i); printf("%d %d %d %d %f\n", comp->rect.x, comp->rect.y, comp->rect.width, comp->rect.height, comp->confidence); } printf("total : %d in time %dms\n", seq->rnum, elapsed_time); ccv_array_free(seq); ccv_matrix_free(image); } else { FILE* r = fopen(argv[1], "rt"); if (argc == 4) chdir(argv[3]); if(r) { size_t len = 1024; char* file = (char*)malloc(len); ssize_t read; while((read = getline(&file, &len, r)) != -1) { while(read > 1 && isspace(file[read - 1])) read--; file[read] = 0; image = 0; ccv_read(file, &image, CCV_IO_ANY_FILE | CCV_IO_RGB_COLOR); assert(image != 0); ccv_array_t* seq = ccv_icf_detect_objects(image, &cascade, 1, ccv_icf_default_params); for (i = 0; i < seq->rnum; i++) { ccv_comp_t* comp = (ccv_comp_t*)ccv_array_get(seq, i); printf("%s %d %d %d %d %f\n", file, comp->rect.x, comp->rect.y, comp->rect.width, comp->rect.height, comp->confidence); } ccv_array_free(seq); ccv_matrix_free(image); } free(file); fclose(r); } } ccv_icf_classifier_cascade_free(cascade); ccv_disable_cache(); return 0; }
void TDetector::pdetect(ccv_dense_matrix_t* image, std::vector<Text2D>& text2d) { text2d.clear(); //text2d.erase(text2d.begin(), text2d.end()); if (image != 0) { for (int i = 0; i < params.size(); i++) { ccv_array_t* words = ccv_swt_detect_words(image, params.at(i)); if (words) { text2d.reserve(words->rnum); ccv_rect_t* rect; for (int j = 0; j < words->rnum; j++) { rect = (ccv_rect_t*) ccv_array_get(words, j); //printf("%d %d %d %d\n", rect->x, rect->y, rect->width, rect->height); text2d.push_back( Text2D(rect->x, rect->y, rect->x + rect->width, rect->y + rect->height, "")); } ccv_array_free(words); } } ccv_matrix_free(image); } }
int main(int argc, char** argv) { int counter = 0; ccv_dense_matrix_t* image = 0; ccv_enable_default_cache(); ccv_read(argv[1], &image, CCV_IO_GRAY | CCV_IO_ANY_FILE); if (image != 0) { ccv_array_t* words = ccv_swt_detect_words(image, ccv_swt_default_params); if (words) { int i; for (i = 0; i < words->rnum; i++) { char filename[256]; ccv_matrix_t* box = 0; ccv_rect_t* rect = (ccv_rect_t*)ccv_array_get(words, i); ccv_slice(image, &box, 0, rect->y, rect->x, rect->height, rect->width); printf("%d %d %d %d\n", rect->x, rect->y, rect->width, rect->height); snprintf(filename, 256, "out-%d.png", ++counter); ccv_write(box, filename, NULL, CCV_IO_PNG_FILE, NULL); } } ccv_array_free(words); } ccv_drain_cache(); return 0; }
int main(int argc, char** argv) { ccv_dense_matrix_t* image = 0; ccv_read(argv[1], &image, CCV_IO_RGB_COLOR | CCV_IO_ANY_FILE); ccv_scd_classifier_cascade_t* cascade = ccv_scd_classifier_cascade_read(argv[2]); ccv_array_t* faces = ccv_scd_detect_objects(image, &cascade, 1, ccv_scd_default_params); int i; for (i = 0; i < faces->rnum; i++) { ccv_comp_t* face = (ccv_comp_t*)ccv_array_get(faces, i); printf("%d %d %d %d\n", face->rect.x, face->rect.y, face->rect.width, face->rect.height); } ccv_array_free(faces); ccv_scd_classifier_cascade_free(cascade); ccv_matrix_free(image); return 0; }
ccv_nnc_graph_exec_symbol_t ccv_nnc_symbolic_graph_while(ccv_nnc_symbolic_graph_t* const graph, ccv_nnc_symbolic_graph_t* const while_graph, const char* const name) { assert(while_graph->p == 0); assert(while_graph->p_idx == 0); ccv_nnc_cmd_t cmd = ccv_nnc_cmd(CCV_NNC_GRAPH_FORWARD, 0, CMD_GENERIC(), 0); // Added one more symbol. ccv_nnc_graph_exec_symbol_t symbol = ccv_nnc_graph_exec_symbol_new(graph, cmd, 0, 0, 0, 0, name); // Assigning graph_ref to it. if (!graph->sub_graphs) graph->sub_graphs = ccv_array_new(sizeof(ccv_nnc_symbolic_graph_t*), 1, 0); ccv_array_push(graph->sub_graphs, &while_graph); ccv_nnc_graph_exec_symbol_info_t* symbol_info = (ccv_nnc_graph_exec_symbol_info_t*)ccv_array_get(graph->exec_symbol_info, symbol.d); // Note the extra allocation (the ccv_array_t only holds a pointer to ccv_nnc_symbolic_graph_t*). // In this way, we can get the while graph and don't have to worry about it will be an invalid pointer once // the array expands (another while graph allocated). symbol_info->graph_ref = graph->sub_graphs->rnum; while_graph->p_idx = graph->sub_graphs->rnum; while_graph->exec_idx = symbol.d + 1; while_graph->p = graph; return symbol; }
int main(int argc, char** argv) { ccv_nnc_init(); ccv_convnet_t* convnet = ccv_convnet_read(0, argv[2]); ccv_dense_matrix_t* image = 0; ccv_read(argv[1], &image, CCV_IO_ANY_FILE | CCV_IO_RGB_COLOR); if (image != 0) { ccv_dense_matrix_t* input = 0; ccv_convnet_input_formation(convnet->input, image, &input); ccv_matrix_free(image); ccv_dense_matrix_t* sliced = 0; ccv_slice(input, (ccv_matrix_t**)&sliced, 0, (input->rows - 225) / 2, (input->cols - 225) / 2, 225, 225); ccv_matrix_free(input); ccv_dense_matrix_t* b = 0; unsigned int elapsed_time = get_current_time(); ccv_convnet_encode(convnet, &sliced, &b, 1); printf("ccv_convnet_encode %u ms\n", get_current_time() - elapsed_time); ccv_nnc_tensor_t* c = ccv_nnc_tensor_new(0, ONE_CPU_TENSOR(1000), 0); ccv_nnc_graph_exec_t source, dest; ccv_array_t* tensors = ccv_array_new(sizeof(ccv_nnc_tensor_t*), 1, 0); ccv_nnc_graph_t* graph = ccv_nnc_simple_graph(convnet, (ccv_nnc_tensor_t*)sliced, c, &source, &dest, tensors); elapsed_time = get_current_time(); ccv_nnc_graph_run(graph, 0, &source, 1, &dest, 1); printf("ccv_nnc_graph_run %u ms\n", get_current_time() - elapsed_time); int i; for (i = 0; i < 1000; i++) if (fabsf(b->data.f32[i] - c->data.f32[i]) > 1e-4) printf("mis-match at %d: %f %f\n", i, b->data.f32[i], c->data.f32[i]); ccv_nnc_tensor_free(c); ccv_matrix_free(sliced); ccv_matrix_free(b); ccv_nnc_graph_free(graph); for (i = 0; i < tensors->rnum; i++) ccv_nnc_tensor_free(*(ccv_nnc_tensor_t**)ccv_array_get(tensors, i)); ccv_array_free(tensors); } ccv_convnet_free(convnet); return 0; }
void ccv_nnc_symbolic_graph_set_while_params(ccv_nnc_symbolic_graph_t* const while_graph, const ccv_nnc_tensor_symbol_map_t* const symbol_map, const int symbol_map_size) { int i; for (i = 0; i < symbol_map_size; i++) { const ccv_nnc_tensor_symbol_t source = ccv_nnc_find_tensor_symbol_from_graph(while_graph, symbol_map[i].source); const ccv_nnc_tensor_symbol_t destination = ccv_nnc_find_tensor_symbol_from_graph(while_graph, symbol_map[i].destination); assert(source.graph == while_graph); assert(destination.graph == while_graph); assert(source.d < while_graph->tensor_symbol_info->rnum); assert(destination.d < while_graph->tensor_symbol_info->rnum); ccv_nnc_tensor_symbol_info_t* destination_tensor_symbol_info = (ccv_nnc_tensor_symbol_info_t*)ccv_array_get(while_graph->tensor_symbol_info, destination.d); // Don't support parameterize with alias. The reason is that to support parameterized loop (for SSA), I choose // to simply reuse the piece of memory (allocating the same memory region to both, therefore to enable parameter // passing). For alias, it is not possible because alias can pointing to the tensors with different sizes, thus, // these pointed tensors cannot share the same memory region. The best way for alias to be parameterized is to // create a new tensor of the same size, transfer value over, and parameterized on that tensor instead. assert(!destination_tensor_symbol_info->alias_ref); assert(!((ccv_nnc_tensor_symbol_info_t*)ccv_array_get(while_graph->tensor_symbol_info, source.d))->alias_ref); destination_tensor_symbol_info->assign_ref = source.d + 1; } }
int main(int argc, char** argv) { // process arguments char* image_file = ""; int scale_invariant = 0; int min_height = 0; int min_area = 0; char ch; while ((ch = getopt(argc, argv, "a:h:i")) != EOF) switch(ch) { case 'i': scale_invariant = 1; printf("Scale invariant\n"); break; case 'h': min_height = atoi(optarg); printf("Min height %d\n", min_height); continue; case 'a': min_area = atoi(optarg); printf("Min area %d\n", min_area); continue; } argc -= optind; argv += optind; image_file = argv[0]; ccv_enable_default_cache(); ccv_dense_matrix_t* image = 0; ccv_read(image_file, &image, CCV_IO_GRAY | CCV_IO_ANY_FILE); if (image==0) { fprintf(stderr, "ERROR: image could not be read\n"); return 1; } unsigned int elapsed_time = get_current_time(); ccv_swt_param_t params = ccv_swt_default_params; if (scale_invariant) params.scale_invariant = 1; if (min_height) params.min_height = min_height; if (min_area) params.min_area = min_area; ccv_array_t* letters = ccv_swt_detect_chars_contour(image, params); elapsed_time = get_current_time() - elapsed_time; if (letters) { printf("total : %d in time %dms\n", letters->rnum, elapsed_time); int i; for (i = 0; i < letters->rnum; i++) { // for each letter ccv_contour_t* cont = *(ccv_contour_t**)ccv_array_get(letters, i); printf("Contour %d (size=%d):\n", i, cont->size); for (int j = 0; j < cont->size; j++) { // for each point in contour ccv_point_t* point = (ccv_point_t*)ccv_array_get(cont->set, j); printf("%d %d\n", point->x, point->y); } printf("End contour %d\n", i); } ccv_array_free(letters); } ccv_matrix_free(image); ccv_drain_cache(); return 0; }
int main(int argc, char** argv) { static struct option swt_options[] = { /* help */ {"help", 0, 0, 0}, /* optional parameters */ {"size", 1, 0, 0}, {"low-thresh", 1, 0, 0}, {"high-thresh", 1, 0, 0}, {"max-height", 1, 0, 0}, {"min-height", 1, 0, 0}, {"min-area", 1, 0, 0}, {"aspect-ratio", 1, 0, 0}, {"std-ratio", 1, 0, 0}, {"thickness-ratio", 1, 0, 0}, {"height-ratio", 1, 0, 0}, {"intensity-thresh", 1, 0, 0}, {"letter-occlude-thresh", 1, 0, 0}, {"distance-ratio", 1, 0, 0}, {"intersect-ratio", 1, 0, 0}, {"letter-thresh", 1, 0, 0}, {"elongate-ratio", 1, 0, 0}, {"breakdown-ratio", 1, 0, 0}, {"breakdown", 1, 0, 0}, {"iterations", 1, 0, 0}, {"base-dir", 1, 0, 0}, {0, 0, 0, 0} }; if (argc <= 1) exit_with_help(); ccv_swt_param_t params = { .interval = 1, .same_word_thresh = { 0.2, 0.8 }, .min_neighbors = 1, .scale_invariant = 0, .size = 3, .low_thresh = 78, .high_thresh = 214, .max_height = 300, .min_height = 10, .min_area = 75, .letter_occlude_thresh = 2, .aspect_ratio = 10, .std_ratio = 0.5, .thickness_ratio = 1.5, .height_ratio = 2.0, .intensity_thresh = 45, .distance_ratio = 3.0, .intersect_ratio = 2.0, .letter_thresh = 3, .elongate_ratio = 1.3, .breakdown = 1, .breakdown_ratio = 1.0, }; ccv_swt_range_t size_range = { .min_value = 1, .max_value = 3, .step = 2, .enable = 1, }; ccv_swt_range_t low_thresh_range = { .min_value = 50, .max_value = 150, .step = 1, .enable = 1, }; ccv_swt_range_t high_thresh_range = { .min_value = 200, .max_value = 350, .step = 1, .enable = 1, }; ccv_swt_range_t max_height_range = { .min_value = 500, .max_value = 500, .step = 1, .enable = 1, }; ccv_swt_range_t min_height_range = { .min_value = 5, .max_value = 30, .step = 1, .enable = 1, }; ccv_swt_range_t min_area_range = { .min_value = 10, .max_value = 100, .step = 1, .enable = 1, }; ccv_swt_range_t letter_occlude_thresh_range = { .min_value = 0, .max_value = 5, .step = 1, .enable = 1, }; ccv_swt_range_t aspect_ratio_range = { .min_value = 5, .max_value = 15, .step = 1, .enable = 1, }; ccv_swt_range_t std_ratio_range = { .min_value = 0.1, .max_value = 1.0, .step = 0.01, .enable = 1, }; ccv_swt_range_t thickness_ratio_range = { .min_value = 1.0, .max_value = 2.0, .step = 0.1, .enable = 1, }; ccv_swt_range_t height_ratio_range = { .min_value = 1.0, .max_value = 3.0, .step = 0.1, .enable = 1, }; ccv_swt_range_t intensity_thresh_range = { .min_value = 1, .max_value = 50, .step = 1, .enable = 1, }; ccv_swt_range_t distance_ratio_range = { .min_value = 1.0, .max_value = 5.0, .step = 0.1, .enable = 1, }; ccv_swt_range_t intersect_ratio_range = { .min_value = 0.0, .max_value = 5.0, .step = 0.1, .enable = 1, }; ccv_swt_range_t letter_thresh_range = { .min_value = 0, .max_value = 5, .step = 1, .enable = 1, }; ccv_swt_range_t elongate_ratio_range = { .min_value = 0.1, .max_value = 2.5, .step = 0.1, .enable = 1, }; ccv_swt_range_t breakdown_ratio_range = { .min_value = 0.5, .max_value = 1.5, .step = 0.01, .enable = 1, }; int i, j, k, iterations = 10; while (getopt_long_only(argc - 1, argv + 1, "", swt_options, &k) != -1) { switch (k) { case 0: exit_with_help(); case 1: decode_range(optarg, &size_range); break; case 2: decode_range(optarg, &low_thresh_range); break; case 3: decode_range(optarg, &high_thresh_range); break; case 4: decode_range(optarg, &max_height_range); break; case 5: decode_range(optarg, &min_height_range); break; case 6: decode_range(optarg, &min_area_range); break; case 7: decode_range(optarg, &aspect_ratio_range); break; case 8: decode_range(optarg, &std_ratio_range); break; case 9: decode_range(optarg, &thickness_ratio_range); break; case 10: decode_range(optarg, &height_ratio_range); break; case 11: decode_range(optarg, &intensity_thresh_range); break; case 12: decode_range(optarg, &letter_occlude_thresh_range); break; case 13: decode_range(optarg, &distance_ratio_range); break; case 14: decode_range(optarg, &intersect_ratio_range); break; case 15: decode_range(optarg, &letter_thresh_range); break; case 16: decode_range(optarg, &elongate_ratio_range); break; case 17: decode_range(optarg, &breakdown_ratio_range); break; case 18: params.breakdown = !!atoi(optarg); break; case 19: iterations = atoi(optarg); break; case 20: chdir(optarg); break; } } FILE* r = fopen(argv[1], "rt"); if (!r) exit_with_help(); ccv_enable_cache(1024 * 1024 * 1024); ccv_array_t* aof = ccv_array_new(sizeof(char*), 64, 0); ccv_array_t* aow = ccv_array_new(sizeof(ccv_array_t*), 64, 0); ccv_array_t* cw = 0; char* file = (char*)malloc(1024); size_t len = 1024; ssize_t read; while ((read = getline(&file, &len, r)) != -1) { while(read > 1 && isspace(file[read - 1])) read--; file[read] = 0; double x, y, width, height; int recognized = sscanf(file, "%lf %lf %lf %lf", &x, &y, &width, &height); if (recognized == 4) { ccv_rect_t rect = { .x = (int)(x + 0.5), .y = (int)(y + 0.5), .width = (int)(width + 0.5), .height = (int)(height + 0.5) }; ccv_array_push(cw, &rect); } else { char* name = (char*)malloc(ccv_min(1023, strlen(file)) + 1); strncpy(name, file, ccv_min(1023, strlen(file)) + 1); ccv_array_push(aof, &name); cw = ccv_array_new(sizeof(ccv_rect_t), 1, 0); ccv_array_push(aow, &cw); } } free(file); printf("loaded %d images for parameter search of:\n", aof->rnum); if (size_range.enable) printf(" - canny size from %d to %d, += %lg\n", (int)(size_range.min_value + 0.5), (int)(size_range.max_value + 0.5), size_range.step); if (std_ratio_range.enable) printf(" - std threshold ratio from %lg to %lg, += %lg\n", std_ratio_range.min_value, std_ratio_range.max_value, std_ratio_range.step); if (max_height_range.enable) printf(" - maximum height from %d to %d, += %lg\n", (int)(max_height_range.min_value + 0.5), (int)(max_height_range.max_value + 0.5), max_height_range.step); if (min_height_range.enable) printf(" - minimum height from %d to %d, += %lg\n", (int)(min_height_range.min_value + 0.5), (int)(min_height_range.max_value + 0.5), min_height_range.step); if (min_area_range.enable) printf(" - minimum area from %d to %d, += %lg\n", (int)(min_area_range.min_value + 0.5), (int)(min_area_range.max_value + 0.5), min_area_range.step); if (letter_occlude_thresh_range.enable) printf(" - letter occlude threshold from %d to %d, += %lg\n", (int)(letter_occlude_thresh_range.min_value + 0.5), (int)(letter_occlude_thresh_range.max_value + 0.5), letter_occlude_thresh_range.step); if (aspect_ratio_range.enable) printf(" - aspect ratio threshold from %lg to %lg, += %lg\n", aspect_ratio_range.min_value, aspect_ratio_range.max_value, aspect_ratio_range.step); if (thickness_ratio_range.enable) printf(" - thickness ratio threshold from %lg to %lg, += %lg\n", thickness_ratio_range.min_value, thickness_ratio_range.max_value, thickness_ratio_range.step); if (height_ratio_range.enable) printf(" - height ratio threshold from %lg to %lg, += %lg\n", height_ratio_range.min_value, height_ratio_range.max_value, height_ratio_range.step); if (intensity_thresh_range.enable) printf(" - intensity threshold from %d to %d, += %lg\n", (int)(intensity_thresh_range.min_value + 0.5), (int)(intensity_thresh_range.max_value + 0.5), intensity_thresh_range.step); if (distance_ratio_range.enable) printf(" - distance ratio threshold from %lg to %lg, += %lg\n", distance_ratio_range.min_value, distance_ratio_range.max_value, distance_ratio_range.step); if (intersect_ratio_range.enable) printf(" - intersect ratio threshold from %lg to %lg, += %lg\n", intersect_ratio_range.min_value, intersect_ratio_range.max_value, intersect_ratio_range.step); if (letter_thresh_range.enable) printf(" - minimum number of letters from %d to %d, += %lg\n", (int)(letter_thresh_range.min_value + 0.5), (int)(letter_thresh_range.max_value + 0.5), letter_thresh_range.step); if (elongate_ratio_range.enable) printf(" - elongate ratio threshold from %lg to %lg, += %lg\n", elongate_ratio_range.min_value, elongate_ratio_range.max_value, elongate_ratio_range.step); if (breakdown_ratio_range.enable) printf(" - breakdown ratio threshold from %lg to %lg, += %lg\n", breakdown_ratio_range.min_value, breakdown_ratio_range.max_value, breakdown_ratio_range.step); if (low_thresh_range.enable) printf(" - canny low threshold from %d to %d, += %lg\n", (int)(low_thresh_range.min_value + 0.5), (int)(low_thresh_range.max_value + 0.5), low_thresh_range.step); if (high_thresh_range.enable) printf(" - canny high threshold from %d to %d, += %lg\n", (int)(high_thresh_range.min_value + 0.5), (int)(high_thresh_range.max_value + 0.5), high_thresh_range.step); double best_f = 0, best_precision = 0, best_recall = 0; double a = 0.5; double v; ccv_swt_param_t best_params = params; #define optimize(parameter, type, rounding) \ if (parameter##_range.enable) \ { \ params = best_params; \ int total_iterations = 0; \ for (v = parameter##_range.min_value; v <= parameter##_range.max_value; v += parameter##_range.step) \ ++total_iterations; \ double* precision = (double*)ccmalloc(sizeof(double) * total_iterations); \ double* recall = (double*)ccmalloc(sizeof(double) * total_iterations); \ double* total_words = (double*)ccmalloc(sizeof(double) * total_iterations); \ memset(precision, 0, sizeof(double) * total_iterations); \ memset(recall, 0, sizeof(double) * total_iterations); \ memset(total_words, 0, sizeof(double) * total_iterations); \ double total_truth = 0; \ for (j = 0; j < aof->rnum; j++) \ { \ char* name = *(char**)ccv_array_get(aof, j); \ ccv_dense_matrix_t* image = 0; \ ccv_read(name, &image, CCV_IO_GRAY | CCV_IO_ANY_FILE); \ ccv_array_t* truth = *(ccv_array_t**)ccv_array_get(aow, j); \ total_truth += truth->rnum; \ for (v = parameter##_range.min_value, k = 0; v <= parameter##_range.max_value; v += parameter##_range.step, k++) \ { \ params.parameter = (type)(v + rounding); \ ccv_array_t* words = ccv_swt_detect_words(image, params); \ double one_precision = 0, one_recall = 0; \ _ccv_evaluate_wolf(words, truth, params, &one_precision, &one_recall); \ assert(one_precision <= words->rnum + 0.1); \ precision[k] += one_precision; \ recall[k] += one_recall; \ total_words[k] += words->rnum; \ ccv_array_free(words); \ FLUSH("perform SWT on %s (%d / %d) for " #parameter " = (%lg <- [%lg, %lg])", name, j + 1, aof->rnum, v, parameter##_range.min_value, parameter##_range.max_value); \ } \ ccv_matrix_free(image); \ } \ for (v = parameter##_range.min_value, j = 0; v <= parameter##_range.max_value; v += parameter##_range.step, j++) \ { \ params.parameter = (type)(v + rounding); \ double f, total_precision = precision[j], total_recall = recall[j]; \ total_precision /= total_words[j]; \ total_recall /= total_truth; \ f = 1.0 / (a / total_precision + (1.0 - a) / total_recall); \ if (f > best_f) \ { \ best_params = params; \ best_f = f; \ best_precision = total_precision; \ best_recall = total_recall; \ } \ FLUSH("current harmonic mean : %.2lf%%, precision : %.2lf%%, recall : %.2lf%% ; best harmonic mean : %.2lf%%, precision : %.2lf%%, recall : %.2lf%% ; at " #parameter " = %lg (%lg <- [%lg, %lg])", f * 100, total_precision * 100, total_recall * 100, best_f * 100, best_precision * 100, best_recall * 100, (double)best_params.parameter, v, parameter##_range.min_value, parameter##_range.max_value); \ } \ printf("\n"); \ ccfree(precision); \ ccfree(recall); \ ccfree(total_words); \ } for (i = 0; i < iterations; i++) { optimize(size, int, 0.5); optimize(std_ratio, double, 0); optimize(max_height, int, 0.5); optimize(min_height, int, 0.5); optimize(min_area, int, 0.5); optimize(letter_occlude_thresh, int, 0.5); optimize(aspect_ratio, double, 0); optimize(thickness_ratio, double, 0); optimize(height_ratio, double, 0); optimize(intensity_thresh, int, 0.5); optimize(distance_ratio, double, 0); optimize(intersect_ratio, double, 0); optimize(letter_thresh, int, 0.5); optimize(elongate_ratio, double, 0); optimize(breakdown_ratio, double, 0); optimize(low_thresh, int, 0.5); optimize(high_thresh, int, 0.5); printf("At iteration %d(of %d) : best parameters for swt is:\n" "\tsize = %d\n" "\tlow_thresh = %d\n" "\thigh_thresh = %d\n" "\tmax_height = %d\n" "\tmin_height = %d\n" "\tmin_area = %d\n" "\tletter_occlude_thresh = %d\n" "\taspect_ratio = %lf\n" "\tstd_ratio = %lf\n" "\tthickness_ratio = %lf\n" "\theight_ratio = %lf\n" "\tintensity_thresh = %d\n" "\tdistance_ratio = %lf\n" "\tintersect_ratio = %lf\n" "\tletter_thresh = %d\n" "\telongate_ratio = %lf\n" "\tbreakdown_ratio = %lf\n", i + 1, iterations, best_params.size, best_params.low_thresh, best_params.high_thresh, best_params.max_height, best_params.min_height, best_params.min_area, best_params.letter_occlude_thresh, best_params.aspect_ratio, best_params.std_ratio, best_params.thickness_ratio, best_params.height_ratio, best_params.intensity_thresh, best_params.distance_ratio, best_params.intersect_ratio, best_params.letter_thresh, best_params.elongate_ratio, best_params.breakdown_ratio); } #undef optimize for (i = 0; i < aof->rnum; i++) { char* name = *(char**)ccv_array_get(aof, i); free(name); ccv_array_t* cw = *(ccv_array_t**)ccv_array_get(aow, i); ccv_array_free(cw); } ccv_array_free(aof); ccv_array_free(aow); ccv_drain_cache(); return 0; }
static void _ccv_set_union_mser(ccv_dense_matrix_t* a, ccv_dense_matrix_t* h, ccv_dense_matrix_t* b, ccv_array_t* seq, ccv_mser_param_t params) { assert(params.direction == CCV_BRIGHT_TO_DARK || params.direction == CCV_DARK_TO_BRIGHT); int v, i, j; ccv_mser_node_t* node = (ccv_mser_node_t*)ccmalloc(sizeof(ccv_mser_node_t) * a->rows * a->cols); ccv_mser_node_t** rnode = (ccv_mser_node_t**)ccmalloc(sizeof(ccv_mser_node_t*) * a->rows * a->cols); if (params.range <= 0) params.range = 255; // put it in a block so that the memory allocated can be released in the end int* buck = (int*)alloca(sizeof(int) * (params.range + 2)); memset(buck, 0, sizeof(int) * (params.range + 2)); ccv_mser_node_t* pnode = node; // this for_block is the only computation that can be shared between dark to bright and bright to dark // two MSER alternatives, and it only occupies 10% of overall time, we won't share this computation // at all (also, we need to reinitialize node for the two passes anyway). if (h != 0) { unsigned char* aptr = a->data.u8; unsigned char* hptr = h->data.u8; #define for_block(_for_get_a, _for_get_h) \ for (i = 0; i < a->rows; i++) \ { \ for (j = 0; j < a->cols; j++) \ if (!_for_get_h(hptr, j, 0)) \ ++buck[_for_get_a(aptr, j, 0)]; \ aptr += a->step; \ hptr += h->step; \ } \ for (i = 1; i <= params.range; i++) \ buck[i] += buck[i - 1]; \ buck[params.range + 1] = buck[params.range]; \ aptr = a->data.u8; \ hptr = h->data.u8; \ for (i = 0; i < a->rows; i++) \ { \ for (j = 0; j < a->cols; j++) \ { \ _ccv_mser_init_node(pnode, j, i); \ if (!_for_get_h(hptr, j, 0)) \ rnode[--buck[_for_get_a(aptr, j, 0)]] = pnode; \ else \ pnode->shortcut = 0; /* this means the pnode is not available */ \ ++pnode; \ } \ aptr += a->step; \ hptr += h->step; \ } ccv_matrix_getter_integer_only_a(a->type, ccv_matrix_getter_integer_only, h->type, for_block); #undef for_block } else { unsigned char* aptr = a->data.u8; #define for_block(_, _for_get) \ for (i = 0; i < a->rows; i++) \ { \ for (j = 0; j < a->cols; j++) \ ++buck[_for_get(aptr, j, 0)]; \ aptr += a->step; \ } \ for (i = 1; i <= params.range; i++) \ buck[i] += buck[i - 1]; \ buck[params.range + 1] = buck[params.range]; \ aptr = a->data.u8; \ for (i = 0; i < a->rows; i++) \ { \ for (j = 0; j < a->cols; j++) \ { \ _ccv_mser_init_node(pnode, j, i); \ rnode[--buck[_for_get(aptr, j, 0)]] = pnode; \ ++pnode; \ } \ aptr += a->step; \ } ccv_matrix_getter_integer_only(a->type, for_block); #undef for_block } ccv_array_t* history_list = ccv_array_new(sizeof(ccv_mser_history_t), 64, 0); for (v = 0; v <= params.range; v++) { int range_segment = buck[params.direction == CCV_DARK_TO_BRIGHT ? v : params.range - v]; int range_segment_cap = buck[params.direction == CCV_DARK_TO_BRIGHT ? v + 1 : params.range - v + 1]; for (i = range_segment; i < range_segment_cap; i++) { pnode = rnode[i]; // try to merge pnode with its neighbors static int dx[] = {-1, 0, 1, -1, 1, -1, 0, 1}; static int dy[] = {-1, -1, -1, 0, 0, 1, 1, 1}; ccv_mser_node_t* node0 = _ccv_mser_find_root(pnode); for (j = 0; j < 8; j++) { int x = dx[j] + pnode->point.x; int y = dy[j] + pnode->point.y; if (x >= 0 && x < a->cols && y >= 0 && y < a->rows) { ccv_mser_node_t* nnode = pnode + dx[j] + dy[j] * a->cols; if (nnode->shortcut == 0) // this is a void node, skip continue; ccv_mser_node_t* node1 = _ccv_mser_find_root(nnode); if (node0 != node1) { // grep the extended root information ccv_mser_history_t* root0 = (node0->root >= 0) ? (ccv_mser_history_t*)ccv_array_get(history_list, node0->root) : 0; ccv_mser_history_t* root1 = (node1->root >= 0) ? (ccv_mser_history_t*)ccv_array_get(history_list, node1->root) : 0; // swap the node if root1 has higher rank, or larger in size, or root0 is non-existent if ((root0 && root1 && (root1->value > root0->value || (root1->value == root0->value && root1->rank > root0->rank) || (root1->value == root0->value && root1->rank == root0->rank && root1->size > root0->size))) || (root1 && !root0)) { ccv_mser_node_t* exnode = node0; node0 = node1; node1 = exnode; ccv_mser_history_t* root = root0; root0 = root1; root1 = root; } if (!root0) { ccv_mser_history_t root = { .rank = 0, .size = 1, .value = v, .shortcut = history_list->rnum, .parent = history_list->rnum, .head = node0, .tail = node1 }; node0->root = history_list->rnum; ccv_array_push(history_list, &root); root0 = (ccv_mser_history_t*)ccv_array_get(history_list, history_list->rnum - 1); assert(node1->root == -1); } else if (root0->value < v) { // conceal the old root as history (er), making a new one and pointing to it root0->shortcut = root0->parent = history_list->rnum; ccv_mser_history_t root = *root0; root.value = v; node0->root = history_list->rnum; ccv_array_push(history_list, &root); root0 = (ccv_mser_history_t*)ccv_array_get(history_list, history_list->rnum - 1); root1 = (node1->root >= 0) ? (ccv_mser_history_t*)ccv_array_get(history_list, node1->root) : 0; // the memory may be reallocated root0->rank = ccv_max(root0->rank, (root1 ? root1->rank : 0)) + 1; } if (root1) { if (root1->value < root0->value) // in this case, root1 is sealed as well root1->parent = node0->root; // thus, if root1->parent == itself && root1->shortcut != itself // it is voided, and not sealed root1->shortcut = node0->root; } // merge the two node1->shortcut = node0; root0->size += root1 ? root1->size : 1; /* insert one endless double link list to another, see illustration: * 0->1->2->3->4->5->0 * a->b->c->d->a * set 5.next (0.prev.next) point to a * set 0.prev point to d * set d.next (a.prev.next) point to 0 * set a.prev point to 5 * the result endless double link list will be: * 0->1->2->3->4->5->a->b->c->d->0 */ node0->prev->next = node1; ccv_mser_node_t* prev = node0->prev; node0->prev = node1->prev; node1->prev->next = node0; // consider self-referencing node1->prev = prev; root0->head = node0; root0->tail = node0->prev; } } }
int main(int argc, char** argv) { FILE* file; char *output_file = "my_output.txt"; int i, ret_val; ccv_dense_matrix_t* image = 0; ccv_array_t* seq; accept_roi_begin(); assert(argc >= 3); ccv_enable_default_cache(); ccv_bbf_classifier_cascade_t* cascade = ccv_bbf_read_classifier_cascade(argv[2]); ccv_read(argv[1], &image, CCV_IO_GRAY | CCV_IO_ANY_FILE); if (image != 0) { unsigned int elapsed_time = get_current_time(); seq = ccv_bbf_detect_objects(image, &cascade, 1, ccv_bbf_default_params); elapsed_time = get_current_time() - elapsed_time; for (i = 0; ENDORSE(i < seq->rnum); i++) { ccv_comp_t* comp = (ccv_comp_t*)ENDORSE(ccv_array_get(seq, i)); printf("%d %d %d %d %f\n", comp->rect.x, comp->rect.y, comp->rect.width, comp->rect.height, comp->classification.confidence); } printf("total : %d in time %dms\n", seq->rnum, elapsed_time); ccv_bbf_classifier_cascade_free(cascade); ccv_disable_cache(); accept_roi_end(); file = fopen(output_file, "w"); if (file == NULL) { perror("fopen for write failed"); return EXIT_FAILURE; } // latest changes struct coordinates { APPROX int x; APPROX int y; }; for (i = 0; ENDORSE(i < seq->rnum); i++) { ccv_comp_t* comp = (ccv_comp_t*) ENDORSE(ccv_array_get(seq, i)); struct coordinates upperleft, upperright, lowerleft, lowerright; upperleft.x = comp->rect.x; upperleft.y = comp->rect.y; upperright.x = comp->rect.x + comp->rect.width; upperright.y = upperleft.y; lowerleft.x = upperleft.x; lowerleft.y = upperleft.y + comp->rect.height; lowerright.x = upperright.x; lowerright.y = lowerleft.y; ret_val = fprintf(file, "%d %d\n%d %d\n%d %d\n%d %d\n", upperleft.x, upperleft.y, upperright.x, upperright.y, lowerright.x, lowerright.y, lowerleft.x, lowerleft.y); // latest changes if (ret_val < 0) { perror("fprintf of coordinates failed"); fclose(file); return EXIT_FAILURE; } } ret_val = fclose(file); if (ret_val != 0) { perror("fclose failed"); return EXIT_FAILURE; } ccv_array_free(seq); ccv_matrix_free(image); } else { FILE* r = fopen(argv[1], "rt"); if (argc == 4) chdir(argv[3]); if(r) { size_t len = 1024; char* file = (char*)malloc(len); ssize_t read; while((read = getline(&file, &len, r)) != -1) { while(read > 1 && isspace(file[read - 1])) read--; file[read] = 0; image = 0; ccv_read(file, &image, CCV_IO_GRAY | CCV_IO_ANY_FILE); assert(image != 0); seq = ccv_bbf_detect_objects(image, &cascade, 1, ccv_bbf_default_params); // seq already declared above for (i = 0; ENDORSE(i < seq->rnum); i++) { ccv_comp_t* comp = (ccv_comp_t*) ENDORSE(ccv_array_get(seq, i)); printf("%s %d %d %d %d %f\n", file, comp->rect.x, comp->rect.y, comp->rect.width, comp->rect.height, comp->classification.confidence); } } free(file); fclose(r); } ccv_bbf_classifier_cascade_free(cascade); ccv_disable_cache(); accept_roi_end(); file = fopen(output_file, "w"); if (file == NULL) { perror("fopen for write failed"); return EXIT_FAILURE; } for (i = 0; ENDORSE(i < seq->rnum); i++) { ccv_comp_t* comp = (ccv_comp_t*) ENDORSE(ccv_array_get(seq, i)); ret_val = fprintf(file, "%d\n%d\n%d\n%d\n%f\n", comp->rect.x, comp->rect.y, comp->rect.width, comp->rect.height, comp->classification.confidence); if (ret_val < 0) { perror("fprintf of coordinates and confidence failed"); fclose(file); return EXIT_FAILURE; } } ret_val = fclose(file); if (ret_val != 0) { perror("fclose failed"); return EXIT_FAILURE; } ccv_array_free(seq); ccv_matrix_free(image); } return 0; }
int uri_dpm_detect_objects(const void* context, const void* parsed, ebb_buf* buf) { if (!parsed) return -1; dpm_param_parser_t* parser = (dpm_param_parser_t*)parsed; param_parser_terminate(&parser->param_parser); if (parser->source.data == 0) { free(parser); return -1; } if (parser->mixture_model == 0) { free(parser->source.data); free(parser); return -1; } ccv_dense_matrix_t* image = 0; ccv_read(parser->source.data, &image, CCV_IO_ANY_STREAM | CCV_IO_GRAY, parser->source.written); free(parser->source.data); if (image == 0) { free(parser); return -1; } ccv_array_t* seq = ccv_dpm_detect_objects(image, &parser->mixture_model, 1, parser->params); ccv_matrix_free(image); if (seq == 0) { free(parser); return -1; } if (seq->rnum > 0) { int i, j; buf->len = 192 + seq->rnum * 131 + 2; char* data = (char*)malloc(buf->len); data[0] = '['; buf->written = 1; for (i = 0; i < seq->rnum; i++) { char cell[128]; ccv_root_comp_t* comp = (ccv_root_comp_t*)ccv_array_get(seq, i); snprintf(cell, 128, "{\"x\":%d,\"y\":%d,\"width\":%d,\"height\":%d,\"confidence\":%f,\"parts\":[", comp->rect.x, comp->rect.y, comp->rect.width, comp->rect.height, comp->confidence); size_t len = strnlen(cell, 128); while (buf->written + len >= buf->len) { buf->len = (buf->len * 3 + 1) / 2; data = (char*)realloc(data, buf->len); } memcpy(data + buf->written, cell, len); buf->written += len; for (j = 0; j < comp->pnum; j++) { snprintf(cell, 128, "{\"x\":%d,\"y\":%d,\"width\":%d,\"height\":%d,\"confidence\":%f}", comp->part[j].rect.x, comp->part[j].rect.y, comp->part[j].rect.width, comp->part[j].rect.height, comp->part[j].confidence); len = strnlen(cell, 128); while (buf->written + len + 3 >= buf->len) { buf->len = (buf->len * 3 + 1) / 2; data = (char*)realloc(data, buf->len); } memcpy(data + buf->written, cell, len); buf->written += len + 1; data[buf->written - 1] = (j == comp->pnum - 1) ? ']' : ','; } buf->written += 2; data[buf->written - 2] = '}'; data[buf->written - 1] = (i == seq->rnum - 1) ? ']' : ','; } char http_header[192]; snprintf(http_header, 192, ebb_http_header, buf->written); size_t len = strnlen(http_header, 192); if (buf->written + len + 1 >= buf->len) { buf->len = buf->written + len + 1; data = (char*)realloc(data, buf->len); } memmove(data + len, data, buf->written); memcpy(data, http_header, len); buf->written += len + 1; data[buf->written - 1] = '\n'; buf->data = data; buf->len = buf->written; buf->on_release = uri_ebb_buf_free; } else { buf->data = (void*)ebb_http_empty_array; buf->len = sizeof(ebb_http_empty_array); buf->on_release = 0; } ccv_array_free(seq); free(parser); return 0; }
ccv_nnc_tensor_symbol_t ccv_nnc_find_tensor_symbol_from_graph(const ccv_nnc_symbolic_graph_t* const graph, const ccv_nnc_tensor_symbol_t symbol) { if (symbol.graph == graph) return symbol; const ccv_nnc_symbolic_graph_t* curr_graph = symbol.graph; ccv_nnc_tensor_symbol_info_t* const symbol_info = (ccv_nnc_tensor_symbol_info_t*)ccv_array_get(symbol.graph->tensor_symbol_info, symbol.d); assert(symbol.d >= 0 && symbol.d < curr_graph->tensor_symbol_info->rnum); while (curr_graph && curr_graph != graph) curr_graph = curr_graph->p; if (curr_graph) { curr_graph = symbol.graph; ccv_nnc_tensor_symbol_info_t* curr_symbol_info = symbol_info; ccv_nnc_tensor_symbol_t curr_symbol = symbol; while (curr_graph != graph) { ccv_nnc_symbolic_graph_t* const p = curr_graph->p; // I need to find the symbol, it must exist. assert(curr_symbol_info->p_ref); // Move on. curr_symbol.d = curr_symbol_info->p_ref - 1; curr_symbol.graph = p; assert(curr_symbol.d >= 0 && curr_symbol.d < p->tensor_symbol_info->rnum); curr_symbol_info = (ccv_nnc_tensor_symbol_info_t*)ccv_array_get(p->tensor_symbol_info, curr_symbol.d); curr_graph = p; } return curr_symbol; } // Otherwise, if the symbol is in the parent graph, this is a bit more expensive because I need to keep a trace stack. curr_graph = graph; ccv_array_t* trace = ccv_array_new(sizeof(int), 0, 0); while (curr_graph && curr_graph != symbol.graph) { const int p_idx = curr_graph->p_idx - 1; ccv_array_push(trace, &p_idx); curr_graph = curr_graph->p; } // If it is not in both the parent graph and the sub-graph, the input is invalid. assert(curr_graph); curr_graph = symbol.graph; ccv_nnc_tensor_symbol_info_t* curr_symbol_info = symbol_info; ccv_nnc_tensor_symbol_t curr_symbol = symbol; // The graph is a sub graph of the symbol passed in. int i; for (i = trace->rnum - 1; i >= 0; i--) { const int p_idx = *(int*)ccv_array_get(trace, i); assert(p_idx >= 0); assert(curr_graph->sub_graphs); assert(curr_symbol_info->s_ref); assert(p_idx >= 0 && p_idx < curr_symbol_info->s_ref->rnum); const int s_idx = *(int*)ccv_array_get(curr_symbol_info->s_ref, p_idx); ccv_nnc_symbolic_graph_t* const s = *(ccv_nnc_symbolic_graph_t**)ccv_array_get(curr_graph->sub_graphs, p_idx); // I need to find the symbol, it must exist. assert(s_idx); curr_symbol.d = s_idx - 1; curr_symbol.graph = s; assert(curr_symbol.d >= 0 && curr_symbol.d < s->tensor_symbol_info->rnum); curr_symbol_info = (ccv_nnc_tensor_symbol_info_t*)ccv_array_get(s->tensor_symbol_info, curr_symbol.d); // Move on. curr_graph = s; } ccv_array_free(trace); return curr_symbol; }
int main(int argc, char** argv) { static struct option icf_options[] = { /* help */ {"help", 0, 0, 0}, /* required parameters */ {"positive-list", 1, 0, 0}, {"background-list", 1, 0, 0}, {"validate-list", 1, 0, 0}, {"working-dir", 1, 0, 0}, {"negative-count", 1, 0, 0}, {"positive-count", 1, 0, 0}, {"acceptance", 1, 0, 0}, {"size", 1, 0, 0}, {"feature-size", 1, 0, 0}, {"weak-classifier-count", 1, 0, 0}, /* optional parameters */ {"base-dir", 1, 0, 0}, {"grayscale", 1, 0, 0}, {"margin", 1, 0, 0}, {"deform-shift", 1, 0, 0}, {"deform-angle", 1, 0, 0}, {"deform-scale", 1, 0, 0}, {"min-dimension", 1, 0, 0}, {"bootstrap", 1, 0, 0}, {0, 0, 0, 0} }; char* positive_list = 0; char* background_list = 0; char* validate_list = 0; char* working_dir = 0; char* base_dir = 0; int negative_count = 0; int positive_count = 0; ccv_icf_new_param_t params = { .grayscale = 0, .margin = ccv_margin(0, 0, 0, 0), .size = ccv_size(0, 0), .deform_shift = 1, .deform_angle = 0, .deform_scale = 0.075, .feature_size = 0, .weak_classifier = 0, .min_dimension = 2, .bootstrap = 3, .detector = ccv_icf_default_params, }; params.detector.step_through = 4; // for faster negatives bootstrap time int i, k; char* token; char* saveptr; while (getopt_long_only(argc, argv, "", icf_options, &k) != -1) { switch (k) { case 0: exit_with_help(); case 1: positive_list = optarg; break; case 2: background_list = optarg; break; case 3: validate_list = optarg; break; case 4: working_dir = optarg; break; case 5: negative_count = atoi(optarg); break; case 6: positive_count = atoi(optarg); break; case 7: params.acceptance = atof(optarg); break; case 8: token = strtok_r(optarg, "x", &saveptr); params.size.width = atoi(token); token = strtok_r(0, "x", &saveptr); params.size.height = atoi(token); break; case 9: params.feature_size = atoi(optarg); break; case 10: params.weak_classifier = atoi(optarg); break; case 11: base_dir = optarg; break; case 12: params.grayscale = !!atoi(optarg); break; case 13: token = strtok_r(optarg, ",", &saveptr); params.margin.left = atoi(token); token = strtok_r(0, ",", &saveptr); params.margin.top = atoi(token); token = strtok_r(0, ",", &saveptr); params.margin.right = atoi(token); token = strtok_r(0, ",", &saveptr); params.margin.bottom = atoi(token); break; case 14: params.deform_shift = atof(optarg); break; case 15: params.deform_angle = atof(optarg); break; case 16: params.deform_scale = atof(optarg); break; case 17: params.min_dimension = atoi(optarg); break; case 18: params.bootstrap = atoi(optarg); break; } } assert(positive_list != 0); assert(background_list != 0); assert(validate_list != 0); assert(working_dir != 0); assert(positive_count > 0); assert(negative_count > 0); assert(params.size.width > 0); assert(params.size.height > 0); ccv_enable_cache(512 * 1024 * 1024); FILE* r0 = fopen(positive_list, "r"); assert(r0 && "positive-list doesn't exists"); FILE* r1 = fopen(background_list, "r"); assert(r1 && "background-list doesn't exists"); FILE* r2 = fopen(validate_list, "r"); assert(r2 && "validate-list doesn't exists"); char* file = (char*)malloc(1024); ccv_decimal_pose_t pose; int dirlen = (base_dir != 0) ? strlen(base_dir) + 1 : 0; ccv_array_t* posfiles = ccv_array_new(sizeof(ccv_file_info_t), 32, 0); // roll pitch yaw while (fscanf(r0, "%s %f %f %f %f %f %f %f", file, &pose.x, &pose.y, &pose.a, &pose.b, &pose.roll, &pose.pitch, &pose.yaw) != EOF) { ccv_file_info_t file_info; file_info.filename = (char*)ccmalloc(1024); if (base_dir != 0) { strncpy(file_info.filename, base_dir, 1024); file_info.filename[dirlen - 1] = '/'; } strncpy(file_info.filename + dirlen, file, 1024 - dirlen); file_info.pose = pose; ccv_array_push(posfiles, &file_info); } fclose(r0); size_t len = 1024; ssize_t read; ccv_array_t* bgfiles = (ccv_array_t*)ccv_array_new(sizeof(ccv_file_info_t), 32, 0); while ((read = getline(&file, &len, r1)) != -1) { while(read > 1 && isspace(file[read - 1])) read--; file[read] = 0; ccv_file_info_t file_info; file_info.filename = (char*)ccmalloc(1024); if (base_dir != 0) { strncpy(file_info.filename, base_dir, 1024); file_info.filename[dirlen - 1] = '/'; } strncpy(file_info.filename + dirlen, file, 1024 - dirlen); ccv_array_push(bgfiles, &file_info); } fclose(r1); ccv_array_t* validatefiles = ccv_array_new(sizeof(ccv_file_info_t), 32, 0); // roll pitch yaw while (fscanf(r2, "%s %f %f %f %f %f %f %f", file, &pose.x, &pose.y, &pose.a, &pose.b, &pose.roll, &pose.pitch, &pose.yaw) != EOF) { ccv_file_info_t file_info; file_info.filename = (char*)ccmalloc(1024); if (base_dir != 0) { strncpy(file_info.filename, base_dir, 1024); file_info.filename[dirlen - 1] = '/'; } strncpy(file_info.filename + dirlen, file, 1024 - dirlen); file_info.pose = pose; ccv_array_push(validatefiles, &file_info); } fclose(r2); free(file); ccv_icf_classifier_cascade_t* classifier = ccv_icf_classifier_cascade_new(posfiles, positive_count, bgfiles, negative_count, validatefiles, working_dir, params); char filename[1024]; snprintf(filename, 1024, "%s/final-cascade", working_dir); ccv_icf_write_classifier_cascade(classifier, filename); for (i = 0; i < posfiles->rnum; i++) { ccv_file_info_t* file_info = (ccv_file_info_t*)ccv_array_get(posfiles, i); free(file_info->filename); } ccv_array_free(posfiles); for (i = 0; i < bgfiles->rnum; i++) { ccv_file_info_t* file_info = (ccv_file_info_t*)ccv_array_get(bgfiles, i); free(file_info->filename); } ccv_array_free(bgfiles); for (i = 0; i < validatefiles->rnum; i++) { ccv_file_info_t* file_info = (ccv_file_info_t*)ccv_array_get(validatefiles, i); free(file_info->filename); } ccv_array_free(validatefiles); ccv_disable_cache(); return 0; }
// compute harmonic mean of precision / recall of swt static void _ccv_evaluate_wolf(ccv_array_t* words, ccv_array_t* truth, ccv_swt_param_t params, double* precision, double* recall) { if (words->rnum == 0 || truth->rnum == 0) return; int j, k; double total_recall = 0, total_precision = 0; int* cG = (int*)ccmalloc(sizeof(int) * truth->rnum); int* cD = (int*)ccmalloc(sizeof(int) * words->rnum); memset(cG, 0, sizeof(int) * truth->rnum); memset(cD, 0, sizeof(int) * words->rnum); double* mG = (double*)ccmalloc(sizeof(double) * truth->rnum * words->rnum); double* mD = (double*)ccmalloc(sizeof(double) * truth->rnum * words->rnum); memset(mG, 0, sizeof(double) * truth->rnum * words->rnum); memset(mD, 0, sizeof(double) * truth->rnum * words->rnum); for (j = 0; j < truth->rnum; j++) { ccv_rect_t* rect = (ccv_rect_t*)ccv_array_get(truth, j); for (k = 0; k < words->rnum; k++) { ccv_rect_t* target = (ccv_rect_t*)ccv_array_get(words, k); int match = ccv_max(ccv_min(target->x + target->width, rect->x + rect->width) - ccv_max(target->x, rect->x), 0) * ccv_max(ccv_min(target->y + target->height, rect->y + rect->height) - ccv_max(target->y, rect->y), 0); if (match > 0) { mG[j * words->rnum + k] = (double)match / (double)(rect->width * rect->height); mD[k * truth->rnum + j] = (double)match / (double)(target->width * target->height); ++cG[j]; ++cD[k]; } } } unsigned char* tG = (unsigned char*)ccmalloc(truth->rnum); unsigned char* tD = (unsigned char*)ccmalloc(words->rnum); memset(tG, 0, truth->rnum); memset(tD, 0, words->rnum); // one to one match for (j = 0; j < truth->rnum; j++) { if (cG[j] != 1) continue; ccv_rect_t* rect = (ccv_rect_t*)ccv_array_get(truth, j); for (k = 0; k < words->rnum; k++) { if (cD[k] != 1) continue; ccv_rect_t* target = (ccv_rect_t*)ccv_array_get(words, k); if (mG[j * words->rnum + k] >= one_g && mD[k * truth->rnum + j] >= one_d) { double dx = (target->x + target->width * 0.5) - (rect->x + rect->width * 0.5); double dy = (target->y + target->height * 0.5) - (rect->y + rect->height * 0.5); double d = sqrt(dx * dx + dy * dy) * 2.0 / (sqrt(target->width * target->width + target->height * target->height) + sqrt(rect->width * rect->width + rect->height * rect->height)); if (d < center_diff_thr) { total_recall += 1.0; total_precision += 1.0; assert(tG[j] == 0); assert(tD[k] == 0); tG[j] = tD[k] = 1; } } } } int* many = (int*)ccmalloc(sizeof(int) * ccv_max(words->rnum, truth->rnum)); // one to many match, starts with ground truth for (j = 0; j < truth->rnum; j++) { if (tG[j] || cG[j] <= 1) continue; double one_sum = 0; int no_many = 0; for (k = 0; k < words->rnum; k++) { if (tD[k]) continue; double many_single = mD[k * truth->rnum + j]; if (many_single >= one_d) { one_sum += mG[j * words->rnum + k]; many[no_many] = k; ++no_many; } } if (no_many == 1) { // degrade to one to one match if (mG[j * words->rnum + many[0]] >= one_g && mD[many[0] * truth->rnum + j] >= one_d) { total_recall += 1.0; total_precision += 1.0; tG[j] = tD[many[0]] = 1; } } else if (one_sum >= one_g) { for (k = 0; k < no_many; k++) tD[many[k]] = 1; total_recall += om_one; total_precision += om_one / (1 + log(no_many)); } } // one to many match, with estimate for (k = 0; k < words->rnum; k++) { if (tD[k] || cD[k] <= 1) continue; double one_sum = 0; int no_many = 0; for (j = 0; j < truth->rnum; j++) { if (tG[j]) continue; double many_single = mG[j * words->rnum + k]; if (many_single >= one_g) { one_sum += mD[k * truth->rnum + j]; many[no_many] = j; ++no_many; } } if (no_many == 1) { // degrade to one to one match if (mG[many[0] * words->rnum + k] >= one_g && mD[k * truth->rnum + many[0]] >= one_d) { total_recall += 1.0; total_precision += 1.0; tG[many[0]] = tD[k] = 1; } } else if (one_sum >= one_g) { for (j = 0; j < no_many; j++) tG[many[j]] = 1; total_recall += om_one / (1 + log(no_many)); total_precision += om_one; } } ccfree(many); ccfree(tG); ccfree(tD); ccfree(cG); ccfree(cD); ccfree(mG); ccfree(mD); assert(total_precision < words->rnum + 0.1); assert(total_recall < truth->rnum + 0.1); if (precision) *precision = total_precision; if (recall) *recall = total_recall; }
/* this code is a rewrite from OpenCV's legendary Lucas-Kanade optical flow implementation */ void ccv_optical_flow_lucas_kanade(ccv_dense_matrix_t* a, ccv_dense_matrix_t* b, ccv_array_t* point_a, ccv_array_t** point_b, ccv_size_t win_size, int level, double min_eigen) { assert(a && b && a->rows == b->rows && a->cols == b->cols); assert(CCV_GET_CHANNEL(a->type) == CCV_GET_CHANNEL(b->type) && CCV_GET_DATA_TYPE(a->type) == CCV_GET_DATA_TYPE(b->type)); assert(CCV_GET_CHANNEL(a->type) == 1); assert(CCV_GET_DATA_TYPE(a->type) == CCV_8U); assert(point_a->rnum > 0); level = ccv_clamp(level + 1, 1, (int)(log((double)ccv_min(a->rows, a->cols) / ccv_max(win_size.width * 2, win_size.height * 2)) / log(2.0) + 0.5)); ccv_declare_derived_signature(sig, a->sig != 0 && b->sig != 0 && point_a->sig != 0, ccv_sign_with_format(128, "ccv_optical_flow_lucas_kanade(%d,%d,%d,%la)", win_size.width, win_size.height, level, min_eigen), a->sig, b->sig, point_a->sig, CCV_EOF_SIGN); ccv_array_t* seq = *point_b = ccv_array_new(sizeof(ccv_decimal_point_with_status_t), point_a->rnum, sig); ccv_object_return_if_cached(, seq); seq->rnum = point_a->rnum; ccv_dense_matrix_t** pyr_a = (ccv_dense_matrix_t**)malloc(sizeof(ccv_dense_matrix_t*) * level); ccv_dense_matrix_t** pyr_a_dx = (ccv_dense_matrix_t**)malloc(sizeof(ccv_dense_matrix_t*) * level); ccv_dense_matrix_t** pyr_a_dy = (ccv_dense_matrix_t**)malloc(sizeof(ccv_dense_matrix_t*) * level); ccv_dense_matrix_t** pyr_b = (ccv_dense_matrix_t**)malloc(sizeof(ccv_dense_matrix_t*) * level); int i, j, t, x, y; /* generating image pyramid */ pyr_a[0] = a; pyr_a_dx[0] = pyr_a_dy[0] = 0; ccv_sobel(pyr_a[0], &pyr_a_dx[0], 0, 3, 0); ccv_sobel(pyr_a[0], &pyr_a_dy[0], 0, 0, 3); pyr_b[0] = b; for (i = 1; i < level; i++) { pyr_a[i] = pyr_a_dx[i] = pyr_a_dy[i] = pyr_b[i] = 0; ccv_sample_down(pyr_a[i - 1], &pyr_a[i], 0, 0, 0); ccv_sobel(pyr_a[i], &pyr_a_dx[i], 0, 3, 0); ccv_sobel(pyr_a[i], &pyr_a_dy[i], 0, 0, 3); ccv_sample_down(pyr_b[i - 1], &pyr_b[i], 0, 0, 0); } int* wi = (int*)malloc(sizeof(int) * win_size.width * win_size.height); int* widx = (int*)malloc(sizeof(int) * win_size.width * win_size.height); int* widy = (int*)malloc(sizeof(int) * win_size.width * win_size.height); ccv_decimal_point_t half_win = ccv_decimal_point((win_size.width - 1) * 0.5f, (win_size.height - 1) * 0.5f); const int W_BITS14 = 14, W_BITS7 = 7, W_BITS9 = 9; const float FLT_SCALE = 1.0f / (1 << 25); // clean up status to 1 for (i = 0; i < point_a->rnum; i++) { ccv_decimal_point_with_status_t* point_with_status = (ccv_decimal_point_with_status_t*)ccv_array_get(seq, i); point_with_status->status = 1; } int prev_rows, prev_cols; for (t = level - 1; t >= 0; t--) { ccv_dense_matrix_t* a = pyr_a[t]; ccv_dense_matrix_t* adx = pyr_a_dx[t]; ccv_dense_matrix_t* ady = pyr_a_dy[t]; assert(CCV_GET_DATA_TYPE(adx->type) == CCV_32S); assert(CCV_GET_DATA_TYPE(ady->type) == CCV_32S); ccv_dense_matrix_t* b = pyr_b[t]; for (i = 0; i < point_a->rnum; i++) { ccv_decimal_point_t prev_point = *(ccv_decimal_point_t*)ccv_array_get(point_a, i); ccv_decimal_point_with_status_t* point_with_status = (ccv_decimal_point_with_status_t*)ccv_array_get(seq, i); prev_point.x = prev_point.x / (float)(1 << t); prev_point.y = prev_point.y / (float)(1 << t); ccv_decimal_point_t next_point; if (t == level - 1) next_point = prev_point; else { next_point.x = point_with_status->point.x * 2 + (a->cols - prev_cols * 2) * 0.5; next_point.y = point_with_status->point.y * 2 + (a->rows - prev_rows * 2) * 0.5; } point_with_status->point = next_point; prev_point.x -= half_win.x; prev_point.y -= half_win.y; ccv_point_t iprev_point = ccv_point((int)prev_point.x, (int)prev_point.y); if (iprev_point.x < 0 || iprev_point.x >= a->cols - win_size.width - 1 || iprev_point.y < 0 || iprev_point.y >= a->rows - win_size.height - 1) { if (t == 0) point_with_status->status = 0; continue; } float xd = prev_point.x - iprev_point.x; float yd = prev_point.y - iprev_point.y; int iw00 = (int)((1 - xd) * (1 - yd) * (1 << W_BITS14) + 0.5); int iw01 = (int)(xd * (1 - yd) * (1 << W_BITS14) + 0.5); int iw10 = (int)((1 - xd) * yd * (1 << W_BITS14) + 0.5); int iw11 = (1 << W_BITS14) - iw00 - iw01 - iw10; float a11 = 0, a12 = 0, a22 = 0; unsigned char* a_ptr = (unsigned char*)ccv_get_dense_matrix_cell_by(CCV_C1 | CCV_8U, a, iprev_point.y, iprev_point.x, 0); int* adx_ptr = (int*)ccv_get_dense_matrix_cell_by(CCV_C1 | CCV_32S, adx, iprev_point.y, iprev_point.x, 0); int* ady_ptr = (int*)ccv_get_dense_matrix_cell_by(CCV_C1 | CCV_32S, ady, iprev_point.y, iprev_point.x, 0); int* wi_ptr = wi; int* widx_ptr = widx; int* widy_ptr = widy; for (y = 0; y < win_size.height; y++) { for (x = 0; x < win_size.width; x++) { wi_ptr[x] = ccv_descale(a_ptr[x] * iw00 + a_ptr[x + 1] * iw01 + a_ptr[x + a->step] * iw10 + a_ptr[x + a->step + 1] * iw11, W_BITS7); // because we use 3x3 sobel, which scaled derivative up by 4 widx_ptr[x] = ccv_descale(adx_ptr[x] * iw00 + adx_ptr[x + 1] * iw01 + adx_ptr[x + adx->cols] * iw10 + adx_ptr[x + adx->cols + 1] * iw11, W_BITS9); widy_ptr[x] = ccv_descale(ady_ptr[x] * iw00 + ady_ptr[x + 1] * iw01 + ady_ptr[x + ady->cols] + iw10 + ady_ptr[x + ady->cols + 1] * iw11, W_BITS9); a11 += (float)(widx_ptr[x] * widx_ptr[x]); a12 += (float)(widx_ptr[x] * widy_ptr[x]); a22 += (float)(widy_ptr[x] * widy_ptr[x]); } a_ptr += a->step; adx_ptr += adx->cols; ady_ptr += ady->cols; wi_ptr += win_size.width; widx_ptr += win_size.width; widy_ptr += win_size.width; } a11 *= FLT_SCALE; a12 *= FLT_SCALE; a22 *= FLT_SCALE; float D = a11 * a22 - a12 * a12; float eigen = (a22 + a11 - sqrtf((a11 - a22) * (a11 - a22) + 4.0f * a12 * a12)) / (2 * win_size.width * win_size.height); if (eigen < min_eigen || D < FLT_EPSILON) { if (t == 0) point_with_status->status = 0; continue; } D = 1.0f / D; next_point.x -= half_win.x; next_point.y -= half_win.y; ccv_decimal_point_t prev_delta; for (j = 0; j < LK_MAX_ITER; j++) { ccv_point_t inext_point = ccv_point((int)next_point.x, (int)next_point.y); if (inext_point.x < 0 || inext_point.x >= a->cols - win_size.width - 1 || inext_point.y < 0 || inext_point.y >= a->rows - win_size.height - 1) break; float xd = next_point.x - inext_point.x; float yd = next_point.y - inext_point.y; int iw00 = (int)((1 - xd) * (1 - yd) * (1 << W_BITS14) + 0.5); int iw01 = (int)(xd * (1 - yd) * (1 << W_BITS14) + 0.5); int iw10 = (int)((1 - xd) * yd * (1 << W_BITS14) + 0.5); int iw11 = (1 << W_BITS14) - iw00 - iw01 - iw10; float b1 = 0, b2 = 0; unsigned char* b_ptr = (unsigned char*)ccv_get_dense_matrix_cell_by(CCV_C1 | CCV_8U, b, inext_point.y, inext_point.x, 0); int* wi_ptr = wi; int* widx_ptr = widx; int* widy_ptr = widy; for (y = 0; y < win_size.height; y++) { for (x = 0; x < win_size.width; x++) { int diff = ccv_descale(b_ptr[x] * iw00 + b_ptr[x + 1] * iw01 + b_ptr[x + b->step] * iw10 + b_ptr[x + b->step + 1] * iw11, W_BITS7) - wi_ptr[x]; b1 += (float)(diff * widx_ptr[x]); b2 += (float)(diff * widy_ptr[x]); } b_ptr += b->step; wi_ptr += win_size.width; widx_ptr += win_size.width; widy_ptr += win_size.width; } b1 *= FLT_SCALE; b2 *= FLT_SCALE; ccv_decimal_point_t delta = ccv_decimal_point((a12 * b2 - a22 * b1) * D, (a12 * b1 - a11 * b2) * D); next_point.x += delta.x; next_point.y += delta.y; if (delta.x * delta.x + delta.y * delta.y < LK_EPSILON) break; if (j > 0 && fabs(prev_delta.x - delta.x) < 0.01 && fabs(prev_delta.y - delta.y) < 0.01) { next_point.x -= delta.x * 0.5; next_point.y -= delta.y * 0.5; break; } prev_delta = delta; } ccv_point_t inext_point = ccv_point((int)next_point.x, (int)next_point.y); if (inext_point.x < 0 || inext_point.x >= a->cols - win_size.width - 1 || inext_point.y < 0 || inext_point.y >= a->rows - win_size.height - 1) point_with_status->status = 0; else { point_with_status->point.x = next_point.x + half_win.x; point_with_status->point.y = next_point.y + half_win.y; } } prev_rows = a->rows; prev_cols = a->cols; ccv_matrix_free(adx); ccv_matrix_free(ady); if (t > 0) { ccv_matrix_free(a); ccv_matrix_free(b); } } free(widy); free(widx); free(wi); free(pyr_b); free(pyr_a_dy); free(pyr_a_dx); free(pyr_a); }
int main(int argc, char** argv) { assert(argc == 3); ccv_enable_default_cache(); ccv_dense_matrix_t* object = 0; ccv_dense_matrix_t* image = 0; ccv_read(argv[1], &object, CCV_IO_GRAY | CCV_IO_ANY_FILE); ccv_read(argv[2], &image, CCV_IO_GRAY | CCV_IO_ANY_FILE); unsigned int elapsed_time = get_current_time(); ccv_sift_param_t params = { .noctaves = 3, .nlevels = 6, .up2x = 1, .edge_threshold = 10, .norm_threshold = 0, .peak_threshold = 0, }; ccv_array_t* obj_keypoints = 0; ccv_dense_matrix_t* obj_desc = 0; ccv_sift(object, &obj_keypoints, &obj_desc, 0, params); ccv_array_t* image_keypoints = 0; ccv_dense_matrix_t* image_desc = 0; ccv_sift(image, &image_keypoints, &image_desc, 0, params); elapsed_time = get_current_time() - elapsed_time; int i, j, k; int match = 0; for (i = 0; i < obj_keypoints->rnum; i++) { float* odesc = obj_desc->data.f32 + i * 128; int minj = -1; double mind = 1e6, mind2 = 1e6; for (j = 0; j < image_keypoints->rnum; j++) { float* idesc = image_desc->data.f32 + 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.36) { ccv_keypoint_t* op = (ccv_keypoint_t*)ccv_array_get(obj_keypoints, i); ccv_keypoint_t* kp = (ccv_keypoint_t*)ccv_array_get(image_keypoints, minj); printf("%f %f => %f %f\n", op->x, op->y, kp->x, kp->y); match++; } } printf("%dx%d on %dx%d\n", object->cols, object->rows, image->cols, image->rows); printf("%d keypoints out of %d are matched\n", match, obj_keypoints->rnum); printf("elpased time : %d\n", elapsed_time); 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_disable_cache(); return 0; }
int main(int argc, char** argv) { assert(argc >= 3); int i, j; ccv_enable_default_cache(); ccv_dense_matrix_t* image = 0; ccv_read(argv[1], &image, CCV_IO_ANY_FILE); ccv_dpm_mixture_model_t* model = ccv_dpm_read_mixture_model(argv[2]); if (image != 0) { unsigned int elapsed_time = get_current_time(); ccv_array_t* seq = ccv_dpm_detect_objects(image, &model, 1, ccv_dpm_default_params); elapsed_time = get_current_time() - elapsed_time; if (seq) { for (i = 0; i < seq->rnum; i++) { ccv_root_comp_t* comp = (ccv_root_comp_t*)ccv_array_get(seq, i); printf("%d %d %d %d %f %d\n", comp->rect.x, comp->rect.y, comp->rect.width, comp->rect.height, comp->classification.confidence, comp->pnum); for (j = 0; j < comp->pnum; j++) printf("| %d %d %d %d %f\n", comp->part[j].rect.x, comp->part[j].rect.y, comp->part[j].rect.width, comp->part[j].rect.height, comp->part[j].classification.confidence); } printf("total : %d in time %dms\n", seq->rnum, elapsed_time); ccv_array_free(seq); } else { printf("elapsed time %dms\n", elapsed_time); } ccv_matrix_free(image); } else { FILE* r = fopen(argv[1], "rt"); if (argc == 4) chdir(argv[3]); if(r) { size_t len = 1024; char* file = (char*)malloc(len); ssize_t read; while((read = getline(&file, &len, r)) != -1) { while(read > 1 && isspace(file[read - 1])) read--; file[read] = 0; image = 0; ccv_read(file, &image, CCV_IO_GRAY | CCV_IO_ANY_FILE); assert(image != 0); ccv_array_t* seq = ccv_dpm_detect_objects(image, &model, 1, ccv_dpm_default_params); if (seq != 0) { for (i = 0; i < seq->rnum; i++) { ccv_root_comp_t* comp = (ccv_root_comp_t*)ccv_array_get(seq, i); printf("%s %d %d %d %d %f %d\n", file, comp->rect.x, comp->rect.y, comp->rect.width, comp->rect.height, comp->classification.confidence, comp->pnum); for (j = 0; j < comp->pnum; j++) printf("| %d %d %d %d %f\n", comp->part[j].rect.x, comp->part[j].rect.y, comp->part[j].rect.width, comp->part[j].rect.height, comp->part[j].classification.confidence); } ccv_array_free(seq); } ccv_matrix_free(image); } free(file); fclose(r); } } ccv_drain_cache(); ccv_dpm_mixture_model_free(model); return 0; }
ccv_array_t* ccv_bbf_detect_objects(ccv_dense_matrix_t* a, ccv_bbf_classifier_cascade_t** _cascade, int count, ccv_bbf_param_t params) { int hr = a->rows / ENDORSE(params.size.height); int wr = a->cols / ENDORSE(params.size.width); double scale = pow(2., 1. / (params.interval + 1.)); APPROX int next = params.interval + 1; int scale_upto = (int)(log((double)ccv_min(hr, wr)) / log(scale)); ccv_dense_matrix_t** pyr = (ccv_dense_matrix_t**)alloca(ENDORSE(scale_upto + next * 2) * 4 * sizeof(ccv_dense_matrix_t*)); memset(pyr, 0, (scale_upto + next * 2) * 4 * sizeof(ccv_dense_matrix_t*)); if (ENDORSE(params.size.height != _cascade[0]->size.height || params.size.width != _cascade[0]->size.width)) ccv_resample(a, &pyr[0], 0, a->rows * ENDORSE(_cascade[0]->size.height / params.size.height), a->cols * ENDORSE(_cascade[0]->size.width / params.size.width), CCV_INTER_AREA); else pyr[0] = a; APPROX int i; int j, k, t, x, y, q; for (i = 1; ENDORSE(i < ccv_min(params.interval + 1, scale_upto + next * 2)); i++) ccv_resample(pyr[0], &pyr[i * 4], 0, (int)(pyr[0]->rows / pow(scale, i)), (int)(pyr[0]->cols / pow(scale, i)), CCV_INTER_AREA); for (i = next; ENDORSE(i < scale_upto + next * 2); i++) ccv_sample_down(pyr[i * 4 - next * 4], &pyr[i * 4], 0, 0, 0); if (params.accurate) for (i = next * 2; ENDORSE(i < scale_upto + next * 2); i++) { ccv_sample_down(pyr[i * 4 - next * 4], &pyr[i * 4 + 1], 0, 1, 0); ccv_sample_down(pyr[i * 4 - next * 4], &pyr[i * 4 + 2], 0, 0, 1); ccv_sample_down(pyr[i * 4 - next * 4], &pyr[i * 4 + 3], 0, 1, 1); } ccv_array_t* idx_seq; ccv_array_t* seq = ccv_array_new(sizeof(ccv_comp_t), 64, 0); ccv_array_t* seq2 = ccv_array_new(sizeof(ccv_comp_t), 64, 0); ccv_array_t* result_seq = ccv_array_new(sizeof(ccv_comp_t), 64, 0); /* detect in multi scale */ for (t = 0; t < count; t++) { ccv_bbf_classifier_cascade_t* cascade = _cascade[t]; APPROX float scale_x = (float) params.size.width / (float) cascade->size.width; APPROX float scale_y = (float) params.size.height / (float) cascade->size.height; ccv_array_clear(seq); for (i = 0; ENDORSE(i < scale_upto); i++) { APPROX int dx[] = {0, 1, 0, 1}; APPROX int dy[] = {0, 0, 1, 1}; APPROX int i_rows = pyr[i * 4 + next * 8]->rows - ENDORSE(cascade->size.height >> 2); APPROX int steps[] = { pyr[i * 4]->step, pyr[i * 4 + next * 4]->step, pyr[i * 4 + next * 8]->step }; APPROX int i_cols = pyr[i * 4 + next * 8]->cols - ENDORSE(cascade->size.width >> 2); int paddings[] = { pyr[i * 4]->step * 4 - i_cols * 4, pyr[i * 4 + next * 4]->step * 2 - i_cols * 2, pyr[i * 4 + next * 8]->step - i_cols }; for (q = 0; q < (params.accurate ? 4 : 1); q++) { APPROX unsigned char* u8[] = { pyr[i * 4]->data.u8 + dx[q] * 2 + dy[q] * pyr[i * 4]->step * 2, pyr[i * 4 + next * 4]->data.u8 + dx[q] + dy[q] * pyr[i * 4 + next * 4]->step, pyr[i * 4 + next * 8 + q]->data.u8 }; for (y = 0; ENDORSE(y < i_rows); y++) { for (x = 0; ENDORSE(x < i_cols); x++) { APPROX float sum; APPROX int flag = 1; ccv_bbf_stage_classifier_t* classifier = cascade->stage_classifier; for (j = 0; j < ENDORSE(cascade->count); ++j, ++classifier) { sum = 0; APPROX float* alpha = classifier->alpha; ccv_bbf_feature_t* feature = classifier->feature; for (k = 0; k < ENDORSE(classifier->count); ++k, alpha += 2, ++feature) sum += alpha[_ccv_run_bbf_feature(feature, ENDORSE(steps), u8)]; if (ENDORSE(sum) < ENDORSE(classifier->threshold)) { flag = 0; break; } } if (ENDORSE(flag)) { ccv_comp_t comp; comp.rect = ccv_rect((int)((x * 4 + dx[q] * 2) * scale_x + 0.5), (int)((y * 4 + dy[q] * 2) * scale_y + 0.5), (int)(cascade->size.width * scale_x + 0.5), (int)(cascade->size.height * scale_y + 0.5)); comp.neighbors = 1; comp.classification.id = t; comp.classification.confidence = sum; ccv_array_push(seq, &comp); } u8[0] += 4; u8[1] += 2; u8[2] += 1; } u8[0] += paddings[0]; u8[1] += paddings[1]; u8[2] += paddings[2]; } } scale_x *= scale; scale_y *= scale; } /* the following code from OpenCV's haar feature implementation */ if(params.min_neighbors == 0) { for (i = 0; ENDORSE(i < seq->rnum); i++) { ccv_comp_t* comp = (ccv_comp_t*)ENDORSE(ccv_array_get(seq, i)); ccv_array_push(result_seq, comp); } } else { idx_seq = 0; ccv_array_clear(seq2); // group retrieved rectangles in order to filter out noise int ncomp = ccv_array_group(seq, &idx_seq, _ccv_is_equal_same_class, 0); ccv_comp_t* comps = (ccv_comp_t*)ccmalloc((ncomp + 1) * sizeof(ccv_comp_t)); memset(comps, 0, (ncomp + 1) * sizeof(ccv_comp_t)); // count number of neighbors for(i = 0; ENDORSE(i < seq->rnum); i++) { ccv_comp_t r1 = *(ccv_comp_t*)ENDORSE(ccv_array_get(seq, i)); int idx = *(int*)ENDORSE(ccv_array_get(idx_seq, i)); if (ENDORSE(comps[idx].neighbors) == 0) comps[idx].classification.confidence = r1.classification.confidence; ++comps[idx].neighbors; comps[idx].rect.x += r1.rect.x; comps[idx].rect.y += r1.rect.y; comps[idx].rect.width += r1.rect.width; comps[idx].rect.height += r1.rect.height; comps[idx].classification.id = r1.classification.id; comps[idx].classification.confidence = ccv_max(comps[idx].classification.confidence, r1.classification.confidence); } // calculate average bounding box for(i = 0; ENDORSE(i < ncomp); i++) { int n = ENDORSE(comps[i].neighbors); if(n >= params.min_neighbors) { ccv_comp_t comp; comp.rect.x = (comps[i].rect.x * 2 + n) / (2 * n); comp.rect.y = (comps[i].rect.y * 2 + n) / (2 * n); comp.rect.width = (comps[i].rect.width * 2 + n) / (2 * n); comp.rect.height = (comps[i].rect.height * 2 + n) / (2 * n); comp.neighbors = comps[i].neighbors; comp.classification.id = comps[i].classification.id; comp.classification.confidence = comps[i].classification.confidence; ccv_array_push(seq2, &comp); } } // filter out small face rectangles inside large face rectangles for(i = 0; ENDORSE(i < seq2->rnum); i++) { ccv_comp_t r1 = *(ccv_comp_t*)ENDORSE(ccv_array_get(seq2, i)); APPROX int flag = 1; for(j = 0; ENDORSE(j < seq2->rnum); j++) { ccv_comp_t r2 = *(ccv_comp_t*)ENDORSE(ccv_array_get(seq2, j)); APPROX int distance = (int)(r2.rect.width * 0.25 + 0.5); if(ENDORSE(i != j && r1.classification.id == r2.classification.id && r1.rect.x >= r2.rect.x - distance && r1.rect.y >= r2.rect.y - distance && r1.rect.x + r1.rect.width <= r2.rect.x + r2.rect.width + distance && r1.rect.y + r1.rect.height <= r2.rect.y + r2.rect.height + distance && (r2.neighbors > ccv_max(3, r1.neighbors) || r1.neighbors < 3))) { flag = 0; break; } } if(ENDORSE(flag)) ccv_array_push(result_seq, &r1); } ccv_array_free(idx_seq); ccfree(comps); } } ccv_array_free(seq); ccv_array_free(seq2); ccv_array_t* result_seq2; /* the following code from OpenCV's haar feature implementation */ if (params.flags & CCV_BBF_NO_NESTED) { result_seq2 = ccv_array_new(sizeof(ccv_comp_t), 64, 0); idx_seq = 0; // group retrieved rectangles in order to filter out noise int ncomp = ccv_array_group(result_seq, &idx_seq, _ccv_is_equal, 0); ccv_comp_t* comps = (ccv_comp_t*)ccmalloc((ncomp + 1) * sizeof(ccv_comp_t)); memset(comps, 0, (ncomp + 1) * sizeof(ccv_comp_t)); // count number of neighbors for(i = 0; ENDORSE(i < result_seq->rnum); i++) { ccv_comp_t r1 = *(ccv_comp_t*)ENDORSE(ccv_array_get(result_seq, i)); int idx = *(int*)ENDORSE(ccv_array_get(idx_seq, i)); if (ENDORSE(comps[idx].neighbors == 0 || comps[idx].classification.confidence < r1.classification.confidence)) { comps[idx].classification.confidence = r1.classification.confidence; comps[idx].neighbors = 1; comps[idx].rect = r1.rect; comps[idx].classification.id = r1.classification.id; } } // calculate average bounding box for(i = 0; ENDORSE(i < ncomp); i++) if(ENDORSE(comps[i].neighbors)) ccv_array_push(result_seq2, &comps[i]); ccv_array_free(result_seq); ccfree(comps); } else { result_seq2 = result_seq; } for (i = 1; ENDORSE(i < scale_upto + next * 2); i++) ccv_matrix_free(pyr[i * 4]); if (params.accurate) for (i = next * 2; ENDORSE(i < scale_upto + next * 2); i++) { ccv_matrix_free(pyr[i * 4 + 1]); ccv_matrix_free(pyr[i * 4 + 2]); ccv_matrix_free(pyr[i * 4 + 3]); } if (ENDORSE(params.size.height != _cascade[0]->size.height || params.size.width != _cascade[0]->size.width)) ccv_matrix_free(pyr[0]); return result_seq2; }