using OpenCvSharp;
using SmartCoalApplication.Base.AuxiliaryCalcModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SmartCoalApplication.Base.CommTool
{
public class XiGaoTools
{
public static Mat temp;
public static int start, end;
private static double threshold = 85;
///
/// 寻找构件
///
///
public static List FindXiGaoHModels(Mat thresholdMat)
{
OpenCvSharp.Point[][] contours;
HierarchyIndex[] hierarchy;
Cv2.FindContours(thresholdMat, out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());
//List contoursDraw = new List();
List list = new List();
for (int i = 0; i < contours.Length; i++)
{
if (hierarchy[i].Parent == -1 && contours[i].Length > 500)
{
XiGaoHModel model = new XiGaoHModel();
model.SetPoints(contours[i]);
list.Add(model);
}
}
if (list.Count == 0 || list.Count == 1) return list;
List list_final = new List();
XiGaoHModel m = list[list.IndexOf(list.Find(b => b.topPoint.Y == list.Min(a => a.topPoint.Y)))];
list.Remove(m);
if (m.topPoint.Y == 0)
{//过滤顶部的亮条
m = list[list.IndexOf(list.Find(b => b.topPoint.Y == list.Min(a => a.topPoint.Y)))];
list.Remove(m);
}
list_final.Add(m);
list_final.Add(list[list.IndexOf(list.Find(b => b.topPoint.Y == list.Min(a => a.topPoint.Y)))]);
//for (int i = 0; i < list_final.Count; i++)
//{
// XiGaoHModel mDraw = list_final[i];
// contoursDraw.Add(mDraw.points);
//}
//Mat thresholdMatClone = thresholdMat.Clone();
//Cv2.DrawContours(thresholdMatClone, contoursDraw.ToArray(), -1, new Scalar(127), 2);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\thresholdMatClone.jpg", thresholdMatClone);
return list_final;
}
///
/// 处理连接在一起的构件
///
///
///
///
public static List FindXiGaoHModelsForConnState(Mat thresholdMat, List list_final)
{
int index = 0, y = 0;
if (list_final[1].topPoint.Y < list_final[0].topPoint.Y)
{
index = 1;
y = list_final[0].topPoint.Y;
}
if (list_final[index].topPoint.X > thresholdMat.Width / 2)
{
thresholdMat.Col[list_final[index].topPoint.X - 399] *= 0;
thresholdMat.Col[list_final[index].topPoint.X - 400] *= 0;
thresholdMat.Col[list_final[index].topPoint.X - 401] *= 0;
}
else
{
thresholdMat.Col[list_final[index].topPoint.X + 399] *= 0;
thresholdMat.Col[list_final[index].topPoint.X + 400] *= 0;
thresholdMat.Col[list_final[index].topPoint.X + 401] *= 0;
}
return FindXiGaoHModels(thresholdMat);
}
///
/// 移除小的联通区域 锡膏
///
///
///
public static Mat RemoveSmallConn(Mat mat, int area = 50)
{
Mat labels_left = new Mat();
Mat stats_left = new Mat();
Mat centroids_left = new Mat();
Cv2.ConnectedComponentsWithStats(mat, labels_left, stats_left, centroids_left, PixelConnectivity.Connectivity8);
Dictionary keyValuePairs_left = new Dictionary();
for (int h = 1; h < centroids_left.Height; h++)
{
int width = stats_left.At(h, 2);
int areaField1 = stats_left.At(h, 4);
if ((0 <= areaField1 && areaField1 <= area))
{
keyValuePairs_left.Add(h, 1);
}
}
for (int h = 1; h < labels_left.Height; h++)
{
for (int w = 1; w < labels_left.Width; w++)
{
byte v = labels_left.At(h, w);
if (v > 0 && keyValuePairs_left.ContainsKey(v))
{
mat.Set(h, w, 0);
}
}
}
return mat;
}
///
/// 移除小的联通区域 锡膏Z
///
///
///
public static Mat RemoveSmallConnZ(Mat mat, int area = 50)
{
for(int h=0; h< mat.Height-1; h++)
{
for (int w = 0; w < mat.Width-1; w++)
{
int v = mat.At(h, w);
if(v>128) mat.Set(h, w, 255);
else mat.Set(h, w, 0);
}
}
mat = mat.Dilate(null, null, 1);
OpenCvSharp.Point[][] contours;
HierarchyIndex[] hierarchy;
Cv2.FindContours(mat, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());
Mat temp = new Mat(mat.Size(), mat.Type());
Cv2.DrawContours(temp, contours, -1, new Scalar(255), 1, LineTypes.Link8);
Mat aaa = new Mat(temp.Size(), MatType.CV_8UC3);
for(int i=0; i< contours.Length; i++)
{
if(hierarchy[i].Parent==-1 && Cv2.ContourArea(contours[i]) <=30)
{
Cv2.FloodFill(mat, contours[i][0], new Scalar(0));
}
}
/*
Mat labels_left = new Mat();
Mat stats_left = new Mat();
Mat centroids_left = new Mat();
Cv2.ConnectedComponentsWithStats(mat, labels_left, stats_left, centroids_left, PixelConnectivity.Connectivity8);
Dictionary keyValuePairs_left = new Dictionary();
for (int h = 1; h < centroids_left.Height; h++)
{
int width = stats_left.At(h, 2);
int areaField1 = stats_left.At(h, 4);
if ((0 <= areaField1 && areaField1 <= area))
{
keyValuePairs_left.Add(h, 1);
}
}
for (int h = 1; h < labels_left.Height; h++)
{
for (int w = 1; w < labels_left.Width; w++)
{
byte v = labels_left.At(h, w);
if (v > 0 && keyValuePairs_left.ContainsKey(v))
{
mat.Set(h, w, 0);
}
}
}*/
return mat;
}
///
/// 二值化寻找直线
///
///
///
public unsafe static List FindLinesInThreshold(Mat mat, int topy, int topx, int type, XiGaoHModel model)
{
List lines = new List();
for (int i = 100; i < 255; i += 3)
{
start = 100;
end = i;
temp = new Mat(mat.Size(), mat.Type(), Scalar.All(0));
mat.ForEachAsByte(FindLinesInThreshold_For);
foreach (int p in lines)
{
for (int a = 0; a < temp.Width; a++)
{
if (temp.At(p, a) > 0)
Cv2.FloodFill(temp, new Point(a, p), Scalar.All(0));
}
}
if (temp.CountNonZero() > 0)
{
Mat labels = new Mat();
for (int h = topy; h < mat.Height - 2; h += 2)
{
if (type == 1)
{
Mat temp1 = new Mat(temp, new OpenCvSharp.Rect(topx - 400, h, 400, 3));
int v = temp1.CountNonZero();
if (v > 200 && temp1.ConnectedComponents(labels, PixelConnectivity.Connectivity8) < 10)
{
if (model.lowY - h > 9)
{
lines.Add(h);
h += 8;
}
}
}
else
{
Mat temp1 = new Mat(temp, new OpenCvSharp.Rect(topx, h, 400, 3));
int v = temp1.CountNonZero();
if (v > 200 && temp1.ConnectedComponents(labels, PixelConnectivity.Connectivity8) < 10)
{
if (model.lowY - h > 9)
{
lines.Add(h);
h += 8;
}
}
}
}
}
}
return lines;
}
private static unsafe void FindLinesInThreshold_For(byte* value, int* position)
{
int y = position[0];
int x = position[1];
byte v = *value;
if (v > 85 && v <= end)
temp.Set(y, x, 255);
else
temp.Set(y, x, 0);
}
public static void SamplePic1(Mat koutu_left, Mat koutu_right, XiGaoHModel left, XiGaoHModel right, int threshold, out Mat mask_left, out Mat mask_right)
{
for (int i = left.topPoint.X; i < koutu_left.Width; i++)
koutu_left.Col[i] *= 0;
for (int i = 0; i < left.topPoint.Y + 150; i++)
koutu_left.Row[i] *= 0;
for (int i = 0; i < right.topPoint.X; i++)
koutu_right.Col[i] *= 0;
for (int i = 0; i < right.topPoint.Y + 150; i++)
koutu_right.Row[i] *= 0;
mask_left = koutu_left.Threshold(threshold, 255, ThresholdTypes.Binary);
mask_right = koutu_right.Threshold(threshold, 255, ThresholdTypes.Binary);
mask_left = null;
mask_right = null;
}
public unsafe static Mat SamplePic1(Mat gray, double thres = 85)
{
threshold = thres;
Mat clone = gray.Clone();
clone.ForEachAsByte(CommFillHoleEach);
return clone;
}
public unsafe static Mat SamplePicZ(Mat gray, double thres = 85)
{
threshold = thres;
Mat clone = gray.Clone();
clone.ForEachAsByte(CommFillHoleEachZ);
return clone;
}
///
/// 第二次裁剪图片
///
///
///
///
///
///
///
///
public unsafe static void SamplePic2(Mat koutu_left, Mat koutu_right, XiGaoHModel left, XiGaoHModel right, int threshold, out Mat mask_left, out Mat mask_right)
{
//二值提取
mask_left = koutu_left.Threshold(0, 255, ThresholdTypes.Binary);
mask_right = koutu_right.Threshold(0, 255, ThresholdTypes.Binary);
//Cv2.ImWrite(@"C:\Users\zyh\Desktop\left_1.jpg", koutu_left);
//Cv2.ImWrite(@"C:\Users\zyh\Desktop\right_1.jpg", koutu_right);
//左侧
OpenCvSharp.Point[][] contours;
HierarchyIndex[] hierarchy;
Cv2.FindContours(mask_left, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());
List list_left = contours.ToList();
Mat mask_l_1 = new Mat(mask_left.Size(), MatType.CV_8UC1);
Cv2.DrawContours(mask_l_1, contours, -1, new Scalar(255), 1, LineTypes.Link8);
int left_y = -1;
for (int i = left.topPoint.Y + 150; i < mask_left.Height; i++)
{
if (mask_l_1.Row[i].CountNonZero() == 2)
{
left_y = i;
break;
}
}
if (left_y == -1) left_y = left.topPoint.Y + 200;
Cv2.FindContours(mask_right, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());
List list_right = contours.ToList();
Mat mask_r_1 = new Mat(mask_left.Size(), MatType.CV_8UC1);
Cv2.DrawContours(mask_r_1, contours, -1, new Scalar(255), 1, LineTypes.Link8);
int right_y = -1;
for (int i = right.topPoint.Y + 150; i < mask_right.Height; i++)
{
if (mask_r_1.Row[i].CountNonZero() == 2)
{
right_y = i;
break;
}
}
if (right_y == -1) right_y = right.topPoint.Y + 200;
for (int i = 0; i < right_y; i++)
{
koutu_right.Row[i] *= 0;
mask_right.Row[i] *= 0;
}
for (int i = 0; i < left_y; i++)
{
koutu_left.Row[i] *= 0;
mask_left.Row[i] *= 0;
}
for (int i = 0; i < right.topPoint.X; i++)
{
koutu_right.Col[i] *= 0;
mask_right.Col[i] *= 0;
}
for (int i = right.topPoint.X + 450; i < koutu_right.Width; i++)
{
koutu_right.Col[i] *= 0;
mask_right.Col[i] *= 0;
}
for (int i = 0; i < left.topPoint.X - 450; i++)
{
koutu_left.Col[i] *= 0;
mask_left.Col[i] *= 0;
}
for (int i = left.topPoint.X; i < koutu_left.Width; i++)
{
koutu_left.Col[i] *= 0;
mask_left.Col[i] *= 0;
}
OpenCvSharp.Point small = new Point(-1, -1);
Cv2.FindContours(koutu_left, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());
list_left = contours.ToList();
if (contours.Length >= 2)
{
for (int i = list_left.Count - 1; i >= 0; i--)
{
if (list_left[i].Count() < 50 || list_left[i].ToList().FindAll(a => a.Y < left.topPoint.Y + 10).Count > 0)
{
Cv2.FloodFill(mask_left, list_left[i][0], new Scalar(0));
list_left.RemoveAt(i);
}
}
}
contours = list_left.ToArray();
if (contours.Length >= 2)
{
int maxy = 0;
for (int i = list_left.Count - 1; i >= 0; i--)
{
if (maxy == 0)
{
maxy = list_left[i].Max(a => a.Y);
}
else
{
if (maxy < list_left[i].Max(a => a.Y))
{
maxy = list_left[i].Max(a => a.Y);
mask_left.FloodFill(list_left[i][0], new Scalar(0));
list_left.RemoveAt(i);
}
}
}
}
contours = list_left.ToArray();
if (contours.Length == 0) return;
if (contours.Length >= 2)
{
int countPoints = 0;
if (contours.Length > 2)
{
countPoints = contours.ToList().Min(a => a.Length);
}
foreach (OpenCvSharp.Point[] p in contours)
{
if (contours.Length > 2)
{
if (p.Length == countPoints)
{
mask_left.FloodFill(p[0], new Scalar(0));
break;
}
}
List ps = p.ToList();
if (left.lowY == 0)
{
left.lowY = ps.Max(a => a.Y);
}
else
{
if (left.lowY < ps.Max(a => a.Y))
left.lowY = ps.Max(a => a.Y);
}
if (left.highY == 0)
{
left.highY = ps.Min(a => a.Y);
left.highX = ps.ToList().Find(a => a.Y == left.highY).X;
}
else
{
if (left.highY > ps.Min(a => a.Y))
{
left.highY = ps.Min(a => a.Y);
left.highX = ps.ToList().Find(a => a.Y == left.highY).X;
}
}
if (small.X == -1)
{
small = ps.Find(b => b.Y == ps.Min(a => a.Y));
}
else
{
OpenCvSharp.Point t = ps.Find(b => b.Y == ps.Min(a => a.Y));
if (t.Y < small.Y)
{
small = t;
}
}
left.centerX = (ps.Min(a => a.X) + ps.Max(a => a.X)) / 2;
if (left.centerX < left.highX)
{
left.centerOffSetHighY = ps.Where(a => a.X < left.centerX - 110).ToList().Min(b => b.Y);
left.centerOffSetHighX = ps.Where(a => a.X < left.centerX - 110).ToList().Find(b => b.Y == left.centerOffSetHighY).X;
}
}
mask_left.FloodFill(small, new Scalar(0));
}
else
{
left.lowY = contours[0].Max(a => a.Y);
left.highY = contours[0].Min(a => a.Y);
left.highX = contours[0].ToList().Find(a => a.Y == left.highY).X;
left.centerX = (contours[0].Min(a => a.X) + contours[0].Max(a => a.X)) / 2;
if (left.centerX < left.highX)
{
left.centerOffSetHighY = contours[0].ToList().Where(a => a.X < left.centerX - 110).ToList().Min(b => b.Y);
left.centerOffSetHighX = contours[0].Where(a => a.X < left.centerX - 110).ToList().Find(b => b.Y == left.centerOffSetHighY).X;
}
}
small = new Point(-1, -1);
Cv2.FindContours(mask_right, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());
list_right = contours.ToList();
if (contours.Length >= 2)
{
for (int i = list_right.Count - 1; i >= 0; i--)
{
if (list_right[i].Count() < 50 || list_right[i].ToList().FindAll(a => a.Y < right.topPoint.Y + 10).Count > 0)
{
Cv2.FloodFill(mask_right, list_right[i][0], new Scalar(0));
list_right.RemoveAt(i);
}
}
}
contours = list_right.ToArray();
if (contours.Length == 0) return;
if (contours.Length >= 2)
{
int maxy = 0;
for (int i = list_right.Count - 1; i >= 0; i--)
{
if (maxy == 0)
{
maxy = list_right[i].Max(a => a.Y);
}
else
{
if (maxy < list_right[i].Max(a => a.Y))
{
maxy = list_right[i].Max(a => a.Y);
mask_right.FloodFill(list_right[i][0], new Scalar(0));
list_right.RemoveAt(i);
}
}
}
}
contours = list_right.ToArray();
if (contours.Length >= 2)
{
int countPoints = 0;
if (contours.Length > 2)
{
countPoints = contours.ToList().Min(a => a.Length);
}
int k = 0;
foreach (OpenCvSharp.Point[] p in contours)
{
if (hierarchy[k].Parent > -1)
{
break;
}
if (contours.Length > 2)
{
if (p.Length == countPoints)
{
mask_right.FloodFill(p[0], new Scalar(0));
break;
}
}
List ps = p.ToList();
if (right.lowY == 0)
{
right.lowY = ps.Max(a => a.Y);
}
else
{
if (right.lowY < ps.Max(a => a.Y))
right.lowY = ps.Max(a => a.Y);
}
if (right.highY == 0)
{
right.highY = ps.Min(a => a.Y);
right.highX = ps.ToList().Find(a => a.Y == right.highY).X;
}
else
{
if (right.highY > ps.Min(a => a.Y))
{
right.highY = ps.Min(a => a.Y);
right.highX = ps.ToList().Find(a => a.Y == right.highY).X;
}
}
if (small.X == -1)
{
small = ps.Find(b => b.Y == ps.Min(a => a.Y));
}
else
{
OpenCvSharp.Point t = ps.Find(b => b.Y == ps.Min(a => a.Y));
if (t.Y < small.Y)
{
small = t;
}
}
right.centerX = (ps.Min(a => a.X) + ps.Max(a => a.X)) / 2;
if (right.centerX > right.highX)
{
right.centerOffSetHighY = ps.Where(a => a.X > right.centerX + 110).ToList().Min(b => b.Y);
right.centerOffSetHighX = ps.Where(a => a.X > right.centerX + 110).ToList().Find(b => b.Y == right.centerOffSetHighY).X;
}
}
mask_right.FloodFill(small, new Scalar(0));
}
else
{
right.lowY = contours[0].Max(a => a.Y);
right.highY = contours[0].Min(a => a.Y);
right.highX = contours[0].ToList().Find(a => a.Y == right.highY).X;
right.centerX = (contours[0].Min(a => a.X) + contours[0].Max(a => a.X)) / 2;
if (right.centerX > right.highX)
{
right.centerOffSetHighY = contours[0].ToList().Where(a => a.X > right.centerX + 110).ToList().Min(b => b.Y);
right.centerOffSetHighX = contours[0].Where(a => a.X > right.centerX + 110).ToList().Find(b => b.Y == right.centerOffSetHighY).X;
}
}
}
private static unsafe void CommFillHoleEach(byte* value, int* position)
{
int y = position[0];
int x = position[1];
byte v = *value;
if (v < 85 && v > 0)
*value = 255;
}
private static unsafe void CommFillHoleEachZ(byte* value, int* position)
{
int y = position[0];
int x = position[1];
byte v = *value;
if (v < threshold && v > 0)
*value = 255;
if (v==0)
*value = 255;
}
///
///
///
///
/// 1左 2右
///
public static List FindLastLine(List list/*, List prevList*/, Mat mat, int type, int width = 0, int times = 1)
{
int now_l = (width == 0) ? mat.Width - 1 : width;
int now_r = width;
if (type == 1)
{
int xleft = 0;
for (int i = now_l; i >= 0; i--)
{
if (mat.Col[i].CountNonZero() == 4)
{
xleft = i;
break;
}
}
for (int i = 0; i < mat.Height - 1; i++)
{
if (mat.At(i, xleft) > 0)
list.Add(i);
}
bool pass = true;
if (list.Count == 4)
{
if (list[1] - list[0] <= 5 || list[2] - list[1] <= 5 || list[3] - list[2] <= 5)
{
pass = false;
}
}
else
{
pass = false;
}
if (pass || times > 20)
return list;// list.Count == 4 ? list : prevList;
if (!pass)
{
//if (list.Count == 4)
//{
// prevList.Clear();
// prevList.AddRange(list);
//}
list.Clear();
FindLastLine(list/*, prevList*/, mat, 1, xleft - 1, ++times);
}
}
else
{
int xright = 0;
for (int i = now_r; i < mat.Width; i++)
{
if (mat.Col[i].CountNonZero() == 4)
{
xright = i;
break;
}
}
for (int i = 0; i < mat.Height - 1; i++)
{
if (mat.At(i, xright) > 0)
list.Add(i);
}
bool pass = true;
if (list.Count == 4)
{
if (list[1] - list[0] <= 5 || list[2] - list[1] <= 5 || list[3] - list[2] <= 5)
{
pass = false;
}
}
else
{
pass = false;
}
if (pass || times > 20)
return list;// list.Count == 4 ? list : prevList;// return list;
if (!pass)
{
//if (list.Count == 4)
//{
// prevList.Clear();
// prevList.AddRange(list);
//}
list.Clear();
FindLastLine(list/*, prevList*/, mat, 2, xright + 1, ++times);
}
}
//if (list.Count == 0 && prevList.Count == 4)
// list.AddRange(prevList);
return list;
}
///
///
///
///
/// 1左 2右
///
public static List FindLastLine(List list, List prevList, Mat mat, int type, int width = 0, int times = 1)
{
int now_l = (width == 0) ? mat.Width - 1 : width;
int now_r = width;
if (type == 1)
{
int xleft = 0;
for (int i = now_l; i >= 0; i--)
{
if (mat.Col[i].CountNonZero() == 4)
{
xleft = i;
break;
}
}
for (int i = 0; i < mat.Height - 1; i++)
{
if (mat.At(i, xleft) > 0)
list.Add(i);
}
bool pass = true;
if (list.Count == 4)
{
if (list[1] - list[0] <= 5 || list[2] - list[1] <= 5 || list[3] - list[2] <= 5)
{
pass = false;
}
}
else
{
pass = false;
}
if (pass || times > 20)
return list.Count == 4 ? list : prevList;// list;//
if (!pass)
{
if (list.Count == 4)
{
prevList.Clear();
prevList.AddRange(list);
}
list.Clear();
FindLastLine(list, prevList, mat, 1, xleft - 1, ++times);
}
}
else
{
int xright = 0;
for (int i = now_r; i < mat.Width; i++)
{
if (mat.Col[i].CountNonZero() == 4)
{
xright = i;
break;
}
}
for (int i = 0; i < mat.Height - 1; i++)
{
if (mat.At(i, xright) > 0)
list.Add(i);
}
bool pass = true;
if (list.Count == 4)
{
if (list[1] - list[0] <= 5 || list[2] - list[1] <= 5 || list[3] - list[2] <= 5)
{
pass = false;
}
}
else
{
pass = false;
}
if (pass || times > 20)
return list.Count == 4 ? list : prevList;// return list;// list;//
if (!pass)
{
if (list.Count == 4)
{
prevList.Clear();
prevList.AddRange(list);
}
list.Clear();
FindLastLine(list, prevList, mat, 2, xright + 1, ++times);
}
}
if (list.Count == 0 && prevList.Count == 4)
list.AddRange(prevList);
return list;
}
public static void CClearDirtyData(Mat mat)
{
for (int i = mat.Height - 1; i >= 0; i--)
{
if (mat.Row[i].CountNonZero() > 0 && mat.Row[i].CountNonZero() < 20)
{
mat.Row[i] *= 0;
}
}
}
public unsafe static Mat ReverseNoneZeroPixel(Mat mat)
{
mat.ForEachAsByte(ReverseNoneZeroPixel_AsByte);
mat = mat.Erode(null, null, 1);
return mat;
}
private unsafe static void ReverseNoneZeroPixel_AsByte(byte* value, int* position)
{
int y = position[0];
int x = position[1];
byte v = *value;
if (v > 0)
{
*value = (byte)(255 - v);
/* byte j = (byte)(255 - v);
if(j>150)
*value = 0;
else if (j < 47)
*value = 0;*/
}
}
public static List FindAllLine(Mat koutu_left_canny, XiGaoHModel model, int lastLine, int offsetY = 23)
{
List final = new List();
List xs = new List();
List ys0 = new List();
//Dictionary dict = new Dictionary();
//Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\canny_left_3T.jpg", koutu_left_canny);
for (int i = lastLine - offsetY; i > model.topPoint.Y + 200; i--)
{
int v = koutu_left_canny.Row[i].CountNonZero();
//if (v>0)
{
//dict.Add(i, v);
xs.Add(i);
ys0.Add(v);
}
}
int[] hist_int = ys0.ToArray(); // HistTools.Smooth(ys.ToArray(), 10, ys.Count);
List temps = hist_int.ToList();
int max = temps.Max(a => a);
int max_index = temps.FindIndex(a => a == max);
int h = 0;
////过滤3(11).jpg的强干扰
//int ensureTimes = 0;
////int max_next = -1;// temps.FindIndex(a => a == max);
////for (int i = max_index + 15; i < temps.Count; i++)
////{
//// if (temps[i] > 0)
//// {
//// max_next = i;
//// break;
//// }
////}
//while (max_index > 20/*max_next == -1*/ && ++ensureTimes < 10)
//{
// hist_int[max_index] = 0;
// temps[max_index] = 0;
// max = temps.Max(a => a);
// max_index = temps.FindIndex(a => a == max);
// //max_next = -1;// temps.FindIndex(a => a == max);
// //for (int i = max_index + 15; i < temps.Count; i++)
// //{
// // if (temps[i] > 0)
// // {
// // max_next = i;
// // break;
// // }
// //}
//}
Console.WriteLine("max_index:" + max_index + "...offsetY:" + offsetY);
for (int i = max_index; i >= 0; i--)
{
if (h > 10) break;
h++;
if (hist_int[i] > 0)
{
hist_int[i] = 0;
}
/*else
{
break;
}*/
}
int g = 0;
for (int i = max_index + 1; i < hist_int.Length - 1; i++)
{
if (g > 10) break;
g++;
if (hist_int[i] > 0)
{
hist_int[i] = 0;
}
/*else
{
break;
}*/
}
if (max > 30 && Math.Abs(xs[max_index] - model.highY) >= 14)
final.Add(xs[max_index]);
temps = hist_int.ToList();
max = temps.Max(a => a);
max_index = temps.FindIndex(a => a == max);
if (max > 30 && Math.Abs(xs[max_index] - model.highY) >= 14)
final.Add(xs[max_index]);
return final;
}
public static void DisposeMat(Mat mat)
{
if (mat != null && !mat.IsDisposed) mat.Dispose();
}
///
/// 处理旋转的图像
///
///
///
public static Mat ActioSpinXiGao(Mat gray)
{
Mat gray1 = gray.Clone();
int left_top = Cv2.FloodFill(gray1, new Point(0, 0), new Scalar(0));
int right_top = Cv2.FloodFill(gray1, new Point(gray.Width-1, 0), new Scalar(0));
int right_bottom = Cv2.FloodFill(gray1, new Point(gray.Width - 1, gray.Height-1), new Scalar(0));
int left_bottom = Cv2.FloodFill(gray1, new Point(0, gray.Height - 1), new Scalar(0));
if (right_top == right_bottom && right_bottom == left_bottom)
return gray1;
return gray;
}
public static int FineTuningLastLine(int lineY, Mat gray)
{
int topY = lineY - 5;
int bottomY = lineY + 1;
List means = new List();
List ys = new List();
for (int i=topY; i< bottomY; i++)
{
means.Add((int)(gray.Row[i].Mean()));
ys.Add(i);
}
int minY = lineY;
int minV = means[5];
for(int i=0; i< means.Count; i++)
{
if(Math.Abs(means[i] - minV) <13)
{
if (means[i] < minV)
{
minV = means[i];
minY = ys[i];
}
}
}
return minY;
}
///
/// 寻找相似的轮廓
///
///
///
///
public static Mat FindSimilarContour(Mat gray)
{
Mat mask = new Mat(gray.Size(), gray.Type());
//计算直方图
float[] hist_float = HistTools.CalcHist(gray);
//直方图平滑
int[] hist_int = HistTools.Smooth(hist_float, 25);
//计算最佳阈值
List mountainsList = new List();
List mountainsArrList = new List();
List mountainsArrListBackUp = new List();
Tools.FindTopAndBetweenWithOutWT123(hist_int, 0, 255, mountainsList, mountainsArrList, mountainsArrListBackUp, new List(), 15);
int threshold = mountainsArrList[mountainsList.IndexOf(mountainsList.Min())][1] - 20;
int thresholdValue = threshold < 100 ? 130 : threshold;
//Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\grayMat.jpg", gray);
//二值化
Mat thresholdMat = gray.Threshold(thresholdValue/*-15*/, 255, ThresholdTypes.Binary);
//Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\thresholdMat.jpg", thresholdMat);
//碎屑删除
thresholdMat = thresholdMat.Dilate(null, null, 3);
//Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\thresholdMat_1.jpg", thresholdMat);
thresholdMat = BinaryTools.DebrisRemoval_New(thresholdMat.CvtColor(ColorConversionCodes.GRAY2BGR), 200).CvtColor(ColorConversionCodes.BGR2GRAY);
//Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\thresholdMat_2.jpg", thresholdMat);
//寻找需要处理的内容
OpenCvSharp.Point[][] contours;
HierarchyIndex[] hierarchy;
List models = new List();
Cv2.FindContours(thresholdMat, out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxNone, new OpenCvSharp.Point());
Mat temp = new Mat(thresholdMat.Size(), thresholdMat.Type(), Scalar.All(0));
Cv2.DrawContours(temp, contours, -1, new Scalar(255), 3, LineTypes.Link8);
//Cv2.ImWrite(@"C:\Users\zyh\Desktop\temp.jpg", temp);
for (int i = 0; i < contours.Length; i++)
{
int height = contours[i].Max(a => a.Y) - contours[i].Min(a => a.Y);
int width = contours[i].Max(a => a.X) - contours[i].Min(a => a.X);
float ratio = height * 1f / width;
if (contours[i].Length > 150 && Cv2.ContourArea(contours[i])>5000
&& height > 90
&& width < gray.Width - 50
&& (ratio>0.5 && ratio<0.9))
{//筛选用于分析的锡膏
XiGaoZModel model = new XiGaoZModel();
model.SetPoints(contours[i]);
models.Add(model);
}
}
//List models_toCal = new List();
//for (int i = 0; i < models.Count; i++)
// if (models[i].points.Length > 100 && models[i].points.Length < 1000)
// {//筛选用于分析的锡膏
// XiGaoZModel model = new XiGaoZModel();
// model.SetPoints(models[i].points);
// models_toCal.Add(model);
// }
//if (models_toCal.Count < 2)
//{
// models_toCal.Clear();
// for (int i = 0; i < models.Count; i++)
// if (models[i].points.Length > 100)
// {//筛选用于分析的锡膏
// XiGaoZModel model = new XiGaoZModel();
// model.SetPoints(models[i].points);
// models_toCal.Add(model);
// }
//}
int maxV = 0;
int now_y = 0;
for (int i = gray.Height - 1; i >0; i-=10)
{
int count = models/*models_toCal*//*models*/.Count(a => a.topY < i && a.bottomY > i);
if (maxV == 0)
{//筛选用于分析的锡膏
now_y = i;
maxV = count;
}
else
{
if(count > maxV)
{
maxV = count;
now_y = i;
}
}
}
//筛选用于分析的锡膏
List temps = models/*models_toCal*//*models*/.FindAll(a => a.topY < now_y && a.bottomY > now_y);
var array = temps.Select(a => a.points).ToArray();
Cv2.DrawContours(mask, array, -1, new Scalar(255), -1, LineTypes.Link8);
//Mat mask222 = new Mat(gray.Size(), gray.Type());
//Cv2.DrawContours(mask222, array, -1, new Scalar(255), 5, LineTypes.Link8);
//Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\mask222.jpg", mask222);
return mask;
}
public static List FindAllLineZ(Mat src, XiGaoZModel model, int offsetY = 23)
{
Mat mat = 255 - src;
//去碎屑
mat = RemoveSmallConnZ(mat.Erode(null, null, 1), src.Width>300 ? 30 : 10);
int hs = 5;
if(mat.Width<300)
{
mat = mat.Erode(null, null, 1);
}
List final = new List();
List xs = new List();
List ys = new List();
Dictionary dict = new Dictionary();
for (int i = (int)(mat.Height*0.92); i >= hs; i--)
{
int sum = (int)(mat[i, i + 1, 0, mat.Width].Sum());
int noneZeroCount = mat[i - hs, i, 0, mat.Width].CountNonZero();
if(noneZeroCount > src.Width)
{
final.Add(i);
i -= 2;// 5;// 2;// 5;
}
}
final.Sort();
while (final.Count > 2 && final[final.Count - 1] - final[final.Count - 1 - 1] < 10)
{
final.RemoveAt(final.Count - 1 - 1);
}
if (final.Count>2)
{
for(int i= final.Count-1; i>0; i--)
{
if(final[i] - final[i-1]<10)
{
if (i == 1 && Math.Max(final[i - 1], final[i]) < 20)
{
final.RemoveAt(i - 1);
break;
}
else
final.RemoveAt(i);
}
}
}
else if(final.Count == 1)
{
final.Clear();
final.Add((int)(src.Height * 0.9) - 3);
final.Add((int)(src.Height / 2) + 1);
}
else if(final.Count==0)
{
final.Add((int)(src.Height * 0.9) - 3);
final.Add((int)(src.Height /2 ) + 1);
}
if (final.Count == 2)
{
if (final[1] - final[0] > mat.Height / 2)
{
final.Insert(1, mat.Height / 2 + 20);
}
}
//顶部校验
if(final.Count == 3)
{
}
int v = mat.Row[final.Count - 1].CountNonZero();
for (int i= final[final.Count-1]; i> final[final.Count - 1] - 6; i--)
{
int d = mat.Row[i].CountNonZero();
if(d>v)
{
v = d;
final[final.Count - 1] = i;
}
}
return final;
}
}
}