private void detectVerticalLines(int width, int height) { vertical_lines = new ArrayList(); ArrayList[] horizontal_positions = new ArrayList[horizontal_magnitude.GetLength(0)]; ArrayList[] horizontal_positions_used = new ArrayList[horizontal_magnitude.GetLength(0)]; int max_y = height - (height / 4); if (ROI != null) max_y = ROI.by; int min_y = width / 4; if (ROI != null) min_y = ROI.ty; float bottom_spacing = 0; float top_spacing = 0; // detect the positions of horizontal disscontinuities for (int i = 0; i < horizontal_magnitude.GetLength(0); i++) { horizontal_positions[i] = new ArrayList(); horizontal_positions_used[i] = new ArrayList(); int n = 0; int prev_x = -1; for (int x = 0; x < width; x++) if (horizontal_magnitude[i, x] > 0) { horizontal_positions[i].Add(x); horizontal_positions_used[i].Add(false); int y = (height - 1) * i / horizontal_magnitude.GetLength(0) + (height / (horizontal_magnitude.GetLength(0) * 2)); if (ROI != null) y = ROI.ty + (i * (ROI.by - ROI.ty) / horizontal_magnitude.GetLength(0)) + ((ROI.by - ROI.ty) / (horizontal_magnitude.GetLength(0) * 2)); if (prev_x > -1) { if (i == 0) top_spacing += (x - prev_x); if (i == horizontal_magnitude.GetLength(0)-1) bottom_spacing += (x - prev_x); n++; } prev_x = x; } if ((i == 0) && (n > 0)) top_spacing /= n; if ((i == horizontal_magnitude.GetLength(0) - 1) && (n > 0)) bottom_spacing /= n; } // calculate the vertical gradient using the top and bottom horizontal spacings if ((top_spacing > 0) && (bottom_spacing > 0)) { if (bottom_spacing < top_spacing * 1.3f) bottom_spacing = top_spacing * 1.3f; if (ROI != null) vertical_gradient = (bottom_spacing - top_spacing) / (float)(ROI.by - ROI.ty); else vertical_gradient = (bottom_spacing - top_spacing) / (float)(height*3/4); } float vertical_additive = 0.5f; int max_horizontal_difference = (int)(width * separation_factor * 1.9f); for (int j = 0; j < horizontal_positions[0].Count; j++) { int x = (int)horizontal_positions[0][j]; int y = height / (horizontal_magnitude.GetLength(0) * 2); if (ROI != null) y = ROI.ty; bool drawn = false; calibration_line line = new calibration_line(); for (int i = 1; i < horizontal_magnitude.GetLength(0); i++) { int max_connectedness = min_connectedness; int best_x = -1; int best_y = -1; int idx = -1; for (int k = 0; k < horizontal_positions[i].Count; k++) { int x2 = (int)horizontal_positions[i][k]; int dx = x2 - x; if (Math.Abs(dx) < max_horizontal_difference) { int y2 = (height - 1) * i / horizontal_magnitude.GetLength(0) + (height / (horizontal_magnitude.GetLength(0) * 2)); if (ROI != null) y2 = ROI.ty + (i * (ROI.by - ROI.ty) / horizontal_magnitude.GetLength(0)) + ((ROI.by - ROI.ty) / (horizontal_magnitude.GetLength(0) * 2)); // are these two connected? if ((y < height) && (y2 < height)) { int grid_width = (int)(top_spacing + (vertical_additive * (bottom_spacing - top_spacing) * y2 / height)); if (ROI != null) grid_width = (int)(top_spacing + (vertical_additive * (bottom_spacing - top_spacing) * (y2 - ROI.ty) / (ROI.by - ROI.ty))); if (!(((x > width * 55 / 100) && (x>x2) && (x2 < x + grid_width)) || ((x < width * 45 / 100) && (x < x2) && (x2 > x - grid_width)))) { int connectedness = pointsConnectedByIntensity(width, height, x, y, x2, y2); if (connectedness > max_connectedness) { best_x = x2; best_y = y2; max_connectedness = connectedness; idx = k; } } } } } if (best_x > -1) { horizontal_positions_used[i][idx] = true; calibration_line temp_line = traceLine(width, height, x, y, best_x, best_y); line.Add(temp_line); x = best_x; y = best_y; drawn = true; } } if (drawn) { calibration_line temp_line = traceLine(width, height, x, y, x, max_y); line.Add(temp_line); if (line.points.Count > 0) vertical_lines.Add(line); } } int index = horizontal_magnitude.GetLength(0) - 1; for (int j = 0; j < horizontal_positions[index].Count; j++) { if ((bool)horizontal_positions_used[index][j] == false) { int x = (int)horizontal_positions[index][j]; int y = height - (height / (horizontal_magnitude.GetLength(0) * 2)); if (ROI != null) y = ROI.by - ((ROI.by - ROI.ty) / (horizontal_magnitude.GetLength(0) * 2)); bool drawn = false; calibration_line line = new calibration_line(); for (int i = horizontal_magnitude.GetLength(0) - 2; i >= 0; i--) { int max_connectedness = min_connectedness; int best_x = -1; int best_y = -1; int idx = -1; for (int k = 0; k < horizontal_positions[i].Count; k++) { int x2 = (int)horizontal_positions[i][k]; int dx = x2 - x; if (Math.Abs(dx) < max_horizontal_difference) { int y2 = height - ((height - 1) * i / horizontal_magnitude.GetLength(0) + (height / (horizontal_magnitude.GetLength(0) * 2))); if (ROI != null) y2 = ROI.by - (i * (ROI.by - ROI.ty) / horizontal_magnitude.GetLength(0)) + ((ROI.by - ROI.ty) / (horizontal_magnitude.GetLength(0) * 2)); // are these two connected? if ((y < height) && (y2 < height)) { int grid_width = (int)(top_spacing + (vertical_additive * (bottom_spacing - top_spacing) * y2 / height)); if (ROI != null) grid_width = (int)(top_spacing + (vertical_additive * (bottom_spacing - top_spacing) * (y2 - ROI.ty) / (ROI.by - ROI.ty))); if (!(((x > width * 55 / 100) && (x > x2) && (x2 < x + grid_width)) || ((x < width * 45 / 100) && (x < x2) && (x2 > x - grid_width)))) { int connectedness = pointsConnectedByIntensity(width, height, x, y, x2, y2); if (connectedness > max_connectedness) { best_x = x2; best_y = y2; max_connectedness = connectedness; idx = k; } } } } } if (best_x > -1) { calibration_line temp_line = traceLine(width, height, best_x, best_y, x, y); temp_line.Reverse(); line.Add(temp_line); x = best_x; y = best_y; drawn = true; } } if (drawn) { calibration_line temp_line = traceLine(width, height, x, min_y, x, y); temp_line.Reverse(); line.Add(temp_line); line.Reverse(); if (line.points.Count > 0) vertical_lines.Add(line); } } } // sort and prune detectLinesSort(width, height, false, vertical_lines); // remove first and last lines , because these are usually poorly detected if (vertical_lines.Count > 2) { vertical_lines.RemoveAt(vertical_lines.Count - 1); vertical_lines.RemoveAt(0); } updateAllLines(width, height, false, vertical_lines); // add index numbers to the lines indexLines(width, height, false, all_vertical_lines); // draw for (int i = 0; i < all_vertical_lines.Count; i++) { calibration_line line = (calibration_line)all_vertical_lines[i]; line.Draw(lines_image, width, height, 255, 0, 0); } }
/// <summary> /// trace along a line /// </summary> /// <param name="width"></param> /// <param name="height"></param> /// <param name="tx"></param> /// <param name="ty"></param> /// <param name="bx"></param> /// <param name="by"></param> /// <returns></returns> private calibration_line traceLine(int width, int height, int tx, int ty, int bx, int by) { calibration_line line = new calibration_line(); int step_size = 10; int radius_x = (int)(width * separation_factor / 4); int radius_x2 = (int)(width * separation_factor * 10 / 4); if (radius_x < 1) radius_x = 1; int radius_y = (int)(height * separation_factor / 4); int radius_y2 = (int)(height * separation_factor * 10 / 4); if (radius_y < 1) radius_y = 1; int dx = bx - tx; int dy = by - ty; if (ROI != null) { if (tx < ROI.tx) tx = ROI.tx; if (ty < ROI.ty) ty = ROI.ty; if (bx > ROI.bx) bx = ROI.bx; if (by > ROI.by) by = ROI.by; } if (dy > dx) { step_size = radius_y2 * 3 / 2; // *3 / 4; if (step_size < 1) step_size = 1; for (int y = ty; y < by; y += step_size * height / 240) { int x = tx + (dx * (y - ty) / dy); radius_x = (int)(width * separation_factor * 1.0f); if (radius_x < 1) radius_x = 1; radius_y = (int)(height * (separation_factor * 2.0f)); if (radius_y < 1) radius_y = 1; int av_x = 0; int av_y = 0; int hits = 0; for (int xx = x - radius_x; xx < x + radius_x; xx++) { if ((xx > 2) && (xx < width-2)) { for (int yy = y - radius_y2; yy < y + radius_y2; yy++) { if ((yy > -1) && (yy < height)) { if (edges_binary[xx, yy]) { av_x += xx; av_y += yy; hits++; } } } } } if (hits > 0) { av_x /= hits; av_y /= hits; int n = (y * width) + av_x; int intensity = calibration_image[n]; int min_x = av_x; for (int xx = av_x - 3; xx <= av_x + 3; xx++) { if ((xx > -1) && (xx < width)) { n = (y * width) + xx; if (calibration_image[n] < intensity) { intensity = calibration_image[n]; min_x = xx; } } } line.Add(min_x, y); } } } else { step_size = radius_x2 * 3 / 2; // *3 / 4; if (step_size < 1) step_size = 1; for (int x = tx; x < bx; x += step_size * width / 320) { int y = ty + (dy * (x - tx) / dx); radius_x = (int)(width * separation_factor * 0.5f); if (radius_x < 1) radius_x = 1; radius_y = (int)(height * separation_factor * 1.0f); if (radius_y < 1) radius_y = 1; int av_x = 0; int av_y = 0; int hits = 0; //int max_diff = 0; for (int xx = x - radius_x2; xx < x + radius_x2; xx++) { if ((xx > -1) && (xx < width)) { for (int yy = y - radius_y; yy < y + radius_y; yy++) { if ((yy > 2) && (yy < height-2)) { if (edges_binary[xx, yy]) { av_x += xx; av_y += yy; hits++; } } } } } if (hits > 0) { av_x /= hits; av_y /= hits; int n = (av_y * width) + x; int intensity = calibration_image[n]; int min_y = av_y; for (int yy = av_y - 2; yy <= av_y + 2; yy++) { if ((yy > -1) && (yy < height)) { n = (yy * width) + x; if (calibration_image[n] < intensity) { intensity = calibration_image[n]; min_y = yy; } } } line.Add(x, min_y); } } } return (line); }
private void detectHorizontalLines(int width, int height) { horizontal_lines = new ArrayList(); ArrayList[] vertical_positions = new ArrayList[vertical_magnitude.GetLength(0)]; ArrayList[] vertical_positions_used = new ArrayList[vertical_magnitude.GetLength(0)]; int max_x = width - (width / 4); if (ROI != null) max_x = ROI.bx; int min_x = width / 4; if (ROI != null) min_x = ROI.tx; // detect the positions of horizontal disscontinuities for (int i = 0; i < vertical_magnitude.GetLength(0); i++) { vertical_positions[i] = new ArrayList(); vertical_positions_used[i] = new ArrayList(); for (int y = 0; y < height; y++) if (vertical_magnitude[i, y] > 0) { vertical_positions[i].Add(y); vertical_positions_used[i].Add(false); int x = (width - 1) * i / vertical_magnitude.GetLength(0) + (width / (vertical_magnitude.GetLength(0)*2)); if (ROI != null) x = ROI.tx + (i * (ROI.bx - ROI.tx) / vertical_magnitude.GetLength(0)) + ((ROI.bx - ROI.tx) / (vertical_magnitude.GetLength(0)*2)); } } int max_vertical_difference = (int)((height * separation_factor) / 1.0f); for (int j = 0; j < vertical_positions[0].Count; j++) { int y = (int)vertical_positions[0][j]; int x = width / (vertical_magnitude.GetLength(0) * 2); if (ROI != null) x = ROI.tx; bool drawn = false; calibration_line line = new calibration_line(); for (int i = 1; i < vertical_magnitude.GetLength(0); i++) { int max_connectedness = min_connectedness; int best_x = -1; int best_y = -1; int idx = -1; for (int k = 0; k < vertical_positions[i].Count; k++) { int y2 = (int)vertical_positions[i][k]; int dy = y2 - y; if (Math.Abs(dy) < max_vertical_difference) { int x2 = (width - 1) * i / vertical_magnitude.GetLength(0) + (width / (vertical_magnitude.GetLength(0) * 2)); if (ROI != null) x2 = ROI.tx + (i * (ROI.bx - ROI.tx) / vertical_magnitude.GetLength(0)) + ((ROI.bx - ROI.tx) / (vertical_magnitude.GetLength(0) * 2)); // are these two connected? int connectedness = pointsConnectedByIntensity(width, height, x, y, x2, y2); if (connectedness > max_connectedness) { best_x = x2; best_y = y2; max_connectedness = connectedness; idx = k; } } } if (best_x > -1) { vertical_positions_used[i][idx] = true; calibration_line temp_line = traceLine(width, height, x, y, best_x, best_y); line.Add(temp_line); x = best_x; y = best_y; drawn = true; } } if (drawn) { calibration_line temp_line = traceLine(width, height, x, y, max_x, y); line.Add(temp_line); if (line.points.Count > 0) horizontal_lines.Add(line); } } int index = vertical_magnitude.GetLength(0) - 1; for (int j = 0; j < vertical_positions[index].Count; j++) { if ((bool)vertical_positions_used[index][j] == false) { int y = (int)vertical_positions[index][j]; int x = width - (width / (vertical_magnitude.GetLength(0) * 2)); if (ROI != null) x = ROI.bx - ((ROI.bx - ROI.tx) / (vertical_magnitude.GetLength(0) * 2)); bool drawn = false; calibration_line line = new calibration_line(); for (int i = vertical_magnitude.GetLength(0) - 2; i >= 0; i--) { int max_connectedness = min_connectedness; int best_x = -1; int best_y = -1; int idx = -1; for (int k = 0; k < vertical_positions[i].Count; k++) { int y2 = (int)vertical_positions[i][k]; int dy = y2 - y; if (Math.Abs(dy) < max_vertical_difference) { int x2 = width - ((width - 1) * i / vertical_magnitude.GetLength(0) + (width / (vertical_magnitude.GetLength(0) * 2))); if (ROI != null) x2 = ROI.bx - (i * (ROI.bx - ROI.tx) / vertical_magnitude.GetLength(0)) + ((ROI.bx - ROI.tx) / (vertical_magnitude.GetLength(0) * 2)); // are these two connected? int connectedness = pointsConnectedByIntensity(width, height, x, y, x2, y2); if (connectedness > max_connectedness) { best_x = x2; best_y = y2; max_connectedness = connectedness; idx = k; } } } if (best_x > -1) { calibration_line temp_line = traceLine(width, height, best_x, best_y, x, y); temp_line.Reverse(); line.Add(temp_line); x = best_x; y = best_y; drawn = true; } } if (drawn) { calibration_line temp_line = traceLine(width, height, min_x, y, x, y); temp_line.Reverse(); line.Add(temp_line); line.Reverse(); if (line.points.Count > 0) horizontal_lines.Add(line); } } } // sort and prune detectLinesSort(width, height, true, horizontal_lines); // remove first and last lines, since they're often poorly detected if (horizontal_lines.Count > 2) { horizontal_lines.RemoveAt(horizontal_lines.Count - 1); horizontal_lines.RemoveAt(0); } updateAllLines(width, height, true, horizontal_lines); // add index numbers to the lines indexLines(width, height, true, all_horizontal_lines); // draw for (int i = 0; i < all_horizontal_lines.Count; i++) { calibration_line line = (calibration_line)all_horizontal_lines[i]; line.Draw(lines_image, width, height, 255, 0, 0); } }
/// <summary> /// adds a point to the line /// </summary> /// <param name="line"></param> public void Add(calibration_line line) { for (int i = 0; i < line.points.Count; i++) points.Add((calibration_point)line.points[i]); }