void adjust_sigma(Simulator *sim, int steps, double step_size, double factor) { double original_sigma = sim->sigma; double best_sigma = sim->sigma; double best_error = barcode_error(sim); for (int step = -steps; step <= steps; step++) { if (step == 0) continue; sim->sigma = original_sigma + step * step_size; if (sim->sigma < 1.0) continue; compute_kernel(sim); convolve_1d(sim->kernel_width, sim->kernel, sim->width, sim->guess, sim->blur, 0, sim->width); double error = barcode_error(sim); // printf("sigma=%.2f error=%.2f\n", sim->sigma, error); if (error < best_error) { best_error = error; best_sigma = sim->sigma; } } sim->sigma = best_sigma * factor + original_sigma * (1.0 - factor); compute_kernel(sim); convolve_1d(sim->kernel_width, sim->kernel, sim->width, sim->guess, sim->blur, 0, sim->width); }
int guess_digit(Simulator *sim, int *sections, int index, int choices_count, char *choices) { // printf("guess_digit start=%d stop=%d\n", sections[0], sections[7]); int start = sim->changes_count; int best_choice = -1; double best_error = UNKNOWN; for (int choice = 0; choice < choices_count; choice++) { encode_bits(sim->width, sim->black, sim->white, sim->guess, sections, 7, choices[choice]); convolve_1d(sim->kernel_width, sim->kernel, sim->width, sim->guess, sim->blur, sections[0], sections[7]); double error = samples_error(sim, sections[0], sections[7]); if (error < best_error) { best_choice = choice; best_error = error; } sim->changes[sim->changes_count].error = error; sim->changes[sim->changes_count].index = index; sim->changes[sim->changes_count].digit = choice; sim->changes_count++; } // Make all changes relative to the best choice. for (int i = start; i < sim->changes_count; i++) sim->changes[i].error -= sim->changes[start + best_choice].error; // Remove the best choice from the changes array. if (best_choice < choices_count - 1) sim->changes[start + best_choice] = sim->changes[start + choices_count - 1]; sim->changes_count--; return best_choice; }
Rle<double> convolve_1d(Rle<double> &rle, std::vector<double> const& kernel, bool rescale, double eps) { std::vector<double> tmp = rle.expand(); std::vector<double> result = convolve_1d(tmp, kernel, rescale); return Rle<double>(result, eps); }
void simulate_range(Simulator *sim, int start, int stop) { // printf("simulate_range start=%d stop=%d\n", start, stop); int x = start; int next_section = 0; while (next_section < 96 && x > sim->sections[next_section]) next_section++; while (x < stop) { // printf("start=%d x=%d stop=%d sections[%d]=%d\n", // start, x, stop, next_section, sim->sections[next_section]); if (next_section <= 0) { // Left shoulder. for (; x < sim->sections[0]; x++) sim->guess[x] = sim->white[x]; next_section = 1; } else if (next_section <= 3) { // Left guard bars. encode_bits(sim->width, sim->black, sim->white, sim->guess, &sim->sections[0], 3, 0x5); next_section = 4; } else if (next_section <= 45) { // Left six digits. int i = (next_section - 4) / 7; encode_bits(sim->width, sim->black, sim->white, sim->guess, &sim->sections[3 + 7 * i], 7, LG[(int)sim->digits[1 + i]]); next_section = 3 + 7 * i + 8; } else if (next_section <= 50) { // Middle guard bars. encode_bits(sim->width, sim->black, sim->white, sim->guess, &sim->sections[45], 5, 0xa); next_section = 51; } else if (next_section <= 92) { // Right six digits. int i = (next_section - 51) / 7; encode_bits(sim->width, sim->black, sim->white, sim->guess, &sim->sections[50 + 7 * i], 7, R[(int)sim->digits[7 + i]]); next_section = 50 + 7 * i + 8; } else if (next_section <= 95) { // Right guard bars. encode_bits(sim->width, sim->black, sim->white, sim->guess, &sim->sections[92], 3, 0x5); next_section = 96; } else { // Right shoulder. for (; x < stop; x++) sim->guess[x] = sim->white[x]; break; } x = sim->sections[next_section - 1]; } convolve_1d(sim->kernel_width, sim->kernel, sim->width, sim->guess, sim->blur, start, stop); }
void correct_errors(Simulator *sim, int max_changes, int max_count) { if (is_valid_barcode(sim->digits)) return; qsort(sim->changes, sim->changes_count, sizeof(Change), compare_float); // for (int i = 0; i < 10; i++) // printf("error=%.6f index=%d digit=%d\n", // changes[i].error, changes[i].index, changes[i].digit); if (sim->changes_count > max_count) sim->changes_count = max_count; // Terminate search for valid candidate. sim->changes[sim->changes_count].index = -1; best_valid_barcode(sim->changes, max_changes, sim->digits); encode_ean13(sim->width, sim->black, sim->white, sim->guess, sim->sections, sim->digits); convolve_1d(sim->kernel_width, sim->kernel, sim->width, sim->guess, sim->blur, 0, sim->width); sim->checksum = ean13_checksum(sim->digits); }
void guess_digits(Simulator *sim) { // printf("guess_digits...\n"); sim->changes_count = 0; sim->digits[0] = 0; for (int i = 0; i < 6; i++) { sim->digits[1 + i] = guess_digit(sim, &sim->sections[3 + i * 7], 1 + i, i ? 20 : 10, LG); sim->digits[7 + i] = guess_digit(sim, &sim->sections[50 + i * 7], 7 + i, 10, R); } encode_ean13(sim->width, sim->black, sim->white, sim->guess, sim->sections, sim->digits); convolve_1d(sim->kernel_width, sim->kernel, sim->width, sim->guess, sim->blur, 0, sim->width); sim->digits[0] = ean13_first_digit(sim->digits); sim->checksum = ean13_checksum(sim->digits); memcpy(sim->unchanged_digits, sim->digits, 13); }