public Snake() { using (IplImage src = new IplImage(Const.ImageCake, LoadMode.GrayScale)) using (IplImage dst = new IplImage(src.Size, BitDepth.U8, 3)) { CvPoint[] contour = new CvPoint[100]; CvPoint center = new CvPoint(src.Width / 2, src.Height / 2); for (int i = 0; i < contour.Length; i++) { contour[i].X = (int)(center.X * Math.Cos(2 * Math.PI * i / contour.Length) + center.X); contour[i].Y = (int)(center.Y * Math.Sin(2 * Math.PI * i / contour.Length) + center.Y); } Console.WriteLine("Press any key to snake\nEsc - quit"); using (CvWindow w = new CvWindow()) { while (true) { src.SnakeImage(contour, 0.45f, 0.35f, 0.2f, new CvSize(15, 15), new CvTermCriteria(1), true); src.CvtColor(dst, ColorConversion.GrayToRgb); for (int i = 0; i < contour.Length - 1; i++) { dst.Line(contour[i], contour[i + 1], new CvColor(255, 0, 0), 2); } dst.Line(contour[contour.Length - 1], contour[0], new CvColor(255, 0, 0), 2); w.Image = dst; int key = CvWindow.WaitKey(); if (key == 27) { break; } } } } }
public Contour() { // cvContourArea, cvArcLength // 輪郭によって区切られた領域の面積と,輪郭の長さを求める const int SIZE = 500; // (1)画像を確保し初期化する using (CvMemStorage storage = new CvMemStorage()) using (IplImage img = new IplImage(SIZE, SIZE, BitDepth.U8, 3)) { img.Zero(); // (2)点列を生成する CvSeq<CvPoint> points = new CvSeq<CvPoint>(SeqType.PolyLine, storage); CvRNG rng = new CvRNG((ulong)DateTime.Now.Ticks); double scale = rng.RandReal() + 0.5; CvPoint pt0 = new CvPoint { X = (int)(Math.Cos(0) * SIZE / 4 * scale + SIZE / 2), Y = (int)(Math.Sin(0) * SIZE / 4 * scale + SIZE / 2) }; img.Circle(pt0, 2, CvColor.Green); points.Push(pt0); for (int i = 1; i < 20; i++) { scale = rng.RandReal() + 0.5; CvPoint pt1 = new CvPoint { X = (int)(Math.Cos(i * 2 * Math.PI / 20) * SIZE / 4 * scale + SIZE / 2), Y = (int)(Math.Sin(i * 2 * Math.PI / 20) * SIZE / 4 * scale + SIZE / 2) }; img.Line(pt0, pt1, CvColor.Green, 2); pt0.X = pt1.X; pt0.Y = pt1.Y; img.Circle(pt0, 3, CvColor.Green, Cv.FILLED); points.Push(pt0); } img.Line(pt0, points.GetSeqElem(0).Value, CvColor.Green, 2); // (3)包含矩形,面積,長さを求める CvRect rect = points.BoundingRect(false); double area = points.ContourArea(); double length = points.ArcLength(CvSlice.WholeSeq, 1); // (4)結果を画像に書き込む img.Rectangle(new CvPoint(rect.X, rect.Y), new CvPoint(rect.X + rect.Width, rect.Y + rect.Height), CvColor.Red, 2); string text_area = string.Format("Area: wrect={0}, contour={1}", rect.Width * rect.Height, area); string text_length = string.Format("Length: rect={0}, contour={1}", 2 * (rect.Width + rect.Height), length); using (CvFont font = new CvFont(FontFace.HersheySimplex, 0.7, 0.7, 0, 1, LineType.AntiAlias)) { img.PutText(text_area, new CvPoint(10, img.Height - 30), font, CvColor.White); img.PutText(text_length, new CvPoint(10, img.Height - 10), font, CvColor.White); } // (5)画像を表示,キーが押されたときに終了 using (CvWindow window = new CvWindow("BoundingRect", WindowMode.AutoSize)) { window.Image = img; CvWindow.WaitKey(0); } } }
public FitLine() { CvSize imageSize = new CvSize(500, 500); // cvFitLine CvPoint2D32f[] points = GetRandomPoints(20, imageSize); CvLine2D line = Cv.FitLine2D(points, DistanceType.L2, 0, 0.01, 0.01); using (IplImage img = new IplImage(imageSize, BitDepth.U8, 3)) { img.Zero(); // draw line { CvPoint pt1, pt2; line.FitSize(img.Width, img.Height, out pt1, out pt2); img.Line(pt1, pt2, CvColor.Green, 1, LineType.Link8); } // draw points and distances using (CvFont font = new CvFont(FontFace.HersheySimplex, 0.33, 0.33)) { foreach (CvPoint2D32f p in points) { double d = line.Distance(p); img.Circle(p, 2, CvColor.White, -1, LineType.AntiAlias); img.PutText(string.Format("{0:F1}", d), new CvPoint((int) (p.X + 3), (int) (p.Y + 3)), font, CvColor.Green); } } CvWindow.ShowImages(img); } }
public TreeNodeIterator() { using (CvMemStorage storage = new CvMemStorage(0)) using (IplImage srcImg = new IplImage(Const.ImageLenna, LoadMode.Color)) using (IplImage srcImgGray = new IplImage(srcImg.Size, BitDepth.U8, 1)) using (IplImage tmpImg = new IplImage(srcImg.Size, BitDepth.U8, 1)) { Cv.CvtColor(srcImg, srcImgGray, ColorConversion.BgrToGray); // (1)画像の二値化と輪郭の検出 Cv.Threshold(srcImgGray, tmpImg, 120, 255, ThresholdType.Binary); CvSeq<CvPoint> contours; Cv.FindContours(tmpImg, storage, out contours, CvContour.SizeOf, ContourRetrieval.Tree, ContourChain.ApproxSimple); /* 輪郭シーケンスから座標を取得 */ using (CvFileStorage fs = new CvFileStorage("contours.yaml", null, FileStorageMode.Write)) { // (2)ツリーノードイテレータの初期化 CvTreeNodeIterator<CvSeq<CvPoint>> it = new CvTreeNodeIterator<CvSeq<CvPoint>>(contours, 1); // (3)各ノード(輪郭)を走査 //CvSeq<CvPoint> contour; //while ((contour = it.NextTreeNode()) != null) foreach(CvSeq<CvPoint> contour in it) { fs.StartWriteStruct("contour", NodeType.Seq); // (4)輪郭を構成する頂点座標を取得 CvPoint tmp = contour[-1].Value; for (int i = 0; i < contour.Total; i++) { CvPoint point = contour[i].Value; srcImg.Line(tmp, point, CvColor.Blue, 2); fs.StartWriteStruct(null, NodeType.Map | NodeType.Flow); fs.WriteInt("x", point.X); fs.WriteInt("y", point.Y); fs.EndWriteStruct(); tmp = point; } fs.EndWriteStruct(); } } Console.WriteLine(File.ReadAllText("contours.yaml")); using (new CvWindow("Contours", srcImg)) { Cv.WaitKey(0); } } }
public SVM() { // CvSVM // SVMを利用して2次元ベクトルの3クラス分類問題を解く const int S = 1000; const int SIZE = 400; CvRNG rng = new CvRNG((ulong)DateTime.Now.Ticks); // (1)画像領域の確保と初期化 using (IplImage img = new IplImage(SIZE, SIZE, BitDepth.U8, 3)) { img.Zero(); // (2)学習データの生成 CvPoint[] pts = new CvPoint[S]; int[] res = new int[S]; for (int i = 0; i < S; i++) { pts[i].X = (int)(rng.RandInt() % SIZE); pts[i].Y = (int)(rng.RandInt() % SIZE); if (pts[i].Y > 50 * Math.Cos(pts[i].X * Cv.PI / 100) + 200) { img.Line(new CvPoint(pts[i].X - 2, pts[i].Y - 2), new CvPoint(pts[i].X + 2, pts[i].Y + 2), new CvColor(255, 0, 0)); img.Line(new CvPoint(pts[i].X + 2, pts[i].Y - 2), new CvPoint(pts[i].X - 2, pts[i].Y + 2), new CvColor(255, 0, 0)); res[i] = 1; } else { if (pts[i].X > 200) { img.Line(new CvPoint(pts[i].X - 2, pts[i].Y - 2), new CvPoint(pts[i].X + 2, pts[i].Y + 2), new CvColor(0, 255, 0)); img.Line(new CvPoint(pts[i].X + 2, pts[i].Y - 2), new CvPoint(pts[i].X - 2, pts[i].Y + 2), new CvColor(0, 255, 0)); res[i] = 2; } else { img.Line(new CvPoint(pts[i].X - 2, pts[i].Y - 2), new CvPoint(pts[i].X + 2, pts[i].Y + 2), new CvColor(0, 0, 255)); img.Line(new CvPoint(pts[i].X + 2, pts[i].Y - 2), new CvPoint(pts[i].X - 2, pts[i].Y + 2), new CvColor(0, 0, 255)); res[i] = 3; } } } // (3)学習データの表示 Cv.NamedWindow("SVM", WindowMode.AutoSize); Cv.ShowImage("SVM", img); Cv.WaitKey(0); // (4)学習パラメータの生成 float[] data = new float[S * 2]; for (int i = 0; i < S; i++) { data[i * 2] = ((float)pts[i].X) / SIZE; data[i * 2 + 1] = ((float)pts[i].Y) / SIZE; } // (5)SVMの学習 using (CvSVM svm = new CvSVM()) { CvMat data_mat = new CvMat(S, 2, MatrixType.F32C1, data); CvMat res_mat = new CvMat(S, 1, MatrixType.S32C1, res); CvTermCriteria criteria = new CvTermCriteria(1000, float.Epsilon); CvSVMParams param = new CvSVMParams(SVMType.CSvc, SVMKernelType.Rbf, 10.0, 8.0, 1.0, 10.0, 0.5, 0.1, null, criteria); svm.Train(data_mat, res_mat, null, null, param); // (6)学習結果の描画 for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) { float[] a = { (float)j / SIZE, (float)i / SIZE }; CvMat m = new CvMat(1, 2, MatrixType.F32C1, a); float ret = svm.Predict(m); CvColor color = new CvColor(); switch ((int)ret) { case 1: color = new CvColor(100, 0, 0); break; case 2: color = new CvColor(0, 100, 0); break; case 3: color = new CvColor(0, 0, 100); break; } img[i, j] = color; } } // (7)トレーニングデータの再描画 for (int i = 0; i < S; i++) { CvColor color = new CvColor(); switch (res[i]) { case 1: color = new CvColor(255, 0, 0); break; case 2: color = new CvColor(0, 255, 0); break; case 3: color = new CvColor(0, 0, 255); break; } img.Line(new CvPoint(pts[i].X - 2, pts[i].Y - 2), new CvPoint(pts[i].X + 2, pts[i].Y + 2), color); img.Line(new CvPoint(pts[i].X + 2, pts[i].Y - 2), new CvPoint(pts[i].X - 2, pts[i].Y + 2), color); } // (8)サポートベクターの描画 int sv_num = svm.GetSupportVectorCount(); for (int i = 0; i < sv_num; i++) { var support = svm.GetSupportVector(i); img.Circle(new CvPoint((int)(support[0] * SIZE), (int)(support[1] * SIZE)), 5, new CvColor(200, 200, 200)); } // (9)画像の表示 Cv.NamedWindow("SVM", WindowMode.AutoSize); Cv.ShowImage("SVM", img); Cv.WaitKey(0); Cv.DestroyWindow("SVM"); } } }
/// <summary> /// sample of C style wrapper /// </summary> private void SampleC() { // cvHoughLines2 using (IplImage srcImgGray = new IplImage(FilePath.Image.Goryokaku, LoadMode.GrayScale)) using (IplImage srcImgStd = new IplImage(FilePath.Image.Goryokaku, LoadMode.Color)) using (IplImage srcImgProb = srcImgStd.Clone()) { Cv.Canny(srcImgGray, srcImgGray, 50, 200, ApertureSize.Size3); using (CvMemStorage storage = new CvMemStorage()) { // Standard algorithm CvSeq lines = srcImgGray.HoughLines2(storage, HoughLinesMethod.Standard, 1, Math.PI / 180, 50, 0, 0); // wrapper style //CvLineSegmentPolar[] lines = src_img_gray.HoughLinesStandard(1, Math.PI / 180, 50, 0, 0); int limit = Math.Min(lines.Total, 10); for (int i = 0; i < limit; i++) { // native code style /* unsafe { float* line = (float*)lines.GetElem<IntPtr>(i).Value.ToPointer(); float rho = line[0]; float theta = line[1]; } //*/ // wrapper style CvLineSegmentPolar elem = lines.GetSeqElem<CvLineSegmentPolar>(i).Value; float rho = elem.Rho; float theta = elem.Theta; double a = Math.Cos(theta); double b = Math.Sin(theta); double x0 = a * rho; double y0 = b * rho; CvPoint pt1 = new CvPoint { X = Cv.Round(x0 + 1000 * (-b)), Y = Cv.Round(y0 + 1000 * (a)) }; CvPoint pt2 = new CvPoint { X = Cv.Round(x0 - 1000 * (-b)), Y = Cv.Round(y0 - 1000 * (a)) }; srcImgStd.Line(pt1, pt2, CvColor.Red, 3, LineType.AntiAlias, 0); } // Probabilistic algorithm lines = srcImgGray.HoughLines2(storage, HoughLinesMethod.Probabilistic, 1, Math.PI / 180, 50, 50, 10); // wrapper style //CvLineSegmentPoint[] lines = src_img_gray.HoughLinesProbabilistic(1, Math.PI / 180, 50, 0, 0); for (int i = 0; i < lines.Total; i++) { // native code style /* unsafe { CvPoint* point = (CvPoint*)lines.GetElem<IntPtr>(i).Value.ToPointer(); src_img_prob.Line(point[0], point[1], CvColor.Red, 3, LineType.AntiAlias, 0); } //*/ // wrapper style CvLineSegmentPoint elem = lines.GetSeqElem<CvLineSegmentPoint>(i).Value; srcImgProb.Line(elem.P1, elem.P2, CvColor.Red, 3, LineType.AntiAlias, 0); } } using (new CvWindow("Hough_line_standard", WindowMode.AutoSize, srcImgStd)) using (new CvWindow("Hough_line_probabilistic", WindowMode.AutoSize, srcImgProb)) { CvWindow.WaitKey(0); } } }
public Inpaint() { // cvInpaint // 画像の不要な文字列部分に対するマスク画像を指定して文字列を除去する Console.WriteLine( "Hot keys: \n" + "\tESC - quit the program\n" + "\tr - restore the original image\n" + "\ti or ENTER - run inpainting algorithm\n" + "\t\t(before running it, paint something on the image)\n" + "\ts - save the original image, mask image, original+mask image and inpainted image to desktop." ); // 原画像の読み込み using (IplImage img0 = new IplImage(Const.ImageFruits, LoadMode.AnyDepth | LoadMode.AnyColor)) { // お絵かき用の画像を確保(マスク) using (IplImage img = img0.Clone()) using (IplImage inpaintMask = new IplImage(img0.Size, BitDepth.U8, 1)) // Inpaintの出力先画像を確保 using (IplImage inpainted = img0.Clone()) { inpainted.Zero(); inpaintMask.Zero(); using (CvWindow wImage = new CvWindow("image", WindowMode.AutoSize, img)) { // マウスイベントの処理 CvPoint prevPt = new CvPoint(-1, -1); wImage.OnMouseCallback += delegate(MouseEvent ev, int x, int y, MouseEvent flags) { if (ev == MouseEvent.LButtonUp || (flags & MouseEvent.FlagLButton) == 0) { prevPt = new CvPoint(-1, -1); } else if (ev == MouseEvent.LButtonDown) { prevPt = new CvPoint(x, y); } else if (ev == MouseEvent.MouseMove && (flags & MouseEvent.FlagLButton) != 0) { CvPoint pt = new CvPoint(x, y); if (prevPt.X < 0) { prevPt = pt; } inpaintMask.Line(prevPt, pt, CvColor.White, 5, LineType.AntiAlias, 0); img.Line(prevPt, pt, CvColor.White, 5, LineType.AntiAlias, 0); prevPt = pt; wImage.ShowImage(img); } }; for (; ; ) { switch ((char)CvWindow.WaitKey(0)) { case (char)27: // ESCキーで終了 CvWindow.DestroyAllWindows(); return; case 'r': // 原画像を復元 inpaintMask.Zero(); img0.Copy(img); wImage.ShowImage(img); break; case 'i': // Inpaintの実行 case '\r': CvWindow wInpaint = new CvWindow("inpainted image", WindowMode.AutoSize); img.Inpaint(inpaintMask, inpainted, 3, InpaintMethod.Telea); wInpaint.ShowImage(inpainted); break; case 's': // 画像の保存 string desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); img0.SaveImage(Path.Combine(desktop, "original.png")); inpaintMask.SaveImage(Path.Combine(desktop, "mask.png")); img.SaveImage(Path.Combine(desktop, "original+mask.png")); inpainted.SaveImage(Path.Combine(desktop, "inpainted.png")); break; } } } } } }
public unsafe Kalman() { // cvKalmanPredict, cvKalmanCorrect // カルマンフィルタを用いて回転する点を追跡する // A matrix data float[] A = new float[] { 1, 1, 0, 1 }; using (IplImage img = new IplImage(500, 500, BitDepth.U8, 3)) using (CvKalman kalman = new CvKalman(2, 1, 0)) using (CvWindow window = new CvWindow("Kalman", WindowMode.AutoSize)) { // state is (phi, delta_phi) - angle and angle increment CvMat state = new CvMat(2, 1, MatrixType.F32C1); CvMat process_noise = new CvMat(2, 1, MatrixType.F32C1); // only phi (angle) is measured CvMat measurement = new CvMat(1, 1, MatrixType.F32C1); measurement.SetZero(); CvRandState rng = new CvRandState(0, 1, -1, DistributionType.Uniform); int code = -1; for (; ; ) { Cv.RandSetRange(rng, 0, 0.1, 0); rng.DistType = DistributionType.Normal; Marshal.Copy(A, 0, kalman.TransitionMatrix.Data, A.Length); kalman.MeasurementMatrix.SetIdentity(1); kalman.ProcessNoiseCov.SetIdentity(1e-5); kalman.MeasurementNoiseCov.SetIdentity(1e-1); kalman.ErrorCovPost.SetIdentity(1); // choose random initial state Cv.Rand(rng, kalman.StatePost); rng.DistType = DistributionType.Normal; for (; ; ) { float state_angle = state.DataSingle[0]; CvPoint state_pt = CalcPoint(img, state_angle); // predict point position CvMat prediction = kalman.Predict(null); float predict_angle = prediction.DataSingle[0]; CvPoint predict_pt = CalcPoint(img, predict_angle); Cv.RandSetRange(rng, 0, Math.Sqrt(kalman.MeasurementNoiseCov.DataSingle[0]), 0); Cv.Rand(rng, measurement); // generate measurement Cv.MatMulAdd(kalman.MeasurementMatrix, state, measurement, measurement); float measurement_angle = measurement.DataArraySingle[0]; CvPoint measurement_pt = CalcPoint(img, measurement_angle); img.SetZero(); DrawCross(img, state_pt, CvColor.White, 3); DrawCross(img, measurement_pt, CvColor.Red, 3); DrawCross(img, predict_pt, CvColor.Green, 3); img.Line(state_pt, measurement_pt, new CvColor(255, 0, 0), 3, LineType.AntiAlias, 0); img.Line(state_pt, predict_pt, new CvColor(255, 255, 0), 3, LineType.AntiAlias, 0); // adjust Kalman filter state kalman.Correct(measurement); Cv.RandSetRange(rng, 0, Math.Sqrt(kalman.ProcessNoiseCov.DataSingle[0]), 0); Cv.Rand(rng, process_noise); Cv.MatMulAdd(kalman.TransitionMatrix, state, process_noise, state); window.ShowImage(img); // break current simulation by pressing a key code = CvWindow.WaitKey(100); if (code > 0) { break; } } // exit by ESCAPE if (code == 27) { break; } } } }
/// <summary> /// 点をプロット /// </summary> /// <param name="img"></param> /// <param name="center"></param> /// <param name="color"></param> /// <param name="d"></param> private void DrawCross(IplImage img, CvPoint center, CvColor color, int d) { img.Line(center.X - d, center.Y - d, center.X + d, center.Y + d, color, 1, 0); img.Line(center.X + d, center.Y - d, center.X - d, center.Y + d, color, 1, 0); }
/// <summary> /// /// </summary> /// <param name="img"></param> /// <param name="edge"></param> /// <param name="color"></param> private void DrawSubdivEdge(IplImage img, CvSubdiv2DEdge edge, CvScalar color) { CvSubdiv2DPoint org_pt = edge.Org(); CvSubdiv2DPoint dst_pt = edge.Dst(); if (org_pt != null && dst_pt != null) { CvPoint2D32f org = org_pt.Pt; CvPoint2D32f dst = dst_pt.Pt; CvPoint iorg = new CvPoint(Cv.Round(org.X), Cv.Round(org.Y)); CvPoint idst = new CvPoint(Cv.Round(dst.X), Cv.Round(dst.Y)); //Console.WriteLine("{0} / {1}", iorg, idst); img.Line(iorg, idst, color, 1, LineType.AntiAlias, 0); } }
/// <summary> /// 指定した分割数でそろばんを全て読み取る /// </summary> /// <param name="source">そろばんの画像</param> /// <param name="threshold">しきい値</param> /// <param name="process_img">処理画像</param> /// <returns>読み取った数値(-1はエラー)</returns> public int[] AllMatching(IplImage source, double threshold, out IplImage process_img) { // グレースケール画像 IplImage cap_gray = new IplImage(PROCESS_SIZE, BitDepth.U8, 1); // キャプチャとリサイズ,グレースケール変換 using (IplImage tmp = new IplImage( PROCESS_SIZE, source.Depth, source.NChannels)) { source.Resize(tmp); tmp.CvtColor(cap_gray, ColorConversion.BgrToGray); } int[] results = new int[DIVIDE_NUM]; int width = cap_gray.Width / (DIVIDE_NUM + 1); int margin = (int)(width * DIVIDE_MARGIN); // 領域ごとに処理 Parallel.For(0, DIVIDE_NUM, i => { IplImage tmp = new IplImage(PROCESS_SIZE, BitDepth.U8, 1); cap_gray.Copy(tmp); int x = (i + 1) * width - width / 2; // 領域を指定 CvRect rect = new CvRect(x - margin, 0, width + margin * 2, PROCESS_SIZE.Height); tmp.SetROI(rect); // 0-9の画像とMatchTemplateし一番高い値を得る results[i] = bestMatchNum(tmp, this.templates[i], threshold); // 領域の指定を解除 tmp.ResetROI(); }); // 分割線の描画 for (int i = 1; i < DIVIDE_NUM + 2; i++) { int x = i * width - width / 2; cap_gray.Line(x, 0, x, PROCESS_SIZE.Height, CvColor.White); } // 読み取り数値を表示 CvFont font = new CvFont(FontFace.HersheyDuplex, 1.0, 1.0); for (int i = 0; i < DIVIDE_NUM; i++) { if (results[i] != -1) { int x = i * width + width / 2; cap_gray.PutText(results[i].ToString(), new CvPoint(x, 30), font, CvColor.White); } } // 分割線, 読み取り数値画像を返す process_img = cap_gray; return results; }
/// <summary> /// sample of C style wrapper /// </summary> private void SampleC() { // cvHoughLines2 // 標準的ハフ変換と確率的ハフ変換を指定して線(線分)の検出を行なう.サンプルコード内の各パラメータ値は処理例の画像に対してチューニングされている. // (1)画像の読み込み using (IplImage srcImgGray = new IplImage(Const.ImageGoryokaku, LoadMode.GrayScale)) using (IplImage srcImgStd = new IplImage(Const.ImageGoryokaku, LoadMode.Color)) using (IplImage srcImgProb = srcImgStd.Clone()) { // (2)ハフ変換のための前処理 Cv.Canny(srcImgGray, srcImgGray, 50, 200, ApertureSize.Size3); using (CvMemStorage storage = new CvMemStorage()) { // (3)標準的ハフ変換による線の検出と検出した線の描画 CvSeq lines = srcImgGray.HoughLines2(storage, HoughLinesMethod.Standard, 1, Math.PI / 180, 50, 0, 0); // wrapper style //CvLineSegmentPolar[] lines = src_img_gray.HoughLinesStandard(1, Math.PI / 180, 50, 0, 0); int limit = Math.Min(lines.Total, 10); for (int i = 0; i < limit; i++) { // native code style /* unsafe { float* line = (float*)lines.GetElem<IntPtr>(i).Value.ToPointer(); float rho = line[0]; float theta = line[1]; } //*/ // wrapper style CvLineSegmentPolar elem = lines.GetSeqElem<CvLineSegmentPolar>(i).Value; float rho = elem.Rho; float theta = elem.Theta; double a = Math.Cos(theta); double b = Math.Sin(theta); double x0 = a * rho; double y0 = b * rho; CvPoint pt1 = new CvPoint { X = Cv.Round(x0 + 1000 * (-b)), Y = Cv.Round(y0 + 1000 * (a)) }; CvPoint pt2 = new CvPoint { X = Cv.Round(x0 - 1000 * (-b)), Y = Cv.Round(y0 - 1000 * (a)) }; srcImgStd.Line(pt1, pt2, CvColor.Red, 3, LineType.AntiAlias, 0); } // (4)確率的ハフ変換による線分の検出と検出した線分の描画 lines = srcImgGray.HoughLines2(storage, HoughLinesMethod.Probabilistic, 1, Math.PI / 180, 50, 50, 10); // wrapper style //CvLineSegmentPoint[] lines = src_img_gray.HoughLinesProbabilistic(1, Math.PI / 180, 50, 0, 0); for (int i = 0; i < lines.Total; i++) { // native code style /* unsafe { CvPoint* point = (CvPoint*)lines.GetElem<IntPtr>(i).Value.ToPointer(); src_img_prob.Line(point[0], point[1], CvColor.Red, 3, LineType.AntiAlias, 0); } //*/ // wrapper style CvLineSegmentPoint elem = lines.GetSeqElem<CvLineSegmentPoint>(i).Value; srcImgProb.Line(elem.P1, elem.P2, CvColor.Red, 3, LineType.AntiAlias, 0); } } // (5)検出結果表示用のウィンドウを確保し表示する using (new CvWindow("Hough_line_standard", WindowMode.AutoSize, srcImgStd)) using (new CvWindow("Hough_line_probabilistic", WindowMode.AutoSize, srcImgProb)) { CvWindow.WaitKey(0); } } }