/// <summary> /// return true if this polygon overlaps with another /// </summary> /// <param name="other"></param> /// <returns></returns> public bool overlaps(polygon2D other) { int i; bool retval = false; i = 0; while ((i < x_points.Count) && (retval == false)) { if (other.isInside((float)x_points[i], (float)y_points[i])) { retval = true; } i++; } i = 0; while ((i < other.x_points.Count) && (retval == false)) { if (isInside((float)other.x_points[i], (float)other.y_points[i])) { retval = true; } i++; } return(retval); }
/// <summary> /// does this polygon overlap with the other, within the given screen dimensions /// </summary> /// <param name="other">other polygon object</param> /// <param name="image_width">image width</param> /// <param name="image_height">image height</param> /// <returns></returns> public bool overlaps(polygon2D other, int image_width, int image_height) { int i; bool retval = false; i = 0; while ((i < x_points.Count) && (retval == false)) { if (other.isInside((float)x_points[i] * 1000 / image_width, (float)y_points[i] * 1000 / image_height)) { retval = true; } i++; } i = 0; while ((i < other.x_points.Count) && (retval == false)) { if (isInside((float)other.x_points[i] * image_width / 1000, (float)other.y_points[i] * image_height / 1000)) { retval = true; } i++; } return(retval); }
/// <summary> /// does this polygon overlap with the other, within the given screen dimensions /// </summary> /// <param name="other">other polygon object</param> /// <param name="image_width">image width</param> /// <param name="image_height">image height</param> /// <returns></returns> public bool overlaps(polygon2D other, int image_width, int image_height) { int i; bool retval = false; i = 0; while ((i < x_points.Count) && (retval == false)) { if (other.isInside((float)x_points[i] * 1000 / image_width, (float)y_points[i] * 1000 / image_height)) retval = true; i++; } i = 0; while ((i < other.x_points.Count) && (retval == false)) { if (isInside((float)other.x_points[i] * image_width / 1000, (float)other.y_points[i] * image_height / 1000)) retval = true; i++; } return (retval); }
/// <summary> /// return true if this polygon overlaps with another /// </summary> /// <param name="other"></param> /// <returns></returns> public bool overlaps(polygon2D other) { int i; bool retval = false; i = 0; while ((i < x_points.Count) && (retval == false)) { if (other.isInside((float)x_points[i],(float)y_points[i])) retval=true; i++; } i = 0; while ((i < other.x_points.Count) && (retval == false)) { if (isInside((float)other.x_points[i], (float)other.y_points[i])) retval = true; i++; } return (retval); }
/// <summary> /// crops line features to the given perimeter shape /// </summary> /// <param name="lines">list of line features</param> /// <param name="perimeter">defines the shape within which lines should reside</param> public static ArrayList cropLines(ArrayList lines, polygon2D perimeter) { ArrayList cropped = new ArrayList(); for (int i = 0; i < lines.Count; i++) { linefeature line1 = (linefeature)lines[i]; if (perimeter.isInside((int)line1.x0, (int)line1.y0)) if (perimeter.isInside((int)line1.x1, (int)line1.y1)) cropped.Add(line1); } return(cropped); }
/// <summary> /// returns a grey scale histogram for the given image within the given perimeter region /// </summary> /// <param name="bmp">image data</param> /// <param name="wdth">width of the image</param> /// <param name="hght">height of the image</param> /// <param name="bytes_per_pixel">number of bytes per pixel</param> /// <param name="levels">histogram levels</param> /// <param name="perimeter">perimeter region inside which to calculate the histogram</param> /// <returns></returns> public static float[] GetGreyHistogram(byte[] bmp, int wdth, int hght, int bytes_per_pixel, int levels, polygon2D perimeter) { float[] hist = new float[levels]; int tx = (int)perimeter.left(); int ty = (int)perimeter.top(); int bx = (int)perimeter.right(); int by = (int)perimeter.bottom(); for (int y = ty; y <= by; y++) { if ((y > -1) && (y < hght)) { for (int x = tx; x <= bx; x++) { if ((x > -1) && (x < wdth)) { if (perimeter.isInside(x, y)) { int n = ((y * wdth) + x) * bytes_per_pixel; float intensity = 0; for (int col = 0; col < bytes_per_pixel; col++) intensity += bmp[n + col]; intensity /= bytes_per_pixel; int bucket = (int)Math.Round(intensity * levels / 255); if (bucket >= levels) bucket = levels - 1; hist[bucket]++; } } } } } // normalise the histogram float max = 1; for (int level = 0; level < levels; level++) if (hist[level] > max) max = hist[level]; for (int level = 0; level < levels; level++) hist[level] = hist[level] / max; return (hist); }
/// <summary> /// show the region within the given image /// </summary> /// <param name="bmp">image to draw into</param> /// <param name="image_width">width of the image</param> /// <param name="image_height">height of the image</param> /// <param name="bytes_per_pixel">number of bytes per pixel</param> /// <param name="line_width">line width to use when drawing</param> public void Show(byte[] bmp, int image_width, int image_height, int bytes_per_pixel, int line_width, int style) { if (bytes_per_pixel == 3) { int[] colr = new int[3]; colr[0] = 255; colr[1] = 255; colr[2] = 255; // use different colours for different types of region if (classification == "interesting area") { colr[0] = 0; colr[1] = 255; colr[2] = 0; } if (classification == "datamatrix") { colr[0] = 0; colr[1] = 255; colr[2] = 0; } if (classification == "text") { colr[0] = 255; colr[1] = 255; colr[2] = 0; } /* if (geometry_type == "square") { colr[0] = 0; colr[1] = 255; colr[2] = 255; } if (geometry_type == "triangle") { colr[0] = 255; colr[1] = 0; colr[2] = 255; } */ switch (style) { case 0: // show boxes { float prev_x = 0, prev_y = 0; float initial_x = -1, initial_y = 0; float x = 0, y = 0; for (int i = 0; i < corners.Count; i += 2) { x = tx + (float)corners[i]; y = ty + (float)corners[i + 1]; if (i > 0) { sluggish.utilities.drawing.drawLine( bmp, image_width, image_height, (int)prev_x, (int)prev_y, (int)x, (int)y, colr[0], colr[1], colr[2], line_width, false); } else { initial_x = x; initial_y = y; } prev_x = x; prev_y = y; } if (initial_x > -1) { sluggish.utilities.drawing.drawLine( bmp, image_width, image_height, (int)initial_x, (int)initial_y, (int)x, (int)y, colr[0], colr[1], colr[2], line_width, false); } break; } case 1: // show colonisation { for (int x = tx; x < tx + width; x++) { for (int y = ty; y < ty + height; y++) { if (shape[x - tx, y - ty]) { int n = ((y * image_width) + x) * 3; for (int col = 0; col < 3; col++) bmp[n + col] = (byte)colr[col]; } } } break; } case 2: // show outline { float x = 0, y = 0; float prev_x = 0; float prev_y = 0; for (int i = 0; i < outline.Count; i += 2) { x = tx + (int)outline[i]; y = ty + (int)outline[i + 1]; if (i > 0) { sluggish.utilities.drawing.drawLine( bmp, image_width, image_height, (int)prev_x, (int)prev_y, (int)x, (int)y, colr[0], colr[1], colr[2], line_width, false); } prev_x = x; prev_y = y; } // show corners for (int i = 0; i < corners.Count; i += 2) { x = tx + (float)corners[i]; y = ty + (float)corners[i + 1]; if (i / 2 != highlight_corner) { sluggish.utilities.drawing.drawCircle( bmp, image_width, image_height, (int)x, (int)y, 5, colr[0], colr[1], colr[2], line_width); } else { sluggish.utilities.drawing.drawCircle( bmp, image_width, image_height, (int)x, (int)y, 5, 255, 0, 0, line_width + 1); } } break; } case 3: // show orientations { int centre_xx = tx + centre_x; int centre_yy = ty + centre_y; int dx = (int)((major_axis_length / 2) * Math.Cos(orientation)); int dy = (int)((major_axis_length / 2) * Math.Sin(orientation)); sluggish.utilities.drawing.drawLine( bmp, image_width, image_height, centre_xx - dx, centre_yy - dy, centre_xx + dx, centre_yy + dy, colr[0], colr[1], colr[2], line_width, false); dx = (int)((minor_axis_length / 2) * Math.Cos(orientation - (Math.PI / 2))); dy = (int)((minor_axis_length / 2) * Math.Sin(orientation - (Math.PI / 2))); sluggish.utilities.drawing.drawLine( bmp, image_width, image_height, centre_xx - dx, centre_yy - dy, centre_xx + dx, centre_yy + dy, colr[0], colr[1], colr[2], line_width, false); break; } case 4: // binary threshold { if (binary_image != null) { for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) //if (polygon.isInside(x, y)) { int xx = tx + x; int yy = ty + y; int n = ((yy * image_width) + xx) * 3; for (int col = 0; col < 3; col++) if (binary_image[x, y]) bmp[n + col] = (byte)255; else bmp[n + col] = (byte)0; } } break; } case 5: // background model low { if (binary_image != null) { for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { int xx = tx + x; int yy = ty + y; int n = ((yy * image_width) + xx) * 3; for (int col = 0; col < 3; col++) bmp[n + col] = (byte)background_low[x, y]; } } break; } case 6: // background model high { if (binary_image != null) { for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { int xx = tx + x; int yy = ty + y; int n = ((yy * image_width) + xx) * 3; for (int col = 0; col < 3; col++) bmp[n + col] = (byte)background_high[x, y]; } } break; } case 7: // polygon { if (polygon != null) { polygon.show(bmp, image_width, image_height, 255, 255, 0, 0, tx, ty); } break; } case 8: // spot responses { if (spot_map != null) { for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { if (polygon.isInside(x, y)) { int xx = tx + x; int yy = ty + y; int n = ((yy * image_width) + xx) * 3; byte response_value = (byte)(spot_map[x, y] * 255); if (response_value > 30) { bmp[n] = 0; bmp[n + 1] = response_value; bmp[n + 2] = response_value; } } } } break; } case 9: // spot centres { if (spots != null) { polygon = createPolygon(); for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { if (polygon.isInside(x, y)) { int xx = tx + x; int yy = ty + y; int n = ((yy * image_width) + xx) * 3; byte value = (byte)(spot_map[x, y] * 255); if (value > 5) { bmp[n] = value; bmp[n + 1] = 0; bmp[n + 2] = 0; } } } for (int i = 0; i < spots.Count; i++) { blob spot = (blob)spots[i]; int n = (((ty + (int)Math.Round(spot.interpolated_y)) * image_width) + (tx + (int)Math.Round(spot.interpolated_x))) * 3; bmp[n] = (byte)255; bmp[n + 1] = (byte)255; bmp[n + 2] = (byte)255; } } break; } case 10: // spots { if (spots != null) { for (int i = 0; i < spots.Count; i++) { blob spot = (blob)spots[i]; int x = tx + (int)Math.Round(spot.interpolated_x); int y = ty + (int)Math.Round(spot.interpolated_y); int radius = (int)Math.Round(spot.average_radius); int r = 0; int g = 255; int b = 0; if (spot.selected) { r = 255; } if (spot.touched) { r = 255; g = 0; b = 255; } sluggish.utilities.drawing.drawCircle(bmp, image_width, image_height, x, y, radius, r, g, b, 0); } } break; } case 11: // connected points { if (spots != null) { for (int i = 0; i < spots.Count; i++) { blob spot = (blob)spots[i]; int x1 = tx + (int)spot.x; int y1 = ty + (int)spot.y; for (int j = 0; j < spot.neighbours.Count; j++) { blob neighbour = (blob)spot.neighbours[j]; int x2 = tx + (int)neighbour.x; int y2 = ty + (int)neighbour.y; sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, x1, y1, x2, y2, 0, 255, 0, 0, false); } } } break; } case 12: // shear angle { if (shear_angle_point != null) { int x0 = tx + (int)(shear_angle_point[0, 0]); int y0 = ty + (int)(shear_angle_point[0, 1]); int x1 = tx + (int)(shear_angle_point[1, 0]); int y1 = ty + (int)(shear_angle_point[1, 1]); int x2 = tx + (int)(shear_angle_point[2, 0]); int y2 = ty + (int)(shear_angle_point[2, 1]); sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, x0, y0, x1, y1, 0, 255, 0, 0, false); sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, x1, y1, x2, y2, 0, 255, 0, 0, false); } break; } case 13: // square/rectangle detection { /* if (square_shape != null) { int prev_x = 0; int prev_y = 0; for (int i = 0; i < square_shape.x_points.Count+1; i++) { int index = i; if (index >= square_shape.x_points.Count) index -= square_shape.x_points.Count; int x = tx + (int)square_shape.x_points[index]; int y = ty + (int)square_shape.y_points[index]; if (i > 0) sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, prev_x, prev_y, x, y, 0,255,0, 0, false); prev_x = x; prev_y = y; } } */ break; } case 14: // edges { for (int i = 0; i < bmp.Length; i++) { int v = (int)(bmp[i] / 2.5f); bmp[i] = (byte)v; } if (spot_radius > 0) { int grid_padding = 2; float grid_fitting_pixels_per_index = 1.12f; int edge_tracing_search_depth = 2; float edge_tracing_threshold = 0.24f; float suppression_radius_factor = 1.23f; ArrayList horizontal_lines = null; ArrayList vertical_lines = null; float[] grid_spacing_horizontal = null; float[] grid_spacing_vertical = null; float dominant_orientation = 0; float secondary_orientation = 0; float shear_angle_radians = 0; ArrayList horizontal_maxima = null; ArrayList vertical_maxima = null; polygon2D grid = fitGrid(ref horizontal_lines, ref vertical_lines, grid_fitting_pixels_per_index, ref dominant_orientation, ref secondary_orientation, ref grid_spacing_horizontal, ref grid_spacing_vertical, ref horizontal_maxima, ref vertical_maxima, ref shear_angle_radians, ref shear_angle_point, grid_padding, suppression_radius_factor, edge_tracing_search_depth, edge_tracing_threshold); for (int i = 0; i < vertical_lines.Count; i++) { linefeature line = (linefeature)vertical_lines[i]; float x0 = tx + line.x0; float y0 = ty + line.y0; float x1 = tx + line.x1; float y1 = ty + line.y1; sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, (int)x0, (int)y0, (int)x1, (int)y1, 255, 255, 0, 0, false); } for (int i = 0; i < horizontal_lines.Count; i++) { linefeature line = (linefeature)horizontal_lines[i]; float x0 = tx + line.x0; float y0 = ty + line.y0; float x1 = tx + line.x1; float y1 = ty + line.y1; sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, (int)x0, (int)y0, (int)x1, (int)y1, 255, 255, 0, 0, false); } float line_length = image_height / 2; float dxx = line_length * (float)Math.Sin(grid_orientation); float dyy = line_length * (float)Math.Cos(grid_orientation); float dxx2 = line_length * (float)Math.Sin(grid_orientation + shear_angle + (Math.PI / 2)); float dyy2 = line_length * (float)Math.Cos(grid_orientation + shear_angle + (Math.PI / 2)); float cx = tx + centre_x; float cy = ty + centre_y; //sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, (int)(cx + dxx), (int)(cy + dyy), (int)(cx - dxx), (int)(cy - dyy), 255, 0, 0, 0, false); //sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, (int)(cx + dxx2), (int)(cy + dyy2), (int)(cx - dxx2), (int)(cy - dyy2), 255, 255, 255, 0, false); dxx = line_length * (float)Math.Sin(grid_orientation); dyy = line_length * (float)Math.Cos(grid_orientation); //dxx2 = line_length * (float)Math.Sin(grid_orientation + shear_angle + (Math.PI / 2)); //dyy2 = line_length * (float)Math.Cos(grid_orientation + shear_angle + (Math.PI / 2)); dxx2 = line_length * (float)Math.Sin(grid_secondary_orientation); dyy2 = line_length * (float)Math.Cos(grid_secondary_orientation); cx = tx + centre_x; cy = ty + centre_y; //sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, (int)(cx + dxx), (int)(cy + dyy), (int)(cx - dxx), (int)(cy - dyy), 255, 0, 0, 0, false); //sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, (int)(cx + dxx2), (int)(cy + dyy2), (int)(cx - dxx2), (int)(cy - dyy2), 255, 255, 255, 0, false); sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, (int)(cx + dxx), (int)(cy + dyy), (int)(cx), (int)(cy), 255, 0, 0, 0, false); sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, (int)(cx + dxx2), (int)(cy + dyy2), (int)(cx), (int)(cy), 255, 255, 255, 0, false); } break; } case 15: // spatial frequency histogram { if (spatial_frequency_histogram != null) { // clear the image for (int i = 0; i < bmp.Length; i++) bmp[i] = 0; // find the maximum non zero index, so that we can scale the graph over the width of the image int max_index = 1; for (int d = 0; d < spatial_frequency_histogram.Length; d++) if (spatial_frequency_histogram[d] > 0.05f) max_index = d; max_index += 2; if (max_index >= spatial_frequency_histogram.Length) max_index = spatial_frequency_histogram.Length - 1; // draw the histogram int prev_x = 0; int prev_y = image_height - 1; for (int d = 0; d < max_index; d++) { int x = d * (image_width - 1) / max_index; int y = image_height - 1 - (int)(spatial_frequency_histogram[d] * (image_height - 1)); sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, prev_x, prev_y, x, y, 0, 255, 0, 0, false); prev_x = x; prev_y = y; } } break; } case 16: // grid spacings { for (int i = 0; i < bmp.Length; i++) bmp[i] = 0; if ((spot_radius > 0) && (grid_graph_horizontal != null)) { for (int axis = 0; axis < 2; axis++) { int prev_x = 0, prev_y = 0; int start_index = 0; int end_index = 0; float[] grid_spacing = grid_graph_horizontal; if (axis == 1) grid_spacing = grid_graph_vertical; for (int i = 0; i < grid_spacing.Length; i++) { if (grid_spacing[i] > 0) { end_index = i; if (start_index == 0) start_index = i; } i++; } if (end_index > start_index) { for (int i = 0; i < grid_spacing.Length; i++) { int x = (i - start_index) * image_width / (end_index - start_index); int y = image_height - 1 - (int)(grid_spacing[i] * ((image_height - 1) / 2)) - (image_height * (1 - axis) / 2); if (i > 0) sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, prev_x, prev_y, x, y, 0, 255, 0, 0, false); prev_x = x; prev_y = y; } } } } break; } case 17: // grid lines { if ((spot_radius > 0) && (grid_horizontal_maxima != null)) { int line_length = width * 120 / 100; float secondary_orientation = grid_secondary_orientation; // + shear_angle + (float)(Math.PI / 2); for (int axis = 0; axis < 2; axis++) { ArrayList grid_maxima = grid_horizontal_maxima; float orient = grid_orientation; if (axis == 1) { grid_maxima = grid_vertical_maxima; orient = secondary_orientation; } for (int i = 0; i < grid_maxima.Count; i++) { float r = (float)grid_maxima[i]; int x0 = tx + centre_x + (int)(r * Math.Sin(orient)); int y0 = ty + centre_y + (int)(r * Math.Cos(orient)); int dx = (int)(line_length / 2 * Math.Sin(orient + (Math.PI / 2))); int dy = (int)(line_length / 2 * Math.Cos(orient + (Math.PI / 2))); sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, x0, y0, x0 + dx, y0 + dy, 0, 255, 0, 0, false); sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, x0, y0, x0 - dx, y0 - dy, 0, 255, 0, 0, false); } } /* polygon2D cell = getGridCellPerimeter(10, 5, horizontal_maxima, vertical_maxima, dominant_orientation); cell.show(bmp, image_width, image_height, 255, 0, 0, 0, tx, ty); */ } break; } case 18: // grid non-uniformity { if (polygon != null) { int line_length = width; float secondary_orientation = grid_secondary_orientation; // + shear_angle + (float)(Math.PI / 2); for (int axis = 0; axis < 2; axis++) { ArrayList grid_maxima = grid_horizontal_maxima; float orient = grid_orientation; if (axis == 1) { grid_maxima = grid_vertical_maxima; orient = secondary_orientation; } for (int i = 0; i < grid_maxima.Count; i++) { float r = (float)grid_maxima[i]; int x0 = tx + centre_x + (int)(r * Math.Sin(orient)); int y0 = ty + centre_y + (int)(r * Math.Cos(orient)); int dx = (int)(line_length / 2 * Math.Sin(orient + (Math.PI / 2))); int dy = (int)(line_length / 2 * Math.Cos(orient + (Math.PI / 2))); sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, x0, y0, x0 + dx, y0 + dy, 255, 0, 0, 0, false); sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, x0, y0, x0 - dx, y0 - dy, 255, 0, 0, 0, false); } } if (polygon.x_points.Count == 4) { float x0 = (float)polygon.x_points[0]; float y0 = (float)polygon.y_points[0]; float x1 = (float)polygon.x_points[1]; float y1 = (float)polygon.y_points[1]; float x2 = (float)polygon.x_points[2]; float y2 = (float)polygon.y_points[2]; float x3 = (float)polygon.x_points[3]; float y3 = (float)polygon.y_points[3]; float dx_top = x1 - x0; float dy_top = y1 - y0; float dx_bottom = x2 - x3; float dy_bottom = y2 - y3; float dx_left = x3 - x0; float dy_left = y3 - y0; float dx_right = x2 - x1; float dy_right = y2 - y1; for (int grid_x = 0; grid_x < grid_columns; grid_x++) { float x_top = x0 + (grid_x * dx_top / grid_columns); float x_bottom = x3 + (grid_x * dx_bottom / grid_columns); float y_top = y0 + (grid_x * dy_top / grid_columns); float y_bottom = y3 + (grid_x * dy_bottom / grid_columns); sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, tx + (int)x_top, ty + (int)y_top, tx + (int)x_bottom, ty + (int)y_bottom, 0, 255, 0, 0, false); } for (int grid_y = 0; grid_y < grid_rows; grid_y++) { float x_left = x0 + (grid_y * dx_left / grid_rows); float x_right = x1 + (grid_y * dx_right / grid_rows); float y_left = y0 + (grid_y * dy_left / grid_rows); float y_right = y1 + (grid_y * dy_right / grid_rows); sluggish.utilities.drawing.drawLine(bmp, image_width, image_height, tx + (int)x_left, ty + (int)y_left, tx + (int)x_right, ty + (int)y_right, 0, 255, 0, 0, false); } } } break; } case 19: // corner features { if (corner_features != null) { for (int i = 0; i < corner_features.Count; i += 2) { int x = (int)corner_features[i]; int y = (int)corner_features[i + 1]; int n = ((y * image_width) + x) * 3; bmp[n] = 0; bmp[n + 1] = (byte)255; bmp[n + 2] = 0; } } break; } case 20: // show segmentation responses { if (segmented != null) { for (int x = tx; x < tx + width; x++) { for (int y = ty; y < ty + height; y++) { byte v = (byte)segmented[x - tx, y - ty]; int n = ((y * image_width) + x) * 3; for (int col = 0; col < 3; col++) bmp[n + col] = v; } } } break; } case 21: // horizontal maxima { int local_radius = 2; int inhibitory_radius = image_width / 50; int min_intensity = 500; int max_intensity = 2500; int image_threshold = 5; int localAverageRadius = 500; int difference_threshold = 35; int step_size = 2; int max_features_per_row = 9; float average_magnitude_horizontal = 0; ArrayList[] hor_maxima = image.horizontal_maxima(bmp, image_width, image_height, 3, max_features_per_row, local_radius, inhibitory_radius, min_intensity, max_intensity, image_threshold, localAverageRadius, difference_threshold, step_size, ref average_magnitude_horizontal); if (hor_maxima != null) { for (int y = 0; y < image_height; y += step_size) { int no_of_features = hor_maxima[y].Count; for (int i = 0; i < no_of_features; i += 2) { float x = (float)hor_maxima[y][i]; float magnitude = (float)hor_maxima[y][i + 1]; if (magnitude > average_magnitude_horizontal * 0.3f) { int radius = 2; int r = 0; int g = 255; int b = 0; sluggish.utilities.drawing.drawCircle(bmp, image_width, image_height, (int)x, y, radius, r, g, b, 0); } } } } float average_magnitude_vertical = 0; ArrayList[] ver_maxima = image.vertical_maxima(bmp, image_width, image_height, 3, max_features_per_row, local_radius, inhibitory_radius, min_intensity, max_intensity, image_threshold, localAverageRadius, difference_threshold, step_size, ref average_magnitude_vertical); if (ver_maxima != null) { for (int x = 0; x < image_width; x += step_size) { int no_of_features = ver_maxima[x].Count; for (int i = 0; i < no_of_features; i += 2) { float y = (float)ver_maxima[x][i]; float magnitude = (float)ver_maxima[x][i + 1]; if (magnitude > average_magnitude_vertical * 0.3f) { int radius = 2; int r = 0; int g = 255; int b = 0; sluggish.utilities.drawing.drawCircle(bmp, image_width, image_height, x, (int)y, radius, r, g, b, 0); } } } } break; } } } else sluggish.utilities.logging.EventLog.AddEvent("Can't display regions in a mono image"); }
/// <summary> /// after finding the horizontal and vertical axis of a region /// this removes any spots which are unlikely to lie inside the /// axis of a square or rectangular region /// </summary> /// <param name="spots">list of spot features</param> /// <param name="shear_angle_point">angle defining the primary axis of the region</param> /// <param name="spot_culling_threshold">the ratio of possible out of bounds spots to the total number of spots must be below this threshold in order for out of bounds cases to be removed</param> private void removeSpots(ArrayList spots, float[,] shear_angle_point, float spot_culling_threshold) { if (shear_angle_point != null) { polygon2D area_perimeter = new polygon2D(); float tx = shear_angle_point[0, 0]; float ty = shear_angle_point[0, 1]; float cx = shear_angle_point[1, 0]; float cy = shear_angle_point[1, 1]; float bx = shear_angle_point[2, 0]; float by = shear_angle_point[2, 1]; float dx1 = cx - tx; float dy1 = cy - ty; float dx2 = cx - bx; float dy2 = cy - by; float dx = dx1; if (Math.Abs(dx2) > Math.Abs(dx1)) dx = dx2; float dy = dy1; if (Math.Abs(dy2) > Math.Abs(dy1)) dy = dy2; // add a small border float x_offset = 4; float y_offset = 4; if (dx < 0) x_offset = -x_offset; if (dy < 0) y_offset = -y_offset; // create a polygon inside which the spot features are expected to lie area_perimeter.Add(tx + x_offset, ty + y_offset); area_perimeter.Add(cx + x_offset, cy + y_offset); area_perimeter.Add(bx + x_offset, by + y_offset); area_perimeter.Add(bx + (tx - cx) + x_offset, by + (ty - cy) + y_offset); // remove any spots outside of this perimeter ArrayList potential_victims = new ArrayList(); for (int i = spots.Count - 1; i >= 0; i--) { blob spot = (blob)spots[i]; if (!area_perimeter.isInside(spot.interpolated_x, spot.interpolated_y)) { // add the index of this spot to the list of potential victims <evil laughter> potential_victims.Add(i); } } if (potential_victims.Count > 0) { // what fraction of the spots are potential victims? // if this ratio is too large then perhaps we have made a dreadful mistake! float victims_ratio = potential_victims.Count / (float)spots.Count; if (victims_ratio < spot_culling_threshold) { // let the slaughter commence for (int i = 0; i < potential_victims.Count; i++) { int victim_index = (int)potential_victims[i]; spots.RemoveAt(victim_index); } } } } }
/// <summary> /// applies a perimeter inside which spots should be contained /// any spots outside of the perimeter are removed /// </summary> /// <param name="perimeter">polygon shape of the perimeter</param> public void applySpotPerimeter(polygon2D perimeter) { if (spots != null) { for (int i = spots.Count - 1; i >= 0; i--) { blob spot = (blob)spots[i]; if (!perimeter.isInside((int)spot.x, (int)spot.y)) spots.RemoveAt(i); } } }
} /// <summary> /// after finding the horizontal and vertical axis of a region /// this removes any spots which are unlikely to lie inside the /// axis of a square or rectangular region /// </summary> /// <param name="spots">list of spot features</param> /// <param name="shear_angle_point">angle defining the primary axis of the region</param> private void removeSpots(ArrayList spots, float[,] shear_angle_point) { if (shear_angle_point != null) { polygon2D area_perimeter = new polygon2D(); float tx = shear_angle_point[0, 0]; float ty = shear_angle_point[0, 1]; float cx = shear_angle_point[1, 0]; float cy = shear_angle_point[1, 1]; float bx = shear_angle_point[2, 0]; float by = shear_angle_point[2, 1]; float dx1 = cx - tx; float dy1 = cy - ty; float dx2 = cx - bx; float dy2 = cy - by; float dx = dx1; if (Math.Abs(dx2) > Math.Abs(dx1)) dx = dx2; float dy = dy1; if (Math.Abs(dy2) > Math.Abs(dy1)) dy = dy2; // add a small border float x_offset = 4; float y_offset = 4; if (dx < 0) x_offset = -x_offset; if (dy < 0) y_offset = -y_offset; // create a polygon inside which the spot features are expected to lie area_perimeter.Add(tx + x_offset, ty + y_offset); area_perimeter.Add(cx + x_offset, cy + y_offset); area_perimeter.Add(bx + x_offset, by + y_offset); area_perimeter.Add(bx + (tx - cx) + x_offset, by + (ty - cy) + y_offset); // remove any spots outside of this perimeter for (int i = spots.Count - 1; i >= 0; i--) { blob spot = (blob)spots[i]; if (!area_perimeter.isInside(spot.interpolated_x, spot.interpolated_y)) spots.RemoveAt(i); }