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;
}
}
}