/// <summary> /// sets the top left or bottom right point of the region of interest /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="topLeft"></param> public void setRegionOfInterestPoint(int x, int y) { if (ROI == null) ROI = new calibration_region_of_interest(); if (y < image_height / 2) { if (x < image_width / 2) ROI.setTopLeft(x, y); else ROI.setTopRight(x, y); } else { if (x < image_width / 2) ROI.setBottomLeft(x, y); else ROI.setBottomRight(x, y); } }
public void Update(Byte[] img, int width, int height, bool alignMode) { if (img != null) { image_width = width; image_height = height; // create lists to store edges edges_horizontal = new ArrayList(); edges_vertical = new ArrayList(); edges_image = new Byte[width * height * 3]; centrealign_image = new Byte[width * height * 3]; corners_image = new Byte[width * height * 3]; lines_image = new Byte[width * height * 3]; edges_binary = new bool[width, height]; horizontal_magnitude = new int[8, width]; vertical_magnitude = new int[5, height]; if (binary_image == null) binary_image = new bool[no_of_images, width, height]; for (int i = 0; i < img.Length; i++) { lines_image[i] = img[i]; centrealign_image[i] = img[i]; edges_image[i] = img[i]; corners_image[i] = img[i]; } // show region of interest if (ROI == null) { // create a default region of interest ROI = new calibration_region_of_interest(); ROI.tx = width / 10; ROI.bx = width - ROI.tx; ROI.ty = height / 10; ROI.by = height - ROI.ty; } // show the region of interest ROI.Show(centrealign_image, width, height); // determine the separation factor used for non-maximal suppression // during edge detection //separation_factor = (int)(1.0f / GetSeparationFactor(width)); separation_factor = GetSeparationFactor(width); // image used for aligning the centre of the calibration pattern showAlignmentLines(centrealign_image, width, height); // create a mono image calibration_image = image.monoImage(img, width, height); if (!alignMode) { if (samples < min_samples) samples++; int min_magnitude = 1; clearBinaryImage(width, height); detectHorizontalEdges(calibration_image, width, height, edges_horizontal, min_magnitude); detectVerticalEdges(calibration_image, width, height, edges_vertical, min_magnitude); updateEdgesImage(width, height); // detect lines detectHorizontalLines(width, height); detectVerticalLines(width, height); float rotn = detectRotation(width, height); if (rotation == 0) rotation = rotn; else rotation = (rotation * 0.9f) + (rotn * 0.1f); // create a grid to store the edges if ((vertical_lines.Count > 0) && (horizontal_lines.Count > 0)) { // locate corners detectCorners(width, height); // hunt the centre spot grid_centre_x = 0; grid_centre_y = 0; detectCentreSpot(calibration_image, width, height, ref grid_centre_x, ref grid_centre_y); if (grid_centre_x > 0) { // detect the lens distortion detectLensDistortion(width, height, grid_centre_x, grid_centre_y); if (fitter != null) { // store the polynomial coefficients which will be used as // a basis for a more detailed search float[] C = new float[3]; C[1] = fitter.Coeff(1); C[2] = fitter.Coeff(2); // itterate a number of time trying different possible matches // the number of itterations is adjusted depending upon the size of the error int max_v = 1; if (min_RMS_error > 5) max_v = 5; //if (min_RMS_error > 10) max_v = 10; for (int v = 0; v < max_v; v++) { // add small amount of noise to the polynomial coefficients for (int c = 1; c <= 2; c++) fitter.SetCoeff(c, C[c] * (1.0f + ((((rnd.Next(2000000) / 1000000.0f) - 1.0f) * 0.01f)))); // does this equation cause the image to be re-scaled? // if it does we can explicitly detect this and correct for it later detectScale(width, height); // the rectification is only considered valid if it is roughly concave if (isValidRectification) { // update the calibration lookup updateCalibrationMap(width, height, fitter, 1.0f, rotation); float RMS_error = GetRMSerror(); if ((RMS_error < min_RMS_error) && (samples >= min_samples)) { // update the graph curve_fit = new Byte[width * height * 3]; fitter.Show(curve_fit, width, height); updateCalibrationMap(width, height, fitter, temp_scale, rotation); calibration_map = new int[width * height]; for (int i = 0; i < temp_calibration_map.Length; i++) calibration_map[i] = temp_calibration_map[i]; calibration_map_inverse = new int[width, height, 2]; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { calibration_map_inverse[x, y, 0] = temp_calibration_map_inverse[x, y, 0]; calibration_map_inverse[x, y, 1] = temp_calibration_map_inverse[x, y, 1]; } } // update the rectified position of the centre of the pattern updatePatternCentreRectified(); scale = temp_scale; best_curve = fitter; min_RMS_error = RMS_error; } } } // rectify Rectify(img, width, height); ShowRectifiedCorners(rectified_image, width, height); } } corners_index++; if (corners_index >= corners.Length) corners_index = 0; } av_centreline_x += closest_to_centreline_x; av_centreline_x_hits++; if (av_centreline_x_hits > 50) { av_centreline_x /= 2; av_centreline_x_hits /= 2; } av_centreline_y += closest_to_centreline_y; av_centreline_y_hits++; if (av_centreline_y_hits > 50) { av_centreline_y /= 2; av_centreline_y_hits /= 2; } } else { samples = 0; } binary_image_index++; if (binary_image_index >= no_of_images) binary_image_index = 0; } }