Beispiel #1
0
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;
}
Beispiel #2
0
void ccv_enable_default_cache(void)
{
	ccv_enable_cache(CCV_DEFAULT_CACHE_SIZE);
}
Beispiel #3
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;
}