//Find outer defect static void FindContour_and_outer_defect(Mat img, List <Point[]> contours_final, ref int nLabels, out int [,] stats, string mode) { // variable OpenCvSharp.Point[][] temp = new Point[1][]; //0: 內圈 ; 1: 外圈 OpenCvSharp.Point[] contour_now; if (mode == "inner") { contour_now = contours_final[0]; } else { contour_now = contours_final[1]; } // Convex hull var ellipsecontour = Cv2.FitEllipse(contour_now); Mat convex_mask_img = Mat.Zeros(img.Size(), MatType.CV_8UC1); Cv2.Ellipse(convex_mask_img, ellipsecontour, 255, -1); // Contour temp[0] = contour_now; Mat contour_mask_img = Mat.Zeros(img.Size(), MatType.CV_8UC1); Cv2.DrawContours(contour_mask_img, temp, -1, 255, -1); Mat diff_image = contour_mask_img ^ convex_mask_img; //Opening Mat kernel = Mat.Ones(4, 4, MatType.CV_8UC1);//改變凹角大小 diff_image = diff_image.MorphologyEx(MorphTypes.Open, kernel); //=========================吃掉邊界======================================= //temp[0] = contour_now; //Cv2.DrawContours(diff_image, temp, -1, 0, 3); //================================================================ convex_mask_img.SaveImage("./" + mode + "convex" + ".jpg"); contour_mask_img.SaveImage("./" + mode + "contour" + ".jpg"); diff_image.SaveImage("./" + mode + "mask" + ".jpg"); //Connected Component var labelMat = new MatOfInt(); var statsMat = new MatOfInt();// Row: number of labels Column: 5 var centroidsMat = new MatOfDouble(); nLabels = Cv2.ConnectedComponentsWithStats(diff_image, labelMat, statsMat, centroidsMat); var labels = labelMat.ToRectangularArray(); stats = statsMat.ToRectangularArray(); var centroids = centroidsMat.ToRectangularArray(); }
/// <summary> /// converts rotation matrix to rotation vector using Rodrigues transformation /// </summary> /// <param name="matrix">Input rotation matrix (3x3).</param> /// <param name="vector">Output rotation vector (3x1).</param> /// <param name="jacobian">Optional output Jacobian matrix, 3x9, which is a matrix of partial derivatives of the output array components with respect to the input array components.</param> public static void Rodrigues(double[,] matrix, out double[] vector, out double[,] jacobian) { if (matrix == null) throw new ArgumentNullException("matrix"); if (matrix.GetLength(0) != 3 || matrix.GetLength(1) != 3) throw new ArgumentException("matrix must be double[3,3]"); using (var matrixM = new Mat(3, 3, MatType.CV_64FC1, matrix)) using (var vectorM = new MatOfDouble()) using (var jacobianM = new MatOfDouble()) { NativeMethods.calib3d_Rodrigues_MatToVec(matrixM.CvPtr, vectorM.CvPtr, jacobianM.CvPtr); vector = vectorM.ToArray(); jacobian = jacobianM.ToRectangularArray(); } }
/// <summary> /// converts rotation vector to rotation matrix using Rodrigues transformation /// </summary> /// <param name="vector">Input rotation vector (3x1).</param> /// <param name="matrix">Output rotation matrix (3x3).</param> /// <param name="jacobian">Optional output Jacobian matrix, 3x9, which is a matrix of partial derivatives of the output array components with respect to the input array components.</param> public static void Rodrigues(double[] vector, out double[,] matrix, out double[,] jacobian) { if (vector == null) throw new ArgumentNullException("vector"); if (vector.Length != 3) throw new ArgumentException("vector.Length != 3"); using (var vectorM = new Mat(3, 1, MatType.CV_64FC1, vector)) using (var matrixM = new MatOfDouble()) using (var jacobianM = new MatOfDouble()) { NativeMethods.calib3d_Rodrigues_VecToMat(vectorM.CvPtr, matrixM.CvPtr, jacobianM.CvPtr); matrix = matrixM.ToRectangularArray(); jacobian = jacobianM.ToRectangularArray(); } }
/// <summary> /// projects points from the model coordinate space to the image coordinates. /// Also computes derivatives of the image coordinates w.r.t the intrinsic /// and extrinsic camera parameters /// </summary> /// <param name="objectPoints">Array of object points, 3xN/Nx3 1-channel or /// 1xN/Nx1 3-channel, where N is the number of points in the view.</param> /// <param name="rvec">Rotation vector (3x1).</param> /// <param name="tvec">Translation vector (3x1).</param> /// <param name="cameraMatrix">Camera matrix (3x3)</param> /// <param name="distCoeffs">Input vector of distortion coefficients /// (k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6]]) of 4, 5, or 8 elements. /// If the vector is null, the zero distortion coefficients are assumed.</param> /// <param name="imagePoints">Output array of image points, 2xN/Nx2 1-channel /// or 1xN/Nx1 2-channel</param> /// <param name="jacobian">Optional output 2Nx(10 + numDistCoeffs) jacobian matrix /// of derivatives of image points with respect to components of the rotation vector, /// translation vector, focal lengths, coordinates of the principal point and /// the distortion coefficients. In the old interface different components of /// the jacobian are returned via different output parameters.</param> /// <param name="aspectRatio">Optional “fixed aspect ratio” parameter. /// If the parameter is not 0, the function assumes that the aspect ratio (fx/fy) /// is fixed and correspondingly adjusts the jacobian matrix.</param> public static void ProjectPoints(IEnumerable<Point3d> objectPoints, double[] rvec, double[] tvec, double[,] cameraMatrix, double[] distCoeffs, out Point2d[] imagePoints, out double[,] jacobian, double aspectRatio = 0) { if (objectPoints == null) throw new ArgumentNullException("objectPoints"); if (rvec == null) throw new ArgumentNullException("rvec"); if (rvec.Length != 3) throw new ArgumentException("rvec.Length != 3"); if (tvec == null) throw new ArgumentNullException("tvec"); if (tvec.Length != 3) throw new ArgumentException("tvec.Length != 3"); if (cameraMatrix == null) throw new ArgumentNullException("cameraMatrix"); if (cameraMatrix.GetLength(0) != 3 || cameraMatrix.GetLength(1) != 3) throw new ArgumentException("cameraMatrix must be double[3,3]"); Point3d[] objectPointsArray = EnumerableEx.ToArray(objectPoints); using (var objectPointsM = new Mat(objectPointsArray.Length, 1, MatType.CV_64FC3, objectPointsArray)) using (var rvecM = new Mat(3, 1, MatType.CV_64FC1, rvec)) using (var tvecM = new Mat(3, 1, MatType.CV_64FC1, tvec)) using (var cameraMatrixM = new Mat(3, 3, MatType.CV_64FC1, cameraMatrix)) using (var imagePointsM = new MatOfPoint2d()) { var distCoeffsM = new Mat(); if (distCoeffs != null) distCoeffsM = new Mat(distCoeffs.Length, 1, MatType.CV_64FC1, distCoeffs); var jacobianM = new MatOfDouble(); NativeMethods.calib3d_projectPoints_Mat(objectPointsM.CvPtr, rvecM.CvPtr, tvecM.CvPtr, cameraMatrixM.CvPtr, distCoeffsM.CvPtr, imagePointsM.CvPtr, jacobianM.CvPtr, aspectRatio); imagePoints = imagePointsM.ToArray(); jacobian = jacobianM.ToRectangularArray(); } }
/// <summary> /// composes 2 [R|t] transformations together. Also computes the derivatives of the result w.r.t the arguments /// </summary> /// <param name="rvec1">First rotation vector.</param> /// <param name="tvec1">First translation vector.</param> /// <param name="rvec2">Second rotation vector.</param> /// <param name="tvec2">Second translation vector.</param> /// <param name="rvec3">Output rotation vector of the superposition.</param> /// <param name="tvec3">Output translation vector of the superposition.</param> /// <param name="dr3dr1">Optional output derivatives of rvec3 or tvec3 with regard to rvec1, rvec2, tvec1 and tvec2, respectively.</param> /// <param name="dr3dt1">Optional output derivatives of rvec3 or tvec3 with regard to rvec1, rvec2, tvec1 and tvec2, respectively.</param> /// <param name="dr3dr2">Optional output derivatives of rvec3 or tvec3 with regard to rvec1, rvec2, tvec1 and tvec2, respectively.</param> /// <param name="dr3dt2">Optional output derivatives of rvec3 or tvec3 with regard to rvec1, rvec2, tvec1 and tvec2, respectively.</param> /// <param name="dt3dr1">Optional output derivatives of rvec3 or tvec3 with regard to rvec1, rvec2, tvec1 and tvec2, respectively.</param> /// <param name="dt3dt1">Optional output derivatives of rvec3 or tvec3 with regard to rvec1, rvec2, tvec1 and tvec2, respectively.</param> /// <param name="dt3dr2">Optional output derivatives of rvec3 or tvec3 with regard to rvec1, rvec2, tvec1 and tvec2, respectively.</param> /// <param name="dt3dt2">Optional output derivatives of rvec3 or tvec3 with regard to rvec1, rvec2, tvec1 and tvec2, respectively.</param> public static void ComposeRT(double[] rvec1, double[] tvec1, double[] rvec2, double[] tvec2, out double[] rvec3, out double[] tvec3, out double[,] dr3dr1, out double[,] dr3dt1, out double[,] dr3dr2, out double[,] dr3dt2, out double[,] dt3dr1, out double[,] dt3dt1, out double[,] dt3dr2, out double[,] dt3dt2) { if (rvec1 == null) throw new ArgumentNullException("rvec1"); if (tvec1 == null) throw new ArgumentNullException("tvec1"); if (rvec2 == null) throw new ArgumentNullException("rvec2"); if (tvec2 == null) throw new ArgumentNullException("tvec2"); using (var rvec1M = new Mat(3, 1, MatType.CV_64FC1, rvec1)) using (var tvec1M = new Mat(3, 1, MatType.CV_64FC1, tvec1)) using (var rvec2M = new Mat(3, 1, MatType.CV_64FC1, rvec2)) using (var tvec2M = new Mat(3, 1, MatType.CV_64FC1, tvec2)) using (var rvec3M = new MatOfDouble()) using (var tvec3M = new MatOfDouble()) using (var dr3dr1M = new MatOfDouble()) using (var dr3dt1M = new MatOfDouble()) using (var dr3dr2M = new MatOfDouble()) using (var dr3dt2M = new MatOfDouble()) using (var dt3dr1M = new MatOfDouble()) using (var dt3dt1M = new MatOfDouble()) using (var dt3dr2M = new MatOfDouble()) using (var dt3dt2M = new MatOfDouble()) { NativeMethods.calib3d_composeRT_Mat(rvec1M.CvPtr, tvec1M.CvPtr, rvec2M.CvPtr, tvec2M.CvPtr, rvec3M.CvPtr, tvec3M.CvPtr, dr3dr1M.CvPtr, dr3dt1M.CvPtr, dr3dr2M.CvPtr, dr3dt2M.CvPtr, dt3dr1M.CvPtr, dt3dt1M.CvPtr, dt3dr2M.CvPtr, dt3dt2M.CvPtr); rvec3 = rvec3M.ToArray(); tvec3 = tvec3M.ToArray(); dr3dr1 = dr3dr1M.ToRectangularArray(); dr3dt1 = dr3dt1M.ToRectangularArray(); dr3dr2 = dr3dr2M.ToRectangularArray(); dr3dt2 = dr3dt2M.ToRectangularArray(); dt3dr1 = dt3dr1M.ToRectangularArray(); dt3dt1 = dt3dt1M.ToRectangularArray(); dt3dr2 = dt3dr2M.ToRectangularArray(); dt3dt2 = dt3dt2M.ToRectangularArray(); } }
/// <summary> /// Decomposes the projection matrix into camera matrix and the rotation martix and the translation vector /// </summary> /// <param name="projMatrix">3x4 input projection matrix P.</param> /// <param name="cameraMatrix">Output 3x3 camera matrix K.</param> /// <param name="rotMatrix">Output 3x3 external rotation matrix R.</param> /// <param name="transVect">Output 4x1 translation vector T.</param> /// <param name="rotMatrixX">Optional 3x3 rotation matrix around x-axis.</param> /// <param name="rotMatrixY">Optional 3x3 rotation matrix around y-axis.</param> /// <param name="rotMatrixZ">Optional 3x3 rotation matrix around z-axis.</param> /// <param name="eulerAngles">ptional three-element vector containing three Euler angles of rotation in degrees.</param> public static void DecomposeProjectionMatrix(double[,] projMatrix, out double[,] cameraMatrix, out double[,] rotMatrix, out double[] transVect, out double[,] rotMatrixX, out double[,] rotMatrixY, out double[,] rotMatrixZ, out double[] eulerAngles) { if (projMatrix == null) throw new ArgumentNullException("projMatrix"); int dim0 = projMatrix.GetLength(0); int dim1 = projMatrix.GetLength(1); if (!((dim0 == 3 && dim1 == 4) || (dim0 == 4 && dim1 == 3))) throw new ArgumentException("projMatrix must be double[3,4] or double[4,3]"); using (var projMatrixM = new Mat(3, 4, MatType.CV_64FC1, projMatrix)) using (var cameraMatrixM = new MatOfDouble()) using (var rotMatrixM = new MatOfDouble()) using (var transVectM = new MatOfDouble()) using (var rotMatrixXM = new MatOfDouble()) using (var rotMatrixYM = new MatOfDouble()) using (var rotMatrixZM = new MatOfDouble()) using (var eulerAnglesM = new MatOfDouble()) { NativeMethods.calib3d_decomposeProjectionMatrix_Mat( projMatrixM.CvPtr, cameraMatrixM.CvPtr, rotMatrixM.CvPtr, transVectM.CvPtr, rotMatrixXM.CvPtr, rotMatrixYM.CvPtr, rotMatrixZM.CvPtr, eulerAnglesM.CvPtr); cameraMatrix = cameraMatrixM.ToRectangularArray(); rotMatrix = rotMatrixM.ToRectangularArray(); transVect = transVectM.ToArray(); rotMatrixX = rotMatrixXM.ToRectangularArray(); rotMatrixY = rotMatrixYM.ToRectangularArray(); rotMatrixZ = rotMatrixZM.ToRectangularArray(); eulerAngles = eulerAnglesM.ToArray(); } }
/// <summary> /// Computes RQ decomposition of 3x3 matrix /// </summary> /// <param name="src">3x3 input matrix.</param> /// <param name="mtxR">Output 3x3 upper-triangular matrix.</param> /// <param name="mtxQ"> Output 3x3 orthogonal matrix.</param> /// <param name="qx">Optional output 3x3 rotation matrix around x-axis.</param> /// <param name="qy">Optional output 3x3 rotation matrix around y-axis.</param> /// <param name="qz">Optional output 3x3 rotation matrix around z-axis.</param> /// <returns></returns> public static Vec3d RQDecomp3x3(double[,] src, out double[,] mtxR, out double[,] mtxQ, out double[,] qx, out double[,] qy, out double[,] qz) { if (src == null) throw new ArgumentNullException("src"); if (src.GetLength(0) != 3 || src.GetLength(1) != 3) throw new ArgumentException("src must be double[3,3]"); using (var srcM = new Mat(3, 3, MatType.CV_64FC1)) using (var mtxRM = new MatOfDouble()) using (var mtxQM = new MatOfDouble()) using (var qxM = new MatOfDouble()) using (var qyM = new MatOfDouble()) using (var qzM = new MatOfDouble()) { Vec3d ret; NativeMethods.calib3d_RQDecomp3x3_Mat(srcM.CvPtr, mtxRM.CvPtr, mtxQM.CvPtr, qxM.CvPtr, qyM.CvPtr, qzM.CvPtr, out ret); mtxR = mtxRM.ToRectangularArray(); mtxQ = mtxQM.ToRectangularArray(); qx = qxM.ToRectangularArray(); qy = qyM.ToRectangularArray(); qz = qzM.ToRectangularArray(); return ret; } }
/// <summary> /// computes the connected components labeled image of boolean image. /// image with 4 or 8 way connectivity - returns N, the total number of labels [0, N-1] where 0 /// represents the background label. ltype specifies the output label image type, an important /// consideration based on the total number of labels or alternatively the total number of /// pixels in the source image. /// </summary> /// <param name="image">the image to be labeled</param> /// <param name="connectivity">8 or 4 for 8-way or 4-way connectivity respectively</param> /// <returns></returns> public static ConnectedComponents ConnectedComponentsEx( InputArray image, PixelConnectivity connectivity = PixelConnectivity.Connectivity8) { using (var labelsMat = new MatOfInt()) using (var statsMat = new MatOfInt()) using (var centroidsMat = new MatOfDouble()) { int nLabels = ConnectedComponentsWithStats( image, labelsMat, statsMat, centroidsMat, connectivity, MatType.CV_32S); var labels = labelsMat.ToRectangularArray(); var stats = statsMat.ToRectangularArray(); var centroids = centroidsMat.ToRectangularArray(); var blobs = new ConnectedComponents.Blob[nLabels]; for (int i = 0; i < nLabels; i++) { blobs[i] = new ConnectedComponents.Blob { Label = i, Left = stats[i, 0], Top = stats[i, 1], Width = stats[i, 2], Height = stats[i, 3], Area = stats[i, 4], Centroid = new Point2d(centroids[i, 0], centroids[i, 1]), }; } return new ConnectedComponents(blobs, labels, nLabels); } }