public dynamic PreProcessImage(ref Mat image, Mat sourceImage) { var copy = new Mat(); try { Cv2.BilateralFilter(image, copy, 9, 75, 75); Cv2.AdaptiveThreshold(copy, copy, 255, AdaptiveThresholdTypes.GaussianC, ThresholdTypes.Binary, 115, 4); Cv2.MedianBlur(copy, copy, 11); Cv2.CopyMakeBorder(copy, copy, 5, 5, 5, 5, BorderTypes.Constant, Scalar.Black); // TODO: Dispose new Mat() var otsu = Cv2.Threshold(copy, new Mat(), 0, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu); Cv2.Canny(copy, copy, otsu, otsu * 2, 3, true); } catch { copy.Dispose(); throw; } image.Dispose(); image = copy; return(null); }
private IEnumerable <IEnumerable <Mat> > SplitImages(Mat image) { var dilate = new Mat(); var element = Cv2.GetStructuringElement(StructuringElementShape.Rect, new Size(image.Width / 40, 1)); Cv2.Dilate(image.Threshold(127, 255, ThresholdType.BinaryInv), dilate, element); HierarchyIndex[] hierarchyIndices; Point[][] contours; Cv2.FindContours(dilate, out contours, out hierarchyIndices, ContourRetrieval.External, ContourChain.ApproxNone); var contourRows = SortToRows(contours); var imageRows = contourRows.Select(r => r.Select(c => { var img = new Mat(); Cv2.CopyMakeBorder(img[Cv2.BoundingRect(c)], img, 10, 10, 10, 10, BorderType.Constant, Scalar.White); // using (new Window("image", segment)) { Cv2.WaitKey(); } return(img); })); return(imageRows); }
private void button1_Click(object sender, EventArgs e) { Mat src_Mat = new Mat("F:\\Microsoft Visual Studio\\project\\yoloaforge\\yoloaforge\\a.jpg", ImreadModes.AnyColor | ImreadModes.AnyDepth); Mat dst_Mat = new Mat(); #region 边缘处理四个类型 //定义四个方向像素,边缘宽度相对于源图像的 0.05 int top = (int)(0.05 * src_Mat.Rows); int botton = (int)(0.05 * src_Mat.Rows); int left = (int)(0.05 * src_Mat.Cols); int right = (int)(0.05 * src_Mat.Cols); //定义随机数 RNG r = new RNG(12345); //int borderType =(int) BorderTypes.Default; BorderTypes borderType = new BorderTypes(); borderType = BorderTypes.Default; //Cv2.ImShow("src", src); int ch = 0; while (true) { ch = Cv2.WaitKey(500); if ((char)ch == 27)// ESC建退出 { break; } else if ((char)ch == 'r') { borderType = BorderTypes.Replicate;//填充边缘像素用已知的边缘像素值 } else if ((char)ch == 'w') { borderType = BorderTypes.Wrap;//用另外一边的像素来补偿填充 } else if ((char)ch == 'c') { borderType = BorderTypes.Constant;//填充边缘用指定像素值 } else if ((char)ch == 'd') { borderType = BorderTypes.Default;//默认边缘处理 } Scalar color = new Scalar(r.Uniform(0, 255), r.Uniform(0, 255), r.Uniform(0, 255)); Cv2.CopyMakeBorder(src_Mat, dst_Mat, top, botton, left, right, borderType, color); Window w = new Window("dst", WindowMode.Normal); Cv2.ImShow("dst", dst_Mat); } #endregion //Cv2.GaussianBlur(src, dst, new Size(5, 5), 5, 5, BorderTypes.Wrap); //using (new Window("dst", WindowMode.Normal, dst_Mat)) //{ // Cv2.WaitKey(0); //} }
public static SoftwareBitmap ExtendImageBorder(SoftwareBitmap Input, Color Colors, int Top, int Left, int Right, int Bottom) { using (Mat inputMat = Input.SoftwareBitmapToMat()) using (Mat outputMat = new Mat(inputMat.Rows, inputMat.Cols, MatType.CV_8UC4)) { Cv2.CopyMakeBorder(inputMat, outputMat, Top, Bottom, Left, Right, BorderTypes.Constant, new Scalar(Colors.B, Colors.G, Colors.R)); return(outputMat.MatToSoftwareBitmap()); } }
private void bernsen_Click(object sender, System.Windows.RoutedEventArgs e) { if (load == true) { Mat src = new Mat(fileName, 0); Mat dst = Mat.Zeros(src.Size(), src.Type()); int r = 15; double eps = 15.0; int border = (r - 1) / 2; Mat result = new Mat(src.Rows, src.Cols, src.Type()); Cv2.CopyMakeBorder(src, result, border, border, border, border, BorderTypes.Replicate); for (int i = border; i < result.Rows - border; i++) { for (int j = border; j < result.Cols - border; j++) { Mat square = result.SubMat(new Rect(j - border, i - border, r, r)); double min, max; Cv2.MinMaxLoc(square, out min, out max); double c = max - min, t; if (c > eps) { t = (min + max) / 2.0; } else { t = 0; } byte value = result.Get <byte>(i, j); if (value > t) { value = 255; } else { value = 0; } dst.Set(i - border, j - border, value); } } showWindow(dst, "bernsen"); } else { textLoad.Foreground = System.Windows.Media.Brushes.OrangeRed; } }
private Mat GetPaddedBinary() { using (Mat tmp = GetInRangeBinary()) using (Mat tmp2 = new Mat()) { Mat tmp3 = new Mat(); // median blue to get ride of the noise Cv2.MedianBlur(tmp, tmp2, 21); var padding = _v.img_padding; Cv2.CopyMakeBorder(tmp2, tmp3, padding, padding, padding, padding, BorderTypes.Constant, new Scalar(0, 0, 0)); return(tmp3); } }
private void niblack_Click(object sender, System.Windows.RoutedEventArgs e) { if (load == true) { Mat src = new Mat(fileName, 0); Mat dst = Mat.Zeros(src.Size(), src.Type()); int r = 15; double k = -0.2; int border = (r - 1) / 2; Mat result = new Mat(src.Rows, src.Cols, src.Type()); Cv2.CopyMakeBorder(src, result, border, border, border, border, BorderTypes.Replicate); for (int i = border; i < result.Rows - border; i++) { for (int j = border; j < result.Cols - border; j++) { Mat square = result.SubMat(new Rect(j - border, i - border, r, r)); Scalar mean = new Scalar(); Scalar dev = new Scalar(); Cv2.MeanStdDev(square, out mean, out dev); double t = mean.Val0 + k * dev.Val0; byte value = result.Get <byte>(i, j); if (value > t) { value = 255; } else { value = 0; } dst.Set(i - border, j - border, value); } } showWindow(dst, "niblack"); } else { textLoad.Foreground = System.Windows.Media.Brushes.OrangeRed; } }
private Mat GetPaddedBinary() { using (Mat tmp = Mat.Ones(_graySrcImage.Size(), MatType.CV_8UC1) * 255) { Mat tmp2 = new Mat(); var pts = _regions.Select(p => { var points = new Point[4]; points[0] = p.Location; points[1] = p.Location + new Point(p.Width, 0); points[2] = p.Location + new Point(p.Width, p.Height); points[3] = p.Location + new Point(0, p.Height); return(points); }); Cv2.FillPoly(tmp, pts, new Scalar(0, 0, 0)); var padding = _v.img_padding; Cv2.CopyMakeBorder(tmp, tmp2, padding, padding, padding, padding, BorderTypes.Constant, new Scalar(0, 0, 0)); return(tmp2); } }
public void CopyMakeBorder() { using var src = new Mat(10, 10, MatType.CV_8UC1, 0); using var dst = new Mat(); const int top = 1, bottom = 2, left = 3, right = 4; Cv2.CopyMakeBorder(src, dst, top, bottom, left, right, BorderTypes.Constant, 255); using var expected = new Mat(src.Rows + top + bottom, src.Cols + left + right, src.Type(), 0); Cv2.Rectangle(expected, new Point(0, 0), new Point(expected.Cols, top - 1), 255, -1); Cv2.Rectangle(expected, new Point(0, expected.Rows - bottom), new Point(expected.Cols, expected.Rows), 255, -1); Cv2.Rectangle(expected, new Point(0, 0), new Point(left - 1, expected.Rows), 255, -1); Cv2.Rectangle(expected, new Point(expected.Cols - right, 0), new Point(expected.Cols, expected.Rows), 255, -1); if (Debugger.IsAttached) { Window.ShowImages(dst, expected); } ImageEquals(dst, expected); }
/** * 扩展图形边界 */ private static Mat CopyBorder(Mat Source) { // 图形形态学(腐蚀) var Eroded = new Mat(); Mat KernelOpen = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(4, 4)); Cv2.MorphologyEx(Source, Eroded, MorphTypes.Open, KernelOpen, new Point(-1, -1), 2); // 往四周扩展10个像素 var CopyBordered = new Mat(); Cv2.CopyMakeBorder(Eroded, CopyBordered, 10, 10, 10, 10, BorderTypes.Constant, new Scalar(0)); // 图形形态学(膨胀) var Dilated = new Mat(); Mat KernelClose = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(2, 2)); Cv2.MorphologyEx(CopyBordered, Dilated, MorphTypes.Close, KernelClose, new Point(-1, -1), 6); return(Dilated); }
private static void Kuwahara(Mat src, Mat dst) { const int kernelSize = 5; const int margin = kernelSize / 2 + 1; if (src.Type() != MatType.CV_8UC3) { throw new ArgumentException("src.Type() != 8UC3", nameof(src)); } using var srcBorder = new Mat(); Cv2.CopyMakeBorder(src, srcBorder, margin, margin, margin, margin, BorderTypes.Reflect); using var sum = new Mat <Vec3i>(); using var sqSum = new Mat <Vec3d>(); Cv2.Integral(srcBorder, sum, sqSum); int w = src.Cols; int h = src.Rows; dst.Create(h, w, src.Type()); var dstIndexer = dst.GetUnsafeGenericIndexer <Vec3b>(); Parallel.For(margin, h + margin, y => { for (int x = margin; x < w + margin; x++) { var a = MeanAndVariance(y - margin, x - margin, margin, sum, sqSum); var b = MeanAndVariance(y - margin, x - 0, margin, sum, sqSum); var c = MeanAndVariance(y - 0, x - 2, margin, sum, sqSum); var d = MeanAndVariance(y - 0, x - 0, margin, sum, sqSum); var min = new[] { a, b, c, d }.OrderBy(mv => mv.Variance[0] + mv.Variance[1] + mv.Variance[2]).First(); dstIndexer[y - margin, x - margin] = new Vec3b( (byte)min.Mean[0], (byte)min.Mean[1], (byte)min.Mean[2]); } }); }
private int OpenT() { String filename = "F:\\b.png"; //Mat I = (Bitmap)Image.FromFile(filename); Mat I = new Mat(filename, ImreadModes.Color); Mat X = new Mat(); Mat padded = new Mat(); //以0填充输入图像矩阵 //Cv2.GetOptimalDFTSize(); int m = Cv2.GetOptimalDFTSize(I.Rows); int n = Cv2.GetOptimalDFTSize(I.Cols); //填充输入图像I,输入矩阵为padded,上方和左方不做填充处理 Cv2.CopyMakeBorder(I, padded, 0, m - I.Rows, 0, n - I.Cols, BorderTypes.Constant); pictureBox1.Image = ToolFunctions.GetThumbnail(X.ToBitmap(), pictureBox1.Height, pictureBox1.Width); return(0); }
/// <summary> /// Nickの手法による二値化処理を行う。 /// </summary> /// <param name="imgSrc">入力画像</param> /// <param name="imgDst">出力画像</param> /// <param name="kernelSize">局所領域のサイズ</param> /// <param name="k">係数</param> #else /// <summary> /// Binarizes by Nick's method /// </summary> /// <param name="src">Input image</param> /// <param name="dst">Output image</param> /// <param name="kernelSize">Window size</param> /// <param name="k">Adequate coefficient</param> #endif public static void Nick(Mat src, Mat dst, int kernelSize, double k) { if (src == null) { throw new ArgumentNullException("src"); } if (dst == null) { throw new ArgumentNullException("dst"); } // グレースケールのみ if (src.Type() != MatType.CV_8UC1) { throw new ArgumentException("src must be gray scale image"); } if (dst.Type() != MatType.CV_8UC1) { throw new ArgumentException("dst must be gray scale image"); } // サイズのチェック if (kernelSize < 3) { throw new ArgumentOutOfRangeException("kernelSize", "size must be 3 and above"); } if (kernelSize % 2 == 0) { throw new ArgumentOutOfRangeException("kernelSize", "size must be odd number"); } int borderSize = kernelSize / 2; int width = src.Width; int height = src.Height; dst.Create(src.Size(), src.Type()); using (var tempMat = new Mat(height + (borderSize * 2), width + (borderSize * 2), src.Type())) using (var sumMat = new Mat(tempMat.Height + 1, tempMat.Width + 1, MatType.CV_64FC1, 1)) using (var sqSumMat = new Mat(tempMat.Height + 1, tempMat.Width + 1, MatType.CV_64FC1, 1)) { Cv2.CopyMakeBorder(src, tempMat, borderSize, borderSize, borderSize, borderSize, BorderTypes.Replicate, Scalar.All(0)); Cv2.Integral(tempMat, sumMat, sqSumMat); using (var tSrcMat = new MatOfByte(src)) using (var tDstMat = new MatOfByte(dst)) using (var tSumMat = new MatOfDouble(sumMat)) using (var tSqSumMat = new MatOfDouble(sqSumMat)) { var tSrc = tSrcMat.GetIndexer(); var tDst = tDstMat.GetIndexer(); var tSum = tSumMat.GetIndexer(); var tSqSum = tSqSumMat.GetIndexer(); int ylim = height + borderSize; int xlim = width + borderSize; int kernelPixels = kernelSize * kernelSize; for (int y = borderSize; y < ylim; y++) { for (int x = borderSize; x < xlim; x++) { int x1 = x - borderSize; int y1 = y - borderSize; int x2 = x + borderSize + 1; int y2 = y + borderSize + 1; double sum = tSum[y2, x2] - tSum[y2, x1] - tSum[y1, x2] + tSum[y1, x1]; double sqsum = tSqSum[y2, x2] - tSqSum[y2, x1] - tSqSum[y1, x2] + tSqSum[y1, x1]; double mean = sum / kernelPixels; double term = (sqsum - mean * mean) / kernelPixels; if (term < 0.0) { term = 0.0; } term = Math.Sqrt(term); double threshold = mean + k * term; if (tSrc[y - borderSize, x - borderSize] < threshold) { tDst[y - borderSize, x - borderSize] = 0; } else { tDst[y - borderSize, x - borderSize] = 255; } } } } } }
/** * 识别的主流程 * 返回识别后的数字 * needSave是否输出中间图像 */ public static string Process(string Img, bool needSave = false) { // 图片路径 // const string Img = @"D:\work\sharp\DigitalTube1\data\1873.jpg"; string ImgPath = Path.GetDirectoryName(Img); string ImgName = Path.GetFileNameWithoutExtension(Img); string ImgPref = Path.Combine(ImgPath, ImgName); // 显示原始图片 var OriginImg = Cv2.ImRead(Img); // ------------------- debug start //Cv2.NamedWindow("OriginImg", WindowMode.Normal); //Cv2.ImShow("OriginImg", OriginImg); // ------------------- debug end // 转化成灰度图 var Grayscale = Cv2.ImRead(Img, ImreadModes.Grayscale); // ------------------- debug start //Cv2.NamedWindow("Grayscale", WindowMode.Normal); //Cv2.ImShow("Grayscale", Grayscale); // ------------------- debug end // 往四周扩展10个像素 var CopyBordered = new Mat(); Cv2.CopyMakeBorder(Grayscale, CopyBordered, 10, 10, 10, 10, BorderTypes.Constant, new Scalar(255)); // ------------------- debug start //Cv2.NamedWindow("CopyBordered", WindowMode.Normal); //Cv2.ImShow("CopyBordered", CopyBordered); // ------------------- debug end // 进行高斯模糊变换(去噪) var Blured = new Mat(); Cv2.GaussianBlur(CopyBordered, Blured, new Size(15, 15), 0); // ------------------- debug start //Cv2.NamedWindow("Blured", WindowMode.Normal); //Cv2.ImShow("Blured", Blured); // ------------------- debug end // 转化为二值图片(只有黑白无灰色) var Binary = new Mat(); Cv2.Threshold(Blured, Binary, 128, 255, ThresholdTypes.Binary); // ------------------- debug start //Cv2.NamedWindow("Binary", WindowMode.Normal); //Cv2.ImShow("Binary", Binary); // ------------------- debug end // 去掉小数点(小块面积去噪) var DropNoise = DropSmallAreaNoise(Binary); // ------------------- debug start //Cv2.NamedWindow("DropNoise", WindowMode.Normal); //Cv2.ImShow("DropNoise", DropNoise); // ------------------- debug end // 图形形态学(腐蚀) var Eroded = new Mat(); Mat KernelOpen = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(4, 4)); Cv2.MorphologyEx(DropNoise, Eroded, MorphTypes.Open, KernelOpen, new Point(-1, -1), 7); // ------------------- debug start //Cv2.NamedWindow("Eroded", WindowMode.Normal); //Cv2.ImShow("Eroded", Eroded); // ------------------- debug end // 图形形态学(膨胀) var Dilated = new Mat(); Mat KernelClose = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3)); Cv2.MorphologyEx(Eroded, Dilated, MorphTypes.Close, KernelClose, new Point(-1, -1), 5); // ------------------- debug start //Cv2.NamedWindow("Dilated", WindowMode.Normal); //Cv2.ImShow("Dilated", Dilated); // ------------------- debug end // 图形取反变换(黑白颠倒) var Binary2 = new Mat(); Cv2.BitwiseNot(Dilated, Binary2); // ------------------- debug start //Cv2.NamedWindow("Binary2", WindowMode.Normal); //Cv2.ImShow("Binary2", Binary2); // ------------------- debug end var Morphologyed = Binary2.Clone(); // 识别图片轮廓(后续按照轮廓分割) var Rects = new List <Rect>(); // 识别轮廓 Point[][] Contours = Cv2.FindContoursAsArray(Binary2, RetrievalModes.External, ContourApproximationModes.ApproxSimple); Console.WriteLine("Contours Count = " + Contours.Length); foreach (Point[] Contour in Contours) { Rect Region = Cv2.BoundingRect(Contour); Cv2.Rectangle(Morphologyed, Region, new Scalar(193, 0, 0), 4); Rects.Add(Region); } // ------------------- debug start //Cv2.NamedWindow("Contours", WindowMode.Normal); //Cv2.ImShow("Contours", Morphologyed); // ------------------- debug start if (needSave) { Cv2.ImWrite(ImgPref + "__Contours.png", Morphologyed); } // 对轮廓进行排序(X轴方向,横写文字) Rects.Sort((a, b) => (a.X - b.X)); // 对每个轮廓部分进行处理 var ImgParts = new Mat[Rects.Count]; for (var i = 0; i < Rects.Count; i++) { // 对图形进行边界扩充 var ImgPart = Binary2[Rects[i]].Clone(); ImgParts[i] = CopyBorder(ImgPart); // ------------------- debug start //Cv2.NamedWindow("Number" + (i + 1), WindowMode.Normal); //Cv2.ImShow("Number" + (i + 1), ImgParts[i]); // ------------------- debug end if (needSave) { Cv2.ImWrite(ImgPref + "__Contours(" + (i + 1) + ").png", ImgParts[i]); } } // 用穿线法将图形识别成数字 var Numbers = new char[Rects.Count]; //如果有一个数字识别不出来,那么就t_number[0]标记为'e' for (var i = 0; i < Rects.Count; i++) { Numbers[i] = myIdentification(ImgParts[i]); // Console.WriteLine("Number" + (i + 1) + " = " + Numbers[i]); } // 将画面停留以便观察结果 //Cv2.WaitKey(); return(new string(Numbers)); }
private void dealimage(String path, String savepath) { Mat result = Cv2.ImRead(path); Scalar color = new Scalar(0, 0, 0); Cv2.CopyMakeBorder(result, result, 10, 10, 10, 10, BorderTypes.Constant, color); Mat outp = new Mat(); Cv2.CvtColor(result, outp, ColorConversionCodes.BGR2GRAY); Mat thresh = new Mat(); Cv2.Threshold(outp, thresh, 0, 255, ThresholdTypes.Binary); /* Cv2.ImShow("2", thresh); * Cv2.WaitKey(-1);*/ OpenCvSharp.Point[][] counts; HierarchyIndex[] hierarchyIndices; Cv2.FindContours(thresh.Clone(), out counts, out hierarchyIndices, RetrievalModes.External, ContourApproximationModes.ApproxSimple); double max = 0; OpenCvSharp.Point[] point = null; foreach (var count in counts) { if (max < Cv2.ContourArea(count)) { point = count; max = Cv2.ContourArea(count); } } Console.WriteLine(thresh.Rows); Console.WriteLine(thresh.Cols); /*int** mask = new int[][];*/ Rect rect = Cv2.BoundingRect(point); Mat mat = Mat.Zeros(thresh.Rows, thresh.Cols, thresh.Type()); Cv2.Rectangle(mat, rect.TopLeft, rect.BottomRight, 255, -1); Mat minRect = mat.Clone(); Mat sub = mat.Clone(); while (Cv2.CountNonZero(sub) > 0) { Cv2.Erode(minRect, minRect, null); Cv2.Subtract(minRect, thresh, sub); } Cv2.FindContours(minRect.Clone(), out counts, out hierarchyIndices, RetrievalModes.External, ContourApproximationModes.ApproxSimple); max = 0; foreach (var count in counts) { if (max < Cv2.ContourArea(count)) { point = count; max = Cv2.ContourArea(count); } } rect = Cv2.BoundingRect(point); result = new Mat(result, rect); savepath = savepath + "/" + "result.jpg"; Cv2.ImWrite(savepath, result); try { pictureBox1.Image = Image.FromFile(savepath); } catch (Exception e) { } MessageBox.Show("拼接成功"); }
/// <summary> /// 材质识别 /// </summary> public static List <string> TextureFind(Mat img, Point[] points) { Mat src = img; Mat hsv = new Mat(), threshold = new Mat(); Mat dst = new Mat(), dst2 = new Mat(); Scalar HsvWhiteLow = new Scalar(0, 0, 1); //白 white Scalar HsvWhiteHigh = new Scalar(0.1156, 0.2480, 0.9804); Scalar HsvGraLow = new Scalar(0, 0, 46); //灰 gray Scalar HsvGraHigh = new Scalar(180, 43, 220); Scalar HsvGrayLow = new Scalar(0.4815, 0.0720, 0.4902); //深灰 Scalar HsvGrayHigh = new Scalar(0.4583, 0.0656, 0.2392); Scalar HsvGlassLow = new Scalar(171, 1, 80); //Glass gray Scalar HsvGlassHigh = new Scalar(171, 5, 60); Scalar HsvBlueLow = new Scalar(100, 43, 46); //蓝 blue Scalar HsvBlueHigh = new Scalar(124, 255, 255); Cv2.CvtColor(src, hsv, ColorConversionCodes.BGR2HSV); Scalar[] HsvLow = { HsvWhiteLow, HsvGlassLow, HsvGraLow, HsvBlueLow, HsvGrayLow }; Scalar[] HsvHigh = { HsvWhiteHigh, HsvGlassHigh, HsvGraHigh, HsvBlueHigh, HsvGrayHigh }; string[] textcolor = { "White", "Glass", "Blue", "Metal ash", "Gray" }; Point[][] contours = { points }; int cc = 0; Point center = new Point(); HierarchyIndex[] hierarchy; //List<string> Texture = new List<string>(); //List<Point> Centerpoint = new List<Point>(); for (int color = 0; color < HsvLow.Length; color++) { Cv2.InRange(hsv, HsvLow[color], HsvHigh[color], threshold); Cv2.Threshold(threshold, threshold, 1, 255, ThresholdTypes.Binary); Cv2.CopyMakeBorder(threshold, dst, 1, 1, 1, 1, BorderTypes.Constant, 0); //Cv2.FindContours(dst, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple); int count = 0; if (count < 1) { Rect bound = Cv2.BoundingRect(points); center = new Point(bound.X + bound.Width / 2, bound.Y + bound.Height / 2); int[] vs = { center.X, center.Y }; char x = threshold.At <char>(vs); if (x > 0) { //Cv2.DrawContours(src, contours, 0, Scalar.Red, 1, LineTypes.Link8); //Cv2.PutText(src, textcolor[color], center, HersheyFonts.HersheyComplex,1, Scalar.Black, 1, LineTypes.Link8); //Cv2.Circle(src, center, 10, Scalar.Gold); cc = color; } } } Centerpoint.Add(center); switch (textcolor[cc]) { case "Gray": case "White": Texture.Add("石头"); break; case "Glass": case "Blue": Texture.Add("玻璃"); break; case "Metal ash": Texture.Add("金属"); break; default: Texture.Add("其他"); break; } //Console.WriteLine(textcolor[cc] + "区域数量:" + count); //Cv2.NamedWindow("result_txe", 0); //Cv2.ResizeWindow("result_txe", 500, 500); //Cv2.ImShow("result_txe", src); // //Window.WaitKey(); return(Texture); }
/// <summary> /// Binarizes by Sauvola's method (This is faster but memory-hogging) /// </summary> /// <param name="src">Input image</param> /// <param name="dst">Output image</param> /// <param name="kernelSize">Window size</param> /// <param name="k">Adequate coefficient</param> /// <param name="r">Adequate coefficient</param> public static void Sauvola(Mat src, Mat dst, int kernelSize, double k, double r) { if (src == null) { throw new ArgumentNullException(nameof(src)); } if (dst == null) { throw new ArgumentNullException(nameof(dst)); } // グレースケールのみ if (src.Type() != MatType.CV_8UC1) { throw new ArgumentException("src must be gray scale image"); } // サイズのチェック if (kernelSize < 3) { throw new ArgumentOutOfRangeException(nameof(kernelSize), "size must be 3 and above"); } if (kernelSize % 2 == 0) { throw new ArgumentOutOfRangeException(nameof(kernelSize), "size must be odd number"); } if (Math.Abs(r) < 1e-9f) { throw new ArgumentOutOfRangeException(nameof(r), "r == 0"); } int borderSize = kernelSize / 2; int width = src.Width; int height = src.Height; dst.Create(src.Size(), src.Type()); using (var tempMat = new Mat(height + (borderSize * 2), width + (borderSize * 2), src.Type())) using (var sumMat = new Mat()) using (var sqSumMat = new Mat()) { Cv2.CopyMakeBorder(src, tempMat, borderSize, borderSize, borderSize, borderSize, BorderTypes.Replicate, Scalar.All(0)); Cv2.Integral(tempMat, sumMat, sqSumMat, MatType.CV_64FC1); using (var tSrcMat = new Mat <byte>(src)) using (var tDstMat = new Mat <byte>(dst)) using (var tSumMat = new Mat <double>(sumMat)) using (var tSqSumMat = new Mat <double>(sqSumMat)) { var tSrc = tSrcMat.GetIndexer(); var tDst = tDstMat.GetIndexer(); var tSum = tSumMat.GetIndexer(); var tSqSum = tSqSumMat.GetIndexer(); int ylim = height + borderSize; int xlim = width + borderSize; int kernelPixels = kernelSize * kernelSize; for (int y = borderSize; y < ylim; y++) { for (int x = borderSize; x < xlim; x++) { int x1 = x - borderSize; int y1 = y - borderSize; int x2 = x + borderSize + 1; int y2 = y + borderSize + 1; double sum = tSum[y2, x2] - tSum[y2, x1] - tSum[y1, x2] + tSum[y1, x1]; double sqsum = tSqSum[y2, x2] - tSqSum[y2, x1] - tSqSum[y1, x2] + tSqSum[y1, x1]; double mean = sum / kernelPixels; double var = (sqsum / kernelPixels) - (mean * mean); if (var < 0.0) { var = 0.0; } double stddev = Math.Sqrt(var); double threshold = mean * (1 + k * (stddev / r - 1)); if (tSrc[y - borderSize, x - borderSize] < threshold) { tDst[y - borderSize, x - borderSize] = 0; } else { tDst[y - borderSize, x - borderSize] = 255; } } } } } }
public static void type2() { Mat src = Cv2.ImRead(@"D:\OpenCV\ING\curtainwall\aaaaa.png"); //src=Findarea(src); //Window.WaitKey(); Mat hsv = new Mat(), threshold = new Mat(); Mat dst = new Mat(), dst2 = new Mat(); //Scalar HsvRedLow = new Scalar(0, 40, 40); //Scalar HsvRedHigh = new Scalar(40, 255, 255); //Scalar HsvGreenLow = new Scalar(41, 40, 40); //Scalar HsvGreenHigh = new Scalar(90, 255, 255); //Scalar HsvBlueLow = new Scalar(100, 40, 40); //Scalar HsvBlueHigh = new Scalar(140, 255, 255); Scalar HsvRedLow = new Scalar(0, 0, 1); //白 white Scalar HsvRedHigh = new Scalar(0.1156, 0.2480, 0.9804); Scalar HsvGreenLow = new Scalar(0, 0, 46); //灰 gray Scalar HsvGreenHigh = new Scalar(180, 43, 220); Scalar HsvBlueLow = new Scalar(100, 43, 46); //蓝 blue Scalar HsvBlueHigh = new Scalar(124, 255, 255); Cv2.CvtColor(src, hsv, ColorConversionCodes.BGR2HSV); Cv2.NamedWindow("hsv", 0); Cv2.ResizeWindow("hsv", 500, 500); Cv2.ImShow("hsv", hsv); Scalar[] HsvLow = { HsvRedLow, HsvGreenLow, HsvBlueLow }; Scalar[] HsvHigh = { HsvRedHigh, HsvGreenHigh, HsvBlueHigh }; string[] textcolor = { "White", "Gray", "Blue" }; Point[][] contours; //= Findarea(src); HierarchyIndex[] hierarchy; // = hierarchys; for (int color = 0; color < 3; color++) { Cv2.InRange(hsv, HsvLow[color], HsvHigh[color], threshold); Cv2.Threshold(threshold, threshold, 1, 255, ThresholdTypes.Binary); Cv2.CopyMakeBorder(threshold, dst, 1, 1, 1, 1, BorderTypes.Constant, 0); Mat a = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(5, 5));//5.23 Cv2.MorphologyEx(dst, dst, MorphTypes.Open, a); //dst = threshold; //Cv2.CvtColor(src,dst2,ColorConversionCodes.BGR2GRAY); //Cv2.Threshold(dst2,dst2,100,255,ThresholdTypes.Binary); //Cv2.FindContours(dst2, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple); //Cv2.ImShow("ss",dst2); Cv2.NamedWindow(textcolor[color] + "轮廓", 0); Cv2.ResizeWindow(textcolor[color] + "轮廓", 500, 500); Cv2.ImShow(textcolor[color] + "轮廓", dst); Cv2.FindContours(dst, out contours, out hierarchy, RetrievalModes.Tree, ContourApproximationModes.ApproxSimple); //Console.WriteLine(contours.Length); int count = 0; for (int i = 0; i < contours.Length; i++) { if (contours[i].Length < 200) { continue; } Rect bound = Cv2.BoundingRect(contours[i]); //Cv2.DrawContours(src, contours, i, Scalar.Black, 1, LineTypes.Link8, hierarchy, 0, new Point(0, 0)); Point center = new Point(bound.X + bound.Width / 2, bound.Y + bound.Height / 2); //int[] bc = { center.X, center.Y }; //char x = threshold.At<char>(bc); //Console.WriteLine(x); if (true) { count++; Cv2.PutText(src, textcolor[color], center, HersheyFonts.HersheyComplex, 1, Scalar.Black, 1, LineTypes.Link8); Cv2.Circle(src, center, 10, Scalar.Gray); } } Console.WriteLine(textcolor[color] + "区域数量:" + count); } Cv2.NamedWindow("result", 0); Cv2.ResizeWindow("result", 500, 500); Cv2.ImShow("result", src); Window.WaitKey(); }
public bool LoadShape(string shapePath) { if (!File.Exists(shapePath)) { Debug.Log("Shape File do not exist!"); return(false); } Mat shapeImage = Cv2.ImRead(shapePath, ImreadModes.GrayScale); if (shapeImage.Empty()) { Debug.Log("No readable shape file: " + shapePath); return(false); } Cv2.CopyMakeBorder(shapeImage, shapeImage, 10, 10, 10, 10, BorderTypes.Constant); shapeImage = 255 - shapeImage; Cv2.Erode(shapeImage, shapeImage, new Mat(), new Point(-1, -1), 5); Cv2.Dilate(shapeImage, shapeImage, new Mat(), new Point(-1, -1), 5); Mat shapeEdges = new Mat(); Cv2.Canny(shapeImage, shapeEdges, 100, 200, 3, false); HierarchyIndex[] contoure_hierarcyInd; generatorState = State.NotSet; Cv2.FindContours(shapeEdges, out contours, out contoure_hierarcyInd, RetrievalModes.External, ContourApproximationModes.ApproxTC89L1); if (contours.Length > 1) { Debug.Log("Dont know witch contour to use."); return(false); } Point2f center; float radius; Cv2.MinEnclosingCircle(contours [0], out center, out radius); float diameter = radius * 2; contourNormalized = new Point2f[contours [0].Length]; contourScaled = new Point2f[contours [0].Length]; for (int i = 0; i < contours [0].Length; ++i) { contourNormalized [i] = new Point2f((contours [0] [i].X - center.X) / diameter, (contours [0] [i].Y - center.Y) / diameter); contourScaled [i] = new Point2f(); } steam = new Point2f[2]; steamNormalized = new Point2f[2]; steamScaled = new Point2f[2]; steam [0] = new Point2f(center.X, center.Y); steam [0].Y += radius; steam [1] = new Point2f(steam [0].X, steam[0].Y); steam [1].Y += diameter * maxSteamLengthRatio; for (int i = 0; i < steam.Length; ++i) { steamNormalized [i] = new Point2f((steam [i].X - center.X) / diameter, (steam [i].Y - center.Y) / diameter); steamScaled [i] = new Point2f(); } generatorState = State.ShapeSet; return(true); }
/// <summary> /// 离散傅里叶变换 /// </summary> /// <param name="source"></param> /// <returns></returns> public static Bitmap Dft(this Bitmap source) { var fileName = Path.GetTempPath() + "\\" + Guid.NewGuid().ToString() + ".bmp"; File.WriteAllBytes(fileName, source.GetBitmapFileData()); using (var img = Cv2.ImRead(fileName, ImreadModes.Grayscale)) { fileName = Path.GetTempPath() + "\\" + Guid.NewGuid().ToString() + ".bmp"; var padded = new Mat(); // 计算最佳 DFT 尺寸 var m = Cv2.GetOptimalDFTSize(img.Rows); var n = Cv2.GetOptimalDFTSize(img.Cols); Cv2.CopyMakeBorder(img, padded, 0, m - img.Rows, 0, n - img.Cols, BorderTypes.Constant, Scalar.All(0)); var paddedF32 = new Mat(); padded.ConvertTo(paddedF32, MatType.CV_32F); Mat[] planes = { paddedF32, Mat.Zeros(padded.Size(), MatType.CV_32F) }; var complex = new Mat(); Cv2.Merge(planes, complex); // 执行 dft var dft = new Mat(); Cv2.Dft(complex, dft); // log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)) Cv2.Split(dft, out var dftPlanes); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) // planes[0] = magnitude var magnitude = new Mat(); Cv2.Magnitude(dftPlanes[0], dftPlanes[1], magnitude); magnitude += Scalar.All(1); Cv2.Log(magnitude, magnitude); var spectrum = magnitude[ new Rect(0, 0, magnitude.Cols & -2, magnitude.Rows & -2)]; // 交换象限 var cx = spectrum.Cols / 2; var cy = spectrum.Rows / 2; var q0 = new Mat(spectrum, new Rect(0, 0, cx, cy)); // 左上 var q1 = new Mat(spectrum, new Rect(cx, 0, cx, cy)); // 右上 var q2 = new Mat(spectrum, new Rect(0, cy, cx, cy)); // 左下 var q3 = new Mat(spectrum, new Rect(cx, cy, cx, cy)); // 右下 var tmp = new Mat(); q0.CopyTo(tmp); q3.CopyTo(q0); tmp.CopyTo(q3); q1.CopyTo(tmp); q2.CopyTo(q1); tmp.CopyTo(q2); // 归一化到 0~255 Cv2.Normalize(spectrum, spectrum, 0, 255, NormTypes.MinMax); var result = new Mat(); spectrum.ConvertTo(result, MatType.CV_8U); result.SaveImage(fileName); return(new Bitmap(fileName)); } }
public void Run() { Mat img = Cv2.ImRead(FilePath.Image.Lenna, ImreadModes.GrayScale); // expand input image to optimal size Mat padded = new Mat(); int m = Cv2.GetOptimalDFTSize(img.Rows); int n = Cv2.GetOptimalDFTSize(img.Cols); // on the border add zero values Cv2.CopyMakeBorder(img, padded, 0, m - img.Rows, 0, n - img.Cols, BorderTypes.Constant, Scalar.All(0)); // Add to the expanded another plane with zeros Mat paddedF32 = new Mat(); padded.ConvertTo(paddedF32, MatType.CV_32F); Mat[] planes = { paddedF32, Mat.Zeros(padded.Size(), MatType.CV_32F) }; Mat complex = new Mat(); Cv2.Merge(planes, complex); // this way the result may fit in the source matrix Mat dft = new Mat(); Cv2.Dft(complex, dft); // compute the magnitude and switch to logarithmic scale // => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)) Mat[] dftPlanes; Cv2.Split(dft, out dftPlanes); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) // planes[0] = magnitude Mat magnitude = new Mat(); Cv2.Magnitude(dftPlanes[0], dftPlanes[1], magnitude); magnitude += Scalar.All(1); // switch to logarithmic scale Cv2.Log(magnitude, magnitude); // crop the spectrum, if it has an odd number of rows or columns Mat spectrum = magnitude[ new Rect(0, 0, magnitude.Cols & -2, magnitude.Rows & -2)]; // rearrange the quadrants of Fourier image so that the origin is at the image center int cx = spectrum.Cols / 2; int cy = spectrum.Rows / 2; Mat q0 = new Mat(spectrum, new Rect(0, 0, cx, cy)); // Top-Left - Create a ROI per quadrant Mat q1 = new Mat(spectrum, new Rect(cx, 0, cx, cy)); // Top-Right Mat q2 = new Mat(spectrum, new Rect(0, cy, cx, cy)); // Bottom-Left Mat q3 = new Mat(spectrum, new Rect(cx, cy, cx, cy)); // Bottom-Right // swap quadrants (Top-Left with Bottom-Right) Mat tmp = new Mat(); q0.CopyTo(tmp); q3.CopyTo(q0); tmp.CopyTo(q3); // swap quadrant (Top-Right with Bottom-Left) q1.CopyTo(tmp); q2.CopyTo(q1); tmp.CopyTo(q2); // Transform the matrix with float values into a Cv2.Normalize(spectrum, spectrum, 0, 1, NormTypes.MinMax); // Show the result Cv2.ImShow("Input Image", img); Cv2.ImShow("Spectrum Magnitude", spectrum); // calculating the idft Mat inverseTransform = new Mat(); Cv2.Dft(dft, inverseTransform, DftFlags.Inverse | DftFlags.RealOutput); Cv2.Normalize(inverseTransform, inverseTransform, 0, 1, NormTypes.MinMax); Cv2.ImShow("Reconstructed by Inverse DFT", inverseTransform); Cv2.WaitKey(); }
public Mat fourier(Mat img) { Mat padded = new Mat(); int m = Cv2.GetOptimalDFTSize(img.Rows); int n = Cv2.GetOptimalDFTSize(img.Cols); // on the border add zero values Cv2.CopyMakeBorder(img, padded, 0, m - img.Rows, 0, n - img.Cols, BorderTypes.Constant, Scalar.All(0)); // Add to the expanded another plane with zeros Mat paddedF32 = new Mat(); padded.ConvertTo(paddedF32, MatType.CV_32F); Mat[] planes = { paddedF32, Mat.Zeros(padded.Size(), MatType.CV_32F) }; Mat complex = new Mat(); Cv2.Merge(planes, complex); // this way the result may fit in the source matrix Mat dft = new Mat(); Cv2.Dft(complex, dft); // compute the magnitude and switch to logarithmic scale // => log(1 + sqrt(Re(DFT(I))^2 + Im(DFT(I))^2)) Mat[] dftPlanes; Cv2.Split(dft, out dftPlanes); // planes[0] = Re(DFT(I), planes[1] = Im(DFT(I)) // planes[0] = magnitude Mat magnitude = new Mat(); Cv2.Magnitude(dftPlanes[0], dftPlanes[1], magnitude); magnitude += Scalar.All(1); // switch to logarithmic scale Cv2.Log(magnitude, magnitude); // crop the spectrum, if it has an odd number of rows or columns Mat spectrum = magnitude[ new OpenCvSharp.Rect(0, 0, magnitude.Cols & -2, magnitude.Rows & -2)]; // rearrange the quadrants of Fourier image so that the origin is at the image center int cx = spectrum.Cols / 2; int cy = spectrum.Rows / 2; Mat q0 = new Mat(spectrum, new OpenCvSharp.Rect(0, 0, cx, cy)); // Top-Left - Create a ROI per quadrant Mat q1 = new Mat(spectrum, new OpenCvSharp.Rect(cx, 0, cx, cy)); // Top-Right Mat q2 = new Mat(spectrum, new OpenCvSharp.Rect(0, cy, cx, cy)); // Bottom-Left Mat q3 = new Mat(spectrum, new OpenCvSharp.Rect(cx, cy, cx, cy)); // Bottom-Right // swap quadrants (Top-Left with Bottom-Right) Mat tmp = new Mat(); q0.CopyTo(tmp); q3.CopyTo(q0); tmp.CopyTo(q3); // swap quadrant (Top-Right with Bottom-Left) q1.CopyTo(tmp); q2.CopyTo(q1); tmp.CopyTo(q2); // Transform the matrix with float values into a Cv2.Normalize(spectrum, spectrum, 0, 1, NormTypes.MinMax); // calculating the idft Mat inverseTransform = new Mat(); Cv2.Dft(dft, inverseTransform, DftFlags.Inverse | DftFlags.RealOutput); Cv2.Normalize(inverseTransform, inverseTransform, 0, 1, NormTypes.MinMax); double minVal = 0.0, maxVal = 0.0; Cv2.MinMaxIdx(inverseTransform, out minVal, out maxVal); Cv2.ConvertScaleAbs(inverseTransform, inverseTransform, 255.0 / (maxVal - minVal), -minVal * 255.0 / (maxVal - minVal)); return(inverseTransform); }