// Watershedアルゴリズムによる画像の領域分割 // パラメータ: 分割数(横), 分割数(縦), マーカサイズ private OpenCvSharp.CPlusPlus.Mat procWatershed(OpenCvSharp.CPlusPlus.Mat matSrc, int wdiv, int hdiv, int msize) { // Matの準備 OpenCvSharp.CPlusPlus.Mat matDst = matSrc.Clone(); // IplImageの準備(C API用) OpenCvSharp.IplImage iplSrc = matSrc.ToIplImage(); OpenCvSharp.IplImage iplDst = iplSrc.Clone(); // マーカ画像の準備 OpenCvSharp.IplImage iplMarker = new OpenCvSharp.IplImage(iplSrc.Size, OpenCvSharp.BitDepth.S32, 1); iplMarker.Zero(); // マーカ設置(等分割) OpenCvSharp.CvPoint[,] mpt = new OpenCvSharp.CvPoint[wdiv, hdiv]; for (int i = 0; i < wdiv; i++) { for (int j = 0; j < hdiv; j++) { mpt[i, j] = new OpenCvSharp.CvPoint((int)(iplSrc.Width / wdiv * (i + 0.5)), (int)(iplSrc.Height / hdiv * (j + 0.5))); iplMarker.Circle(mpt[i, j], msize, OpenCvSharp.CvScalar.ScalarAll(i * wdiv + j), OpenCvSharp.Cv.FILLED, OpenCvSharp.LineType.Link8, 0); } } // 分割実行 OpenCvSharp.Cv.Watershed(iplSrc, iplMarker); // マーカの描画 for (int i = 0; i < wdiv; i++) { for (int j = 0; j < hdiv; j++) { iplDst.Circle(mpt[i, j], msize, OpenCvSharp.CvColor.White, 3, OpenCvSharp.LineType.Link8, 0); } } // 領域境界の描画 for (int i = 0; i < iplMarker.Height; i++) { for (int j = 0; j < iplMarker.Width; j++) { int idx = (int)(iplMarker.Get2D(i, j).Val0); if (idx == -1) { iplDst.Set2D(i, j, OpenCvSharp.CvColor.Red); } } } // IplImage -> Matに戻す matDst = new OpenCvSharp.CPlusPlus.Mat(iplDst); return matDst; }
// 平均値シフト法による画像のセグメント化 // パラメータ: 空間窓の半径, 色空間窓の半径, セグメンテーションに用いるピラミッドの最大レベル private OpenCvSharp.CPlusPlus.Mat procPyrMeanShiftFiltering(OpenCvSharp.CPlusPlus.Mat matSrc, double sp, double sr, int level) { // 終了パラメータ OpenCvSharp.CPlusPlus.TermCriteria term = new OpenCvSharp.CPlusPlus.TermCriteria(OpenCvSharp.CriteriaType.Iteration, 5, 1); //OpenCvSharp.CPlusPlus.TermCriteria term = new OpenCvSharp.CPlusPlus.TermCriteria(OpenCvSharp.CriteriaType.Epsilon, 5, 1); // Matの準備 OpenCvSharp.CPlusPlus.Mat matDst = matSrc.Clone(); OpenCvSharp.CPlusPlus.Cv2.PyrMeanShiftFiltering(matSrc, matDst, sp, sr, level, term); return matDst; }
// 画像ピラミッドを用いた画像の領域分割 // パラメータ: ピラミッドレベル, ピクセルを接続する閾値, クラスタリングの範囲の閾値 private OpenCvSharp.CPlusPlus.Mat procPyrSegmentation(OpenCvSharp.CPlusPlus.Mat matSrc, int level, double threshold1, double threshold2) { // Matの準備 OpenCvSharp.CPlusPlus.Mat matDst = matSrc.Clone(); // IplImageの準備(C API用) OpenCvSharp.IplImage iplSrc = matSrc.ToIplImage(); OpenCvSharp.IplImage iplDst = iplSrc.Clone(); // ピラミッド画像作成のためのROI設定(2^levelで割り切れるサイズ) OpenCvSharp.CvRect roi; roi.X = 0; roi.Y = 0; roi.Width = iplSrc.Width & -(1 << level); roi.Height = iplSrc.Height & -(1 << level); iplSrc.SetROI(roi); iplDst.SetROI(roi); OpenCvSharp.Cv.PyrSegmentation(iplSrc, iplDst, level, threshold1, threshold2); // IplImage -> Matに戻す matDst = new OpenCvSharp.CPlusPlus.Mat(iplDst); return matDst; }
// 確率的Hough変換(Canny + Hough) + 統計情報 private OpenCvSharp.CPlusPlus.Mat procHoughStat(OpenCvSharp.CPlusPlus.Mat matSrc, int votes, double minLength, double maxGap) { OpenCvSharp.CPlusPlus.Mat matDst = matSrc.Clone(); OpenCvSharp.CPlusPlus.Mat matGray = new OpenCvSharp.CPlusPlus.Mat(matSrc.Rows, matSrc.Cols, OpenCvSharp.CPlusPlus.MatType.CV_8UC1); OpenCvSharp.CPlusPlus.Mat matBinary = new OpenCvSharp.CPlusPlus.Mat(matSrc.Rows, matSrc.Cols, OpenCvSharp.CPlusPlus.MatType.CV_8UC1); OpenCvSharp.CPlusPlus.Cv2.CvtColor(matSrc, matGray, OpenCvSharp.ColorConversion.BgraToGray, 1); OpenCvSharp.CPlusPlus.Cv2.Threshold(matGray, matBinary, 0, 255, OpenCvSharp.ThresholdType.Binary | OpenCvSharp.ThresholdType.Otsu); // Hough変換 double rho = 1.0; // 距離分解能 double theta = Math.PI / 180.0; // 角度分解能 OpenCvSharp.CvLineSegmentPoint[] lines = OpenCvSharp.CPlusPlus.Cv2.HoughLinesP(matBinary, rho, theta, votes, minLength, maxGap); // 描画 Random rnd = new Random(); foreach (OpenCvSharp.CvLineSegmentPoint it in lines) { //matDst.Line(it.P1, it.P2, new OpenCvSharp.CPlusPlus.Scalar(0, 0, 255), 1, OpenCvSharp.LineType.AntiAlias, 0); matDst.Line(it.P1, it.P2, new OpenCvSharp.CPlusPlus.Scalar(rnd.Next(0, 255), rnd.Next(0, 255), rnd.Next(0, 255)), 1, OpenCvSharp.LineType.AntiAlias, 0); } // 本数、平均長、最大長の計算と表示 //int divNumR = 10; //int divNumC = 10; int divSizeR = matDst.Rows / divNumR; int divSizeC = matDst.Cols / divNumC; //double[,] sum = new double[divNumR, divNumC]; //double[,] max = new double[divNumR, divNumC]; //int[,] num = new int[divNumR, divNumC]; foreach (OpenCvSharp.CvLineSegmentPoint it in lines) { double midR = (it.P1.Y + it.P2.Y) / 2; double midC = (it.P1.X + it.P2.X) / 2; double dist = it.P1.DistanceTo(it.P2); for (int r = 0; r < divNumR; r++) { for (int c = 0; c < divNumC; c++) { if (midR >= divSizeR * r && midR < divSizeR * (r + 1) && midC >= divSizeC * c && midC < divSizeC * (c + 1)) { sum[r, c] += dist; num[r, c]++; if (max[r, c] < dist) { max[r, c] = dist; } } } } } for (int r = 0; r < divNumR; r++) { matDst.Line(new OpenCvSharp.CPlusPlus.Point(0, divSizeR * r), new OpenCvSharp.CPlusPlus.Point(matDst.Cols, divSizeR * r), new OpenCvSharp.CPlusPlus.Scalar(0, 0, 255), 1, OpenCvSharp.LineType.AntiAlias, 0); for (int c = 0; c < divNumC; c++) { matDst.Line(new OpenCvSharp.CPlusPlus.Point(divSizeC * c, 0), new OpenCvSharp.CPlusPlus.Point(divSizeC * c, matDst.Cols), new OpenCvSharp.CPlusPlus.Scalar(0, 0, 255), 1, OpenCvSharp.LineType.AntiAlias, 0); if (num[r, c] > 0) { OpenCvSharp.CPlusPlus.Cv2.PutText(matDst, num[r, c].ToString(), new OpenCvSharp.CPlusPlus.Point(10 + divSizeC * c, 20 + divSizeR * r), OpenCvSharp.FontFace.HersheySimplex, 0.5, new OpenCvSharp.CPlusPlus.Scalar(0, 0, 255), 2, OpenCvSharp.LineType.AntiAlias); OpenCvSharp.CPlusPlus.Cv2.PutText(matDst, (sum[r, c] / num[r, c]).ToString("F2"), new OpenCvSharp.CPlusPlus.Point(10 + divSizeC * c, 40 + divSizeR * r), OpenCvSharp.FontFace.HersheySimplex, 0.5, new OpenCvSharp.CPlusPlus.Scalar(0, 0, 255), 2, OpenCvSharp.LineType.AntiAlias); OpenCvSharp.CPlusPlus.Cv2.PutText(matDst, max[r, c].ToString("F2"), new OpenCvSharp.CPlusPlus.Point(10 + divSizeC * c, 60 + divSizeR * r), OpenCvSharp.FontFace.HersheySimplex, 0.5, new OpenCvSharp.CPlusPlus.Scalar(0, 0, 255), 2, OpenCvSharp.LineType.AntiAlias); } } } return matDst; }
// 確率的Hough変換(Canny + Hough) private OpenCvSharp.CPlusPlus.Mat procHough(OpenCvSharp.CPlusPlus.Mat matSrc, int votes, double minLength, double maxGap) { OpenCvSharp.CPlusPlus.Mat matDst = matSrc.Clone(); OpenCvSharp.CPlusPlus.Mat matCanny = new OpenCvSharp.CPlusPlus.Mat(matSrc.Rows, matSrc.Cols, OpenCvSharp.CPlusPlus.MatType.CV_8UC1); OpenCvSharp.CPlusPlus.Cv2.Canny(matSrc, matCanny, 100, 200, 3); // Hough変換 double rho = 1.0; // 距離分解能 double theta = Math.PI / 180.0; // 角度分解能 OpenCvSharp.CvLineSegmentPoint[] lines = OpenCvSharp.CPlusPlus.Cv2.HoughLinesP(matCanny, rho, theta, votes, minLength, maxGap); // 描画 Random rnd = new Random(); foreach (OpenCvSharp.CvLineSegmentPoint it in lines) { //matDst.Line(it.P1, it.P2, new OpenCvSharp.CPlusPlus.Scalar(0, 0, 255), 1, OpenCvSharp.LineType.AntiAlias, 0); matDst.Line(it.P1, it.P2, new OpenCvSharp.CPlusPlus.Scalar(rnd.Next(0, 255), rnd.Next(0, 255), rnd.Next(0, 255)), 1, OpenCvSharp.LineType.AntiAlias, 0); } return matDst; }
// グレースケール化 private OpenCvSharp.CPlusPlus.Mat procGrayScale(OpenCvSharp.CPlusPlus.Mat matSrc) { OpenCvSharp.CPlusPlus.Mat matDst = matSrc.Clone(); OpenCvSharp.CPlusPlus.Mat matGray = new OpenCvSharp.CPlusPlus.Mat(matSrc.Rows, matSrc.Cols, OpenCvSharp.CPlusPlus.MatType.CV_8UC1); OpenCvSharp.CPlusPlus.Cv2.CvtColor(matSrc, matGray, OpenCvSharp.ColorConversion.BgraToGray, 1); OpenCvSharp.CPlusPlus.Cv2.CvtColor(matGray, matDst, OpenCvSharp.ColorConversion.GrayToBgra, 3); return matDst; }
// エッジ抽出(Canny) private OpenCvSharp.CPlusPlus.Mat procCanny(OpenCvSharp.CPlusPlus.Mat matSrc, double threshold1, double threshold2, int apertureSize) { OpenCvSharp.CPlusPlus.Mat matDst = matSrc.Clone(); OpenCvSharp.CPlusPlus.Mat matCanny = new OpenCvSharp.CPlusPlus.Mat(matSrc.Rows, matSrc.Cols, OpenCvSharp.CPlusPlus.MatType.CV_8UC1); OpenCvSharp.CPlusPlus.Cv2.Canny(matSrc, matCanny, threshold1, threshold2, apertureSize); OpenCvSharp.CPlusPlus.Cv2.CvtColor(matCanny, matDst, OpenCvSharp.ColorConversion.GrayToBgra, 3); return matDst; }
// 2値化(グレースケール化 + 2値化) private OpenCvSharp.CPlusPlus.Mat procBinary(OpenCvSharp.CPlusPlus.Mat matSrc) { OpenCvSharp.CPlusPlus.Mat matDst = matSrc.Clone(); OpenCvSharp.CPlusPlus.Mat matGray = new OpenCvSharp.CPlusPlus.Mat(matSrc.Rows, matSrc.Cols, OpenCvSharp.CPlusPlus.MatType.CV_8UC1); OpenCvSharp.CPlusPlus.Mat matBinary = new OpenCvSharp.CPlusPlus.Mat(matSrc.Rows, matSrc.Cols, OpenCvSharp.CPlusPlus.MatType.CV_8UC1); OpenCvSharp.CPlusPlus.Cv2.CvtColor(matSrc, matGray, OpenCvSharp.ColorConversion.BgraToGray, 1); OpenCvSharp.CPlusPlus.Cv2.Threshold(matGray, matBinary, 0, 255, OpenCvSharp.ThresholdType.Binary | OpenCvSharp.ThresholdType.Otsu); OpenCvSharp.CPlusPlus.Cv2.CvtColor(matBinary, matDst, OpenCvSharp.ColorConversion.GrayToBgra, 3); return matDst; }