using OpenCvSharp; using PaintDotNet.Adjust; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Metis.AutoAnalysis { /// /// 寻找最差视场 /// class WorstfieldFinder { public static Mat Find(Mat src, OpenCvSharp.Size size) { Mat gray = new Mat(); Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY); Mat mask = convert2Mask(gray); //去掉边缘 Mat element = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(11, 11)); Cv2.Erode(mask, mask, element); //取边缘 Mat srcTemp = src.Clone(); Mat edge = ImageSobel(srcTemp); if(edge == null) { Mat result1 = new Mat(src, new OpenCvSharp.Rect(new OpenCvSharp.Point(0, 0), size)); return result1; } //把因为拼图造成的边缘去掉 Cv2.BitwiseAnd(edge, mask, edge); Mat thr = new Mat(); Cv2.Threshold(edge, thr, 50, 255, ThresholdTypes.Binary); OpenCvSharp.Point[][] contours = null; HierarchyIndex[] hierarchy = null; Cv2.FindContours(thr, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxNone); var obj = new Mat(gray.Size(), MatType.CV_8UC1, Scalar.All(0)); Cv2.DrawContours(obj, contours, -1, Scalar.All(255), -1); //遍历整个图形 int step = 500; int maxNZ = -100;//非0点个数 var tempLoc = new OpenCvSharp.Point(); for (int y = 0; y < src.Height - size.Height; y += step) { for (int x = 0; x < src.Width - size.Width; x += step) { LogHelper.log.Debug(" Find x =" + x.ToString() + " y = " + y.ToString()); Rect rc = new Rect(x, y, size.Width, size.Height); Mat roi = new Mat(obj, rc); var countNZ = Cv2.CountNonZero(roi); if(maxNZ < countNZ) { maxNZ = countNZ; tempLoc = new Point(x, y); } } } Mat result = new Mat(src, new Rect(tempLoc, size)); return result; } /// /// 生成拼图后的掩码 /// /// /// private static Mat convert2Mask(Mat gray) { LogHelper.log.Debug(" convert2Mask 111"); Mat thr = new Mat(); Cv2.Threshold(gray, thr, 1, 255, ThresholdTypes.Binary); LogHelper.log.Debug(" convert2Mask 222"); OpenCvSharp.Point[][] contours = null; HierarchyIndex[] hierarchy = null; Cv2.FindContours(thr, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxNone); LogHelper.log.Debug(" convert2Mask 333"); //生成拼图后实际图像的掩码 var mask = new Mat(gray.Size(), MatType.CV_8UC1, Scalar.All(0)); Cv2.DrawContours(mask, contours, -1, Scalar.All(255), -1); LogHelper.log.Debug(" convert2Mask 444"); return mask; } public static Mat ImageSobel(Mat src) { Mat gray = null, xgrad = null, ygrad = null, output = null; try { //转为灰度 gray = new Mat(); Cv2.CvtColor(src, gray, ColorConversionCodes.BGR2GRAY); MatType m = src.Type(); //求 X 和 Y 方向的梯度 Sobel and scharr xgrad = new Mat(); ygrad = new Mat(); Cv2.Sobel(gray, xgrad, MatType.CV_16S, 1, 0, 3); Cv2.Sobel(gray, ygrad, MatType.CV_16S, 0, 1, 3); Cv2.ConvertScaleAbs(xgrad, xgrad);//缩放、计算绝对值并将结果转换为8位。不做转换的化显示不了,显示图相只能是8U类型 Cv2.ConvertScaleAbs(ygrad, ygrad); //加强边缘检测 //Cv2.Scharr(gray, xgrad, -1, 1, 0, 3); //Cv2.Scharr(gray, ygrad, -1, 0, 1, 3); output = new Mat(gray.Size(), gray.Type()); //图像混合相加(基于权重 0.5)不精确 Cv2.AddWeighted(xgrad, 0.5, ygrad, 0.5, 0, output); return output; } catch (Exception ex) { } finally { if (gray != null) gray.Dispose(); if (xgrad != null) gray.Dispose(); if (ygrad != null) gray.Dispose(); if (output != null) gray.Dispose(); GC.Collect(); } return null; } } }