using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;
using SmartCoalApplication.Base.CommTool;
namespace SmartCoalApplication.Base.AutoMeasure
{
public class Ceju
{
///
/// 对图像进行二值化,得到产品目标区域
///
/// 单通道图像,一般是红色通道
/// 输出二值图
public void GetContour(Mat image, out Mat imageContour)
{
// 均值滤波
Mat imageFilter = new Mat();
Cv2.Blur(image, imageFilter, new OpenCvSharp.Size(5, 5));
// 二值化,获得目标区域
imageContour = imageFilter.Threshold(0, 1, ThresholdTypes.Otsu);
//new Window("contour", WindowMode.Normal, imageContour * 255);
// 闭运算,消除小孔
Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(10, 10));// 结构元素
Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se);
Mat fillContour = new Mat();
Fill(imageContour, out fillContour, 1);
//new Window("close", WindowMode.Normal, imageContour * 255);
//new Window("fill", WindowMode.Normal, fillContour * 255);
//Cv2.WaitKey();
Mat fanse = 1 - fillContour;
Scalar sum = fanse.Sum();
Scalar sumBefore = imageContour.Sum();
Scalar sumAfter = fillContour.Sum();
int areaDifference = (int)sumAfter - (int)sumBefore;
if ((int)sum != 0)//避免整张图全填充
{
if (areaDifference < 100)//避免填充区域过多
imageContour = fillContour;
}
#region[清理内存]
//if (imageFilter != null)
//{
// imageFilter.Dispose();
//}
//if (fillContour != null)
//{
// fillContour.Dispose();
//}
#endregion
}
public void GetContourTongkongShuangceng(Mat image, out Mat imageContour)
{
// 均值滤波
Mat imageFilter = new Mat();
Cv2.Blur(image, imageFilter, new OpenCvSharp.Size(5, 5));
// 二值化,获得目标区域
imageContour = imageFilter.Threshold(0, 1, ThresholdTypes.Otsu);
//new Window("contour", WindowMode.Normal, imageContour * 255);
// 开运算,消除杂质,闭运算,消除小孔
Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(10, 10));// 结构元素
Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Open, se);
Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se);
Mat fillContour = new Mat();
Fill(imageContour, out fillContour, 1);
//new Window("close", WindowMode.Normal, imageContour * 255);
//new Window("fill", WindowMode.Normal, fillContour * 255);
//Cv2.WaitKey();
Mat fanse = 1 - fillContour;
Scalar sum = fanse.Sum();
Scalar sumBefore = imageContour.Sum();
Scalar sumAfter = fillContour.Sum();
int areaDifference = (int)sumAfter - (int)sumBefore;
if ((int)sum != 0)//避免整张图全填充
{
if (areaDifference < 100)//避免填充区域过多
imageContour = fillContour;
}
}
public void GetShenmangkongContour(Mat image, out Mat imageContour)
{
// 均值滤波
Mat imageFilter = new Mat();
Cv2.Blur(image, imageFilter, new OpenCvSharp.Size(5, 5));
// 二值化,获得目标区域
imageContour = imageFilter.Threshold(0, 1, ThresholdTypes.Otsu);
//膨胀
Mat seDilate = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(20, 1));
Mat dilate = new Mat();
Cv2.Dilate(imageContour, dilate, seDilate);
// 闭运算,消除小孔
Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(15, 15));// 结构元素
Cv2.MorphologyEx(dilate, imageContour, MorphTypes.Close, se);
Mat fillContour = new Mat();
Fill(imageContour, out fillContour, 1);
//new Window("fill", WindowMode.Normal, fillContour * 255);
//Cv2.WaitKey();
Mat fanse = 1 - fillContour;
Scalar sum = fanse.Sum();
Scalar sumBefore = imageContour.Sum();
Scalar sumAfter = fillContour.Sum();
int areaDifference = (int)sumAfter - (int)sumBefore;
if ((int)sum != 0)//避免整张图全填充
{
if (areaDifference < 2000)//避免填充区域过多
imageContour = fillContour;
}
}
///
/// 对图片进行上下裁剪,去掉空白的部分
///
/// 输入二值图像
/// 输出去掉的上下边界
/// 输出裁剪后的图片
public void Crop(Mat image, out int[] y, out Mat cropContour, bool isCropFlag)
{
int range = 300;
if (isCropFlag)
range = 15;
y = new int[2] { 0, 0 };
for (int i = range; i < image.Rows; i++)
{
for (int j = 0; j < image.Cols; j++)
{
if (image.Get(i, j) > 0)
{
y[0] = i;
break;
}
}
if (y[0] != 0)
break;
}
for (int i = image.Rows - range; i > range; i--)
{
for (int j = 0; j < image.Cols; j++)
{
if (image.Get(i, j) > 0)
{
y[1] = i;
break;
}
}
if (y[1] != 0)
break;
}
cropContour = image[y[0], y[1], 0, image.Cols - 1];
}
///
/// 对全图片进行裁剪,去掉上下空白的地方,左右被亮光影响的地方
///
/// 原图
/// 上下裁剪后边缘图,用作提取孔铜
/// 裁剪的上下边界
/// 用来裁剪槽孔区域的左右边界
public void Crop2(Mat image, out Mat cropEdge, out int[] y, out int[] b, bool isCropFlag)
{
//获得蓝色,绿色,红色通道图片
Mat[] bgr = Cv2.Split(image);
Mat imageBlue = bgr[0];
Mat imageGreen = bgr[1];
Mat imageRed = bgr[2];
// 调色
Mat imageNew = 0.9 * imageGreen + 0.1 * imageRed;
//滤波
Mat filter = new Mat();
Cv2.BilateralFilter(imageNew, filter, 15, 150, 3);
// 增强
Mat zengqiang = new Mat();
InputArray kernel = InputArray.Create(new int[3, 3] { { 0, -1, 0 }, { -1, 5, -1 }, { 0, -1, 0 } });
Cv2.Filter2D(filter, zengqiang, -1, kernel);
Cv2.ConvertScaleAbs(zengqiang, zengqiang);
//边缘检测
Mat grad_x2 = new Mat();
Sobel(zengqiang, out grad_x2);
//开运算
Mat seOpen = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素
Mat open = new Mat();
Cv2.MorphologyEx(grad_x2, open, MorphTypes.Open, seOpen);
////閉運算
Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));// 结构元素
Mat close = new Mat();
Cv2.MorphologyEx(open, close, MorphTypes.Close, se);
Mat thresh2 = close.Threshold(0, 1, ThresholdTypes.Otsu);
//填充
Mat fill = new Mat();
Fill(thresh2, out fill, 1);
//new Window("grad", WindowMode.Normal, grad_x2.Threshold(0, 255, ThresholdTypes.Otsu));
//new Window("open", WindowMode.Normal, open);
//new Window("close", WindowMode.Normal, close);
//Cv2.WaitKey();
Ceju ceju = new Ceju();
y = new int[2];
ceju.Crop(fill, out y, out fill, isCropFlag);//用来计算左右裁剪边界
//Mat edge = grad_x2.Threshold(0, 1, ThresholdTypes.Otsu);
cropEdge = thresh2[y[0], y[1], 0, thresh2.Cols - 1];//用来计算孔铜边缘
b = new int[4] { 0, 0, 0, 0 };
int sum = 0;
int range = 100;
if (isCropFlag)
range = 15;
for (int j = range; j < fill.Cols - 1; j++)
{
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
b[0] = j;
break;
}
}
if (b[0] != 0)
break;
}
for (int j = b[0] + 100; j < fill.Cols - 1; j++)
{
sum = 0;
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
sum = 1;
break;
}
}
if (sum == 0)
{
b[1] = j;
break;
}
}
if (b[1] - b[0] < 300)
{
b[0] = 0;
for (int j = b[1] + 50; j < fill.Cols - 1; j++)
{
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
b[0] = j;
break;
}
}
if (b[0] != 0)
break;
}
for (int j = b[0] + 50; j < fill.Cols - 1; j++)
{
sum = 0;
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
sum = 1;
break;
}
}
if (sum == 0)
{
b[1] = j;
break;
}
}
}
for (int j = fill.Cols - range; j > 0; j--)
{
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
b[3] = j;
break;
}
}
if (b[3] != 0)
break;
}
for (int j = b[3] - 100; j > 0; j--)
{
sum = 0;
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
sum = 1;
break;
}
}
if (sum == 0)
{
b[2] = j;
break;
}
}
if (b[3] - b[2] < 300)
{
b[3] = 0;
for (int j = b[2] - 50; j > 0; j--)
{
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
b[3] = j;
break;
}
}
if (b[3] != 0)
break;
}
for (int j = b[3] - 50; j > 0; j--)
{
sum = 0;
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
sum = 1;
break;
}
}
if (sum == 0)
{
b[2] = j;
break;
}
}
}
}
///
/// 用于四层孔径的裁剪,减小了左右裁剪的判定标准,其他同Crop2
///
///
///
///
///
public void CropSicengKongjing(Mat image, out Mat cropEdge, out int[] y, out int[] b, bool isCropFlag)
{
//获得蓝色,绿色,红色通道图片
Mat[] bgr = Cv2.Split(image);
Mat imageBlue = bgr[0];
Mat imageGreen = bgr[1];
Mat imageRed = bgr[2];
// 调色
Mat imageNew = 0.9 * imageGreen + 0.1 * imageRed;
//滤波
Mat filter = new Mat();
Cv2.BilateralFilter(imageNew, filter, 15, 150, 3);
// 增强
Mat zengqiang = new Mat();
InputArray kernel = InputArray.Create(new int[3, 3] { { 0, -1, 0 }, { -1, 5, -1 }, { 0, -1, 0 } });
Cv2.Filter2D(filter, zengqiang, -1, kernel);
Cv2.ConvertScaleAbs(zengqiang, zengqiang);
//边缘检测
Mat grad_x2 = new Mat();
Sobel(zengqiang, out grad_x2);
//开运算
Mat seOpen = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素
Mat open = new Mat();
Cv2.MorphologyEx(grad_x2, open, MorphTypes.Open, seOpen);
////閉運算
Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));// 结构元素
Mat close = new Mat();
Cv2.MorphologyEx(open, close, MorphTypes.Close, se);
Mat thresh2 = close.Threshold(0, 1, ThresholdTypes.Otsu);
//填充
Mat fill = new Mat();
Fill(thresh2, out fill, 1);
Ceju ceju = new Ceju();
y = new int[2];
ceju.Crop(fill, out y, out fill, isCropFlag);//用来计算左右裁剪边界
//Mat edge = grad_x2.Threshold(0, 1, ThresholdTypes.Otsu);
cropEdge = thresh2[y[0], y[1], 0, thresh2.Cols - 1];//用来计算孔铜边缘
b = new int[4] { 0, 0, 0, 0 };
int sum = 0;
int range = 100;
if (isCropFlag)
range = 15;
for (int j = range; j < fill.Cols - 1; j++)
{
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
b[0] = j;
break;
}
}
if (b[0] != 0)
break;
}
for (int j = b[0] + 100; j < fill.Cols - 1; j++)
{
sum = 0;
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
sum = 1;
break;
}
}
if (sum == 0)
{
b[1] = j;
break;
}
}
if (b[1] - b[0] < 50)
{
b[0] = 0;
for (int j = b[1] + 50; j < fill.Cols - 1; j++)
{
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
b[0] = j;
break;
}
}
if (b[0] != 0)
break;
}
for (int j = b[0] + 50; j < fill.Cols - 1; j++)
{
sum = 0;
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
sum = 1;
break;
}
}
if (sum == 0)
{
b[1] = j;
break;
}
}
}
for (int j = fill.Cols - range; j > 0; j--)
{
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
b[3] = j;
break;
}
}
if (b[3] != 0)
break;
}
for (int j = b[3] - 100; j > 0; j--)
{
sum = 0;
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
sum = 1;
break;
}
}
if (sum == 0)
{
b[2] = j;
break;
}
}
if (b[3] - b[2] < 50)
{
b[3] = 0;
for (int j = b[2] - 50; j > 0; j--)
{
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
b[3] = j;
break;
}
}
if (b[3] != 0)
break;
}
for (int j = b[3] - 50; j > 0; j--)
{
sum = 0;
for (int i = 0; i < fill.Rows - 1; i++)
{
if (fill.Get(i, j) > 0)
{
sum = 1;
break;
}
}
if (sum == 0)
{
b[2] = j;
break;
}
}
}
}
///
/// 去掉槽孔的亮光,并裁剪
///
/// 上下裁剪后的图片
/// 输出裁剪后的边界
/// 输出裁剪后的图片
/// 选择槽孔的左右位置,left/right
public void CropLight(Mat cropContour, out int border, out Mat cropContour2, string direction)
{
int[] b = new int[4] { 0, 0, 0, 0 };
int sum = 0;
border = 0;
cropContour2 = new Mat();
switch (direction)
{
case "left":
for (int j = 0; j < cropContour.Cols; j++)
{
for (int i = 0; i < cropContour.Rows; i++)
{
if (cropContour.Get(i, j) > 0)
{
b[0] = j;
break;
}
}
if (b[0] != 0)
break;
}
for (int j = b[0]; j < cropContour.Cols; j++)
{
sum = 0;
for (int i = 0; i < cropContour.Rows; i++)
{
sum += cropContour.Get(i, j);
}
if (sum == 0)
{
b[1] = j;
break;
}
}
for (int j = cropContour.Cols - 1; j > b[1]; j--)
{
for (int i = 0; i < cropContour.Rows; i++)
{
if (cropContour.Get(i, j) > 0)
{
b[3] = j;
break;
}
}
if (b[3] != 0)
break;
}
for (int j = b[3]; j > b[1]; j--)
{
sum = 0;
for (int i = 0; i < cropContour.Rows; i++)
{
sum += cropContour.Get(i, j);
}
if (sum == 0)
{
b[2] = j;
break;
}
}
if (b[1] - b[0] > 500)
{
if (Math.Abs(b[2] - b[1]) > 50)
{
cropContour2 = cropContour[0, cropContour.Rows - 1, b[0], b[1]];
border = b[0];
}
else
cropContour2 = cropContour[0, cropContour.Rows - 1, 0, cropContour.Cols - 1];
}
else
{
cropContour2 = cropContour[0, cropContour.Rows - 1, 0, b[3]];
border = 0;
}
break;
case "right":
for (int j = cropContour.Cols - 1; j > 0; j--)
{
for (int i = 0; i < cropContour.Rows; i++)
{
if (cropContour.Get(i, j) > 0)
{
b[3] = j;
break;
}
}
if (b[3] != 0)
break;
}
for (int j = b[3]; j > 0; j--)
{
sum = 0;
for (int i = 0; i < cropContour.Rows; i++)
{
sum += cropContour.Get(i, j);
}
if (sum == 0)
{
b[2] = j;
break;
}
}
for (int j = 0; j < b[2]; j++)
{
for (int i = 0; i < cropContour.Rows; i++)
{
if (cropContour.Get(i, j) > 0)
{
b[0] = j;
break;
}
}
if (b[0] != 0)
break;
}
for (int j = b[0]; j < b[2]; j++)
{
sum = 0;
for (int i = 0; i < cropContour.Rows; i++)
{
sum += cropContour.Get(i, j);
}
if (sum == 0)
{
b[1] = j;
break;
}
}
if (b[3] - b[2] > 500)
{
if (Math.Abs(b[2] - b[1]) > 50)
{
cropContour2 = cropContour[0, cropContour.Rows - 1, b[2], cropContour.Cols - 1];
border = b[2];
}
else
cropContour2 = cropContour[0, cropContour.Rows - 1, 0, cropContour.Cols - 1];
}
else
{
cropContour2 = cropContour[0, cropContour.Rows - 1, b[0], cropContour.Cols - 1];
border = b[0];
}
break;
default:
break;
}
}
///
/// 针对双层深盲孔进行裁剪,上面空白区域较小,因此从第0行开始
///
///
///
///
public void CropShenmangkongShuangceng(Mat image, out int[] y, out Mat cropContour, bool isCropFlag)
{
Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));
Cv2.MorphologyEx(image, image, MorphTypes.Open, se);
int range = 200;
if (isCropFlag)
range = 15;
y = new int[2] { 0, 0 };
for (int i = 0; i < image.Rows; i++)
{
for (int j = range; j < image.Cols - range; j++)
{
if (image.Get(i, j) > 0)
{
y[0] = i - 10;
break;
}
}
if (y[0] != 0)
break;
}
for (int i = image.Rows - 1; i > y[0]; i--)
{
for (int j = range; j < image.Cols - range; j++)
{
if (image.Get(i, j) > 0)
{
y[1] = i + 10;
break;
}
}
if (y[1] != 0)
break;
}
cropContour = image[y[0], y[1], 0, image.Cols - 1];
}
///
/// 圖片旋轉之後出現白邊,去掉白邊
///
///
///
///
public void CropBothSide(Mat image, out Mat crop, out int range)
{
range = 50;
crop = image[range, image.Rows - range, range, image.Cols - range].Clone();
}
//public void CropLight2(Mat image, out int border, out Mat cropImage, string direction)
//{
// Mat filter = new Mat();
// Cv2.BilateralFilter(image, filter, 15, 150, 3);
// // 增强
// Mat zengqiang = new Mat();
// InputArray kernel = InputArray.Create(new int[3, 3] { { 0, -1, 0 }, { -1, 5, -1 }, { 0, -1, 0 } });
// Cv2.Filter2D(filter, zengqiang, -1, kernel);
// Cv2.ConvertScaleAbs(zengqiang, zengqiang);
// //边缘检测
// Mat grad_x = new Mat();
// Mat grad_x2 = new Mat();
// //Cv2.Sobel(zengqiang, grad_x, MatType.CV_16S, 1, 0);
// //Cv2.ConvertScaleAbs(grad_x, grad_x2);
// CejuFunction.Sobel(zengqiang, out grad_x2);
// ////腐蚀
// //Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(1, 5));
// //Mat erode = new Mat();
// //Cv2.Erode(grad_x2, erode, se);
// //开运算
// Mat seOpen = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素
// Mat open = new Mat();
// //Cv2.MorphologyEx(close, openAfterClose,MorphTypes.Open, seOpen);
// Cv2.MorphologyEx(grad_x2, open, MorphTypes.Open, seOpen);
// ////閉運算
// Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素
// Mat close = new Mat();
// Cv2.MorphologyEx(open, close, MorphTypes.Close, se);
// Mat thresh2 = close.Threshold(0, 1, ThresholdTypes.Otsu);
// //填充
// Mat fill = new Mat();
// CejuFunction.Fill(thresh2, out fill, 1);
// int[] b = new int[4] { 0, 0, 0, 0 };
// int sum = 0;
// border = 0;
// cropImage = new Mat();
// switch (direction)
// {
// case "left":
// for (int j = 0; j < fill.Cols; j++)
// {
// for (int i = 0; i < fill.Rows; i++)
// {
// if (fill.Get(i, j) > 0)
// {
// b[0] = j;
// break;
// }
// }
// if (b[0] != 0)
// break;
// }
// for (int j = b[0]; j < fill.Cols; j++)
// {
// sum = 0;
// for (int i = 0; i < fill.Rows; i++)
// {
// sum += fill.Get(i, j);
// }
// if (sum == 0)
// {
// b[1] = j;
// break;
// }
// }
// for (int j = fill.Cols - 1; j > b[1]; j--)
// {
// for (int i = 0; i < fill.Rows; i++)
// {
// if (fill.Get(i, j) > 0)
// {
// b[3] = j;
// break;
// }
// }
// if (b[3] != 0)
// break;
// }
// for (int j = b[3]; j > b[1]; j--)
// {
// sum = 0;
// for (int i = 0; i < fill.Rows; i++)
// {
// sum += fill.Get(i, j);
// }
// if (sum == 0)
// {
// b[2] = j;
// break;
// }
// }
// if (b[1] - b[0] > 500)
// {
// if (Math.Abs(b[2] - b[1]) > 50)
// {
// cropImage = fill[0, fill.Rows - 1, b[0], b[1]];
// border = b[0];
// }
// else
// cropImage = fill[0, fill.Rows - 1, 0, fill.Cols - 1];
// }
// else
// {
// cropImage = fill[0, fill.Rows - 1, 0, b[3]];
// border = 0;
// }
// break;
// case "right":
// for (int j = fill.Cols - 1; j > 0; j--)
// {
// for (int i = 0; i < fill.Rows; i++)
// {
// if (fill.Get(i, j) > 0)
// {
// b[3] = j;
// break;
// }
// }
// if (b[3] != 0)
// break;
// }
// for (int j = b[3]; j > 0; j--)
// {
// sum = 0;
// for (int i = 0; i < fill.Rows; i++)
// {
// sum += fill.Get(i, j);
// }
// if (sum == 0)
// {
// b[2] = j;
// break;
// }
// }
// for (int j = 0; j < b[2]; j++)
// {
// for (int i = 0; i < fill.Rows; i++)
// {
// if (fill.Get(i, j) > 0)
// {
// b[0] = j;
// break;
// }
// }
// if (b[0] != 0)
// break;
// }
// for (int j = b[0]; j < b[2]; j++)
// {
// sum = 0;
// for (int i = 0; i < fill.Rows; i++)
// {
// sum += fill.Get(i, j);
// }
// if (sum == 0)
// {
// b[1] = j;
// break;
// }
// }
// if (b[3] - b[2] > 500)
// {
// if (Math.Abs(b[2] - b[1]) > 50)
// {
// cropImage = fill[0, fill.Rows - 1, b[2], fill.Cols - 1];
// border = b[2];
// }
// else
// cropImage = fill[0, fill.Rows - 1, 0, fill.Cols - 1];
// }
// else
// {
// cropImage = fill[0, fill.Rows - 1, b[0], fill.Cols - 1];
// border = b[0];
// }
// break;
// default:
// break;
// }
//}
///
/// 提取数据的提取区域
///
/// 输入去掉亮光后的图片
/// 输出提取区域dataArea[0]左,dataArea[1]右
/// /// 槽孔的位置方向,left/right
public void GetDataArea(Mat cropContour2, out int[] dataArea, string direction)
{
int[] rowSum = new int[cropContour2.Rows];
int max = 0;
int fillBorder = 0;
for (int i = 0; i < cropContour2.Rows; i++)
{
for (int j = 0; j < cropContour2.Cols; j++)
rowSum[i] += cropContour2.Get(i, j);
}
max = rowSum.Max();
for (int i = 0; i < rowSum.Length; i++)
{
if (rowSum[i] > max - 50)
{
fillBorder = i;
break;
}
}
Mat fill = cropContour2.Clone();
Cv2.Rectangle(fill, new Rect(0, fillBorder, cropContour2.Cols, cropContour2.Rows - fillBorder), new Scalar(1), -1);
//提取區域
dataArea = new int[2] { 0, 0 };
int[] colSum = new int[fill.Cols];
for (int j = 100; j < fill.Cols - 100; j++)
{
for (int i = 0; i < fill.Rows; i++)
{
colSum[j] += fill.Get(i, j);
}
}
max = colSum.Max();
switch (direction)
{
case "right":
//for (int j = 0; j < colSum.Length; j++)
//{
// if (colSum[j] > max - 10)
// {
// dataArea[0] = j+100;
// break;
// }
//}
dataArea[0] = 100;
for (int j = dataArea[0] + 100; j < colSum.Length - 100; j++)
{
if (colSum[j] > max - 10)
{
dataArea[1] = j;
break;
}
}
if (dataArea[1] == 0)
dataArea[1] = dataArea[0] + 100;
//dataArea[0] = 100;
if (dataArea[1] - dataArea[0] > 200)
dataArea[1] = dataArea[0] + 200;
break;
case "left":
//for (int j = colSum.Length - 1; j > 0; j--)
//{
// if (colSum[j] > max - 10)
// {
// dataArea[1] = j+100;
// break;
// }
//}
dataArea[1] = cropContour2.Cols - 100;
for (int j = dataArea[1] - 100; j > 100; j--)
{
if (colSum[j] > max - 10)
{
dataArea[0] = j;
break;
}
}
if (dataArea[0] == 0)
dataArea[0] = dataArea[1] - 100;
//dataArea[1] = cropContour2.Cols - 100;
if (dataArea[1] - dataArea[0] > 200)
dataArea[0] = dataArea[1] - 200;
break;
}
}
///
/// 得到浅盲孔的数据提取区域
///
/// 裁剪后的二值图像
/// 输出提取区域,从左至右分别是[0][1][2][3]
public void GetMangkongDataAreaForQian(Mat cropContour, out int[] dataArea)
{
dataArea = new int[4];
int[] middleArea = new int[2];
int[] sum = new int[cropContour.Cols];
//每列求和
for (int j = 0; j < cropContour.Cols; j++)
{
sum[j] = 0;
for (int i = 0; i < cropContour.Rows; i++)
{
sum[j] += cropContour.Get(i, j);
}
}
//求中部区域
int max = sum.Max();
for (int j = 0; j < sum.Length; j++)
{
if (sum[j] > max - 10)
{
middleArea[0] = j;
break;
}
}
for (int j = sum.Length - 1; j > 0; j--)
{
if (sum[j] > max - 10)
{
middleArea[1] = j;
break;
}
}
//第一次容错
if(middleArea[1]- middleArea[0] < 100)
{
for (int j = 0; j < sum.Length; j++)
{
if (sum[j] > max - 20)
{
middleArea[0] = j;
break;
}
}
for (int j = sum.Length - 1; j > 0; j--)
{
if (sum[j] > max - 20)
{
middleArea[1] = j;
break;
}
}
}
//每行求和
int[] rowsSum = new int[cropContour.Rows];
for (int i = 0; i < cropContour.Rows; i++)
{
rowsSum[i] = 0;
for (int j = 0; j < cropContour.Cols; j++)
{
rowsSum[i] += cropContour.Get(i, j);
}
}
//得到填充上界,其下填为0
max = rowsSum.Max();
int fillBorder = new int();
for (int i = 0; i < rowsSum.Length; i++)
{
if (rowsSum[i] > max / 2)
{
fillBorder = i;
break;
}
}
Mat fill = cropContour.Clone();
Cv2.Rectangle(fill, new Rect(0, fillBorder, cropContour.Cols, cropContour.Rows - fillBorder), new Scalar(1), -1);
//每列求和
int[] colSum = new int[fill.Cols];
for (int j = 0; j < fill.Cols; j++)
{
colSum[j] = 0;
for (int i = 0; i < fill.Rows; i++)
{
colSum[j] += fill.Get(i, j);
}
}
//左,右最大值
int[] left = colSum.Skip(middleArea[0] - 500).Take(500).ToArray();
int[] right = colSum.Skip(middleArea[1]).Take(500).ToArray();
int leftMax = left.Max();
int rightMax = right.Max();
//数据提取区域
int range = 100;
if (colSum[middleArea[0] - 100] < leftMax - 10 || colSum[middleArea[1] + 100] < rightMax - 10)
range = 0;
for (int j = middleArea[0] - range; j > middleArea[0] - 500 && j > 0; j--)
{
if (colSum[j] > leftMax - 10)
{
dataArea[1] = j;
break;
}
}
if (dataArea[1] == 0) dataArea[1] = leftMax;
for (int j = dataArea[1] - 100; j < dataArea[1]; j++)
{
if (colSum[j] > leftMax - 10)
{
dataArea[0] = j;
break;
}
}
for (int j = middleArea[1] + range; j < middleArea[1] + 500; j++)
{
if (colSum[j] > rightMax - 5)
{
dataArea[2] = j;
break;
}
}
for (int j = dataArea[2] + 100; j > dataArea[2]; j--)
{
if (colSum[j] > rightMax - 5)
{
dataArea[3] = j;
break;
}
}
if (dataArea[1] == 0)
{
dataArea[1] = middleArea[0] - 70;//不加100是因为出去还要加20
dataArea[0] = dataArea[1] - 100;
}
if (dataArea[0] == 0)
{
dataArea[0] = dataArea[1] - 100;
if (colSum[dataArea[0]] < leftMax - 10)
dataArea[0] = dataArea[1] - 30;
}
if (dataArea[2] == 0)
{
dataArea[2] = middleArea[1] + 70;//不加100是因为出去还要加20
dataArea[3] = dataArea[2] + 100;
}
if (dataArea[3] == 0)
{
dataArea[3] = dataArea[2] + 100;
if (colSum[dataArea[3]] < rightMax - 10)//防止加完出界
dataArea[3] = dataArea[2] + 30;
}
if (dataArea[1] - dataArea[0] < 50)
dataArea[1] += 50;
if (dataArea[3] - dataArea[2] < 50)
dataArea[2] -= 50;
}
///
/// 得到浅盲孔的数据提取区域
///
/// 裁剪后的二值图像
/// 输出提取区域,从左至右分别是[0][1][2][3]
public void GetMangkongDataArea(Mat cropContour, out int[] dataArea)
{
dataArea = new int[4];
int[] middleArea = new int[2];
int[] sum = new int[cropContour.Cols];
//每列求和
for (int j = 0; j < cropContour.Cols; j++)
{
sum[j] = 0;
for (int i = 0; i < cropContour.Rows; i++)
{
sum[j] += cropContour.Get(i, j);
}
}
//求中部区域
int max = sum.Max();
for (int j = 0; j < sum.Length; j++)
{
if (sum[j] > max - 20)
{
middleArea[0] = j;
break;
}
}
for (int j = sum.Length - 1; j > 0; j--)
{
if (sum[j] > max - 20)
{
middleArea[1] = j;
break;
}
}
//第一次容错
if (middleArea[1] - middleArea[0] < 110)
{
for (int j = 0; j < sum.Length; j++)
{
if (sum[j] > max - 80)
{
middleArea[0] = j;
break;
}
}
for (int j = sum.Length - 1; j > 0; j--)
{
if (sum[j] > max - 80)
{
middleArea[1] = j;
break;
}
}
}
//每行求和
int[] rowsSum = new int[cropContour.Rows];
for (int i = 0; i < cropContour.Rows; i++)
{
rowsSum[i] = 0;
for (int j = 0; j < cropContour.Cols; j++)
{
rowsSum[i] += cropContour.Get(i, j);
}
}
//得到填充上界,其下填为0
max = rowsSum.Max();
int fillBorder = new int();
for (int i = 0; i < rowsSum.Length; i++)
{
if (rowsSum[i] > max / 2)
{
fillBorder = i;
break;
}
}
Mat fill = cropContour.Clone();
Cv2.Rectangle(fill, new Rect(0, fillBorder, cropContour.Cols, cropContour.Rows - fillBorder), new Scalar(1), -1);
//每列求和
int[] colSum = new int[fill.Cols];
for (int j = 0; j < fill.Cols; j++)
{
colSum[j] = 0;
for (int i = 0; i < fill.Rows; i++)
{
colSum[j] += fill.Get(i, j);
}
}
//左,右最大值
int[] left = colSum.Skip(middleArea[0] - 500).Take(500).ToArray();
int[] right = colSum.Skip(middleArea[1]).Take(500).ToArray();
int leftMax = left.Max();
int rightMax = right.Max();
//数据提取区域
int range = 100;
if (colSum[middleArea[0] - 100] < leftMax - 10 || colSum[middleArea[1] + 100] < rightMax - 10)
range = 0;
for (int j = middleArea[0] - range; j > middleArea[0] - 500 && j > 0; j--)
{
if (colSum[j] > leftMax - 10)
{
dataArea[1] = j;
break;
}
}
for (int j = dataArea[1] - 100; j < dataArea[1]; j++)
{
if (colSum[j] > leftMax - 10)
{
dataArea[0] = j;
break;
}
}
for (int j = middleArea[1] + range; j < middleArea[1] + 500; j++)
{
if (colSum[j] > rightMax - 5)
{
dataArea[2] = j;
break;
}
}
for (int j = dataArea[2] + 100; j > dataArea[2]; j--)
{
if (colSum[j] > rightMax - 5)
{
dataArea[3] = j;
break;
}
}
if (dataArea[1] == 0)
{
dataArea[1] = middleArea[0] - 70;//不加100是因为出去还要加20
dataArea[0] = dataArea[1] - 100;
}
if (dataArea[0] == 0)
{
dataArea[0] = dataArea[1] - 100;
if (colSum[dataArea[0]] < leftMax - 10)
dataArea[0] = dataArea[1] - 30;
}
if (dataArea[2] == 0)
{
dataArea[2] = middleArea[1] + 70;//不加100是因为出去还要加20
dataArea[3] = dataArea[2] + 100;
}
if (dataArea[3] == 0)
{
dataArea[3] = dataArea[2] + 100;
if (colSum[dataArea[3]] < rightMax - 10)//防止加完出界
dataArea[3] = dataArea[2] + 30;
}
if (dataArea[1] - dataArea[0] < 50)
dataArea[1] += 50;
if (dataArea[3] - dataArea[2] < 50)
dataArea[2] -= 50;
}
///
/// 提取第一條橫綫縱坐標
///
/// 輸入二值化圖像
/// 輸出坐標
/// 左邊界
/// 右边界
/// 大于等于0时,记录大于0的点,小于0记录等于零的点
public void ExtractLines(Mat image, out double averageCoordinateNew, int leftBorder, int rightBorder, int direction)
{
//数组长宽
int rows = image.Rows;
int cols = image.Cols;
int count = 0;
int sum = 0;
// 对循环次数计数,防止程序卡死
int circleCount = 0;
//当点的个数少于5的时候循环
while (count < 5)
{
count = 0;
sum = 0;
//每次循环,寻找范围向下移动5个像素
//遍历,寻找线条上的点,并记录纵坐标
for (int j = leftBorder; j < rightBorder; j++)
{
for (int i = 0; i < rows; i++)
{
if (direction >= 0)
{
if (image.Get(i, j) > 0)
{
sum += i;
count++;
break;
}
}
else
{
if (image.Get(i, j) == 0)
{
sum += i;
count++;
break;
}
}
}
}
// 超过30次跳出
if(circleCount <= 30)
{
circleCount++;
}
else
{
break;
}
}
averageCoordinateNew = sum / count;
}
///
/// 提取非第一条横线纵坐标
///
/// 输入二值化图像
/// 输出纵坐标
/// 左边界
/// 右边界
/// 上一条线的坐标
/// 大于等于0时,记录大于0的点,小于0时记录等于零的点
public void ExtractLines(Mat image, out double averageCoordinateNew, int leftBorder, int rightBorder, double averageCoordinate, int direction)
{
//ImageShow(image*255);
//数组长宽
int rows = image.Rows;
int cols = image.Cols;
int count = 0;
int sum = 0;
int upperBound = (int)averageCoordinate + 15;
int lowerBound = (int)averageCoordinate + 45;
//当点的个数少于5的时候循环
while (count < 5)
{
count = 0;
sum = 0;
//每次循环,寻找范围向下移动5个像素
upperBound = upperBound + 5;
lowerBound = lowerBound + 5;
if (lowerBound > image.Rows)
break;
//遍历,寻找线条上的点,并记录纵坐标
int value = 0;
for (int j = leftBorder; j < rightBorder; j++)
{
for (int i = upperBound; i < lowerBound; i++)
{
if (direction >= 0)
{
value = image.Get(i, j);
if (value > 0)
{
sum += i;
count++;
break;
}
}
else
{
if (image.Get(i, j) == 0)
{
sum += i;
count++;
break;
}
}
}
}
}
averageCoordinateNew = count == 0 ? 0 : sum / count;
}
///
/// 从下向上提取第一条横线纵坐标
///
/// 輸入二值化圖像
/// 輸出坐標
/// 左邊界
/// 右边界
/// 大于等于0时,记录大于0的点,小于0记录等于零的点
public void ExtractLines2(Mat image, out double averageCoordinateNew, int leftBorder, int rightBorder, int direction)
{
//数组长宽
int rows = image.Rows;
int cols = image.Cols;
int count = 0;
int sum = 0;
int tag = 0;
//当点的个数少于5的时候循环
while (count < 5)
{
count = 0;
sum = 0;
//每次循环,寻找范围向下移动5个像素
//遍历,寻找线条上的点,并记录纵坐标
for (int j = leftBorder; j < rightBorder; j++)
{
for (int i = rows - 1; i > 0; i--)
{
if (i == 1)
tag += 1;
if (direction >= 0)
{
if (image.Get(i, j) > 0)
{
sum += i;
count++;
break;
}
}
else
{
if (image.Get(i, j) == 0)
{
sum += i;
count++;
break;
}
}
}
if (tag == 3)
break;
}
if (tag == 3)
break;
}
averageCoordinateNew = (count == 0) ? 0 : sum / count;
}
///
/// 从下向上提取横线纵坐标
///
/// 输入二值化图像
/// 输出纵坐标
/// 左边界
/// 右边界
/// 上一条线的坐标
/// 大于等于0时,记录大于0的点,小于0时记录等于零的点
public void ExtractLines2(Mat image, out double averageCoordinateNew, int leftBorder, int rightBorder, double averageCoordinate, int direction)
{
//数组长宽
int rows = image.Rows;
int cols = image.Cols;
int sum = 0, count = 0;
//遍历范围的上界和下界
int upperBound = (int)averageCoordinate - 45;
int lowerBound = (int)averageCoordinate - 10;
//当点的个数少于5的时候循环
while (count < 5)
{
count = 0;
sum = 0;
//每次循环,寻找范围向下移动5个像素
upperBound = upperBound - 5;
lowerBound = lowerBound - 5;
if (upperBound < 0)
break;
//遍历,寻找线条上的点,并记录纵坐标
for (int j = leftBorder; j < rightBorder; j++)
{
for (int i = lowerBound; i > upperBound; i--)
{
if (direction >= 0)
{
if (image.Get(i, j) > 0)
{
sum += i;
count++;
break;
}
}
else
{
if (image.Get(i, j) == 0)
{
sum += i;
count++;
break;
}
}
}
}
}
averageCoordinateNew = count==0 ? 0 : sum / count;
}
///
/// 提取第一条竖线的横坐标,从左往右
///
/// 输入二值图像
/// 输出坐标结果
/// 上边界
/// 下边界
public void ExtractVerticalLinesL2R(Mat image, out double result, int upperBound, int lowerBound, int showMat = 0)
{
int rows = image.Rows;
int cols = image.Cols;
List sum = new List();
int k = 0;
while (sum.Count == 0)
{
if (upperBound - 5 * k < 0 || lowerBound + 5 * k > image.Rows) break;
//解决两层板有些孔铜找不到的问题
for (int i = upperBound - 5 * k; i < lowerBound + 5 * k; i++)
{
for (int j = 0; j < cols; j++)
{
if (image.Get(i, j) > 0)
{
sum.Add(j);
break;
}
}
}
++k;
}
////int count = 0;
//for (int i = upperBound; i < lowerBound; i++)
//{
// for (int j = 0; j < cols; j++)
// {
// if (image.Get(i, j) > 0)
// {
// sum.Add(j);
// //sum += j;
// //count++;
// break;
// }
// }
//}
//if (sum.Count == 0)
// result = 1;// 0;
//else
result = sum.Average();// / count;
//if (showMat > 0)
//{
// Mat imageClone = image.Clone() * 127;
// Cv2.Line(imageClone, 0, upperBound, cols - 1, upperBound, new Scalar(255));
// Cv2.Line(imageClone, 0, lowerBound, cols - 1, lowerBound, new Scalar(255));
// Cv2.ImWrite(@"C:\Users\54434\Desktop\imageClone_" + showMat + ".png", imageClone);
//}
//////对自动结果不正确(这里使用距离过远来判定)的扩展运算
////double result1 = 0;
if (showMat > 0 && result > 20/*countV > (upperBound + lowerBound) / 2*/)
{
sum.Clear();
//sum = 0;
//count = 0;
////Mat imageClone = image.Clone() * 127;
////Cv2.Line(imageClone, 0, upperBound, cols - 1, upperBound, new Scalar(255));
////Cv2.Line(imageClone, 0, lowerBound, cols - 1, lowerBound, new Scalar(255));
////Cv2.ImWrite(@"C:\Users\54434\Desktop\imageClone_" + showMat + ".png", imageClone);
//////int sum = 0;
//////int count = 0;
bool sumAdd = false;
for (int i = upperBound - 5; i < lowerBound + 5; i++)
{
sumAdd = false;
for (int j = 0; j < 20; j++)
{
if (image.Get(i, j) > 0)
{
sumAdd = true;
sum.Add(j);
//sum += j;
//count++;
break;
}
}
if (!sumAdd && sum.Count > 0)
break;
}
if (sum.Count == 0)
{
for (int i = upperBound - 5; i < lowerBound + 5; i++)
{
sumAdd = false;
for (int j = 0; j < 26; j++)
{
if (image.Get(i, j) > 0)
{
sumAdd = true;
sum.Add(j);
//sum += j;
//count++;
break;
}
}
if (!sumAdd && sum.Count > 0)
break;
}
//for (int i = upperBound - 5; i < lowerBound + 5; i++)
//{
// sumAdd = false;
// for (int j = cols - 1; j > cols - 26; j--)
// {
// if (image.Get(i, j) > 0)
// {
// sumAdd = true;
// sum += j;
// count++;
// break;
// }
// }
// if (!sumAdd && sum > 0)
// break;
//}
}
// 输出平均横坐标
if (sum.Count > 0)
result = sum.Average();// / count;
}
else if (showMat > 0)
{//对自动结果不正确(这里使用垂直方向不整齐来判定)的扩展运算
sum.Sort();
for (int i = 0; i < sum.Count - 1; i++)
{
if (sum[i + 1] - sum[i] > 10)
{
for (int j = sum.Count - 1; j > i; j--)
sum.RemoveAt(j);
break;
}
}
// 输出平均横坐标
if (sum.Count > 0)
result = sum.Average();// / count;
//Mat imageClone = image.Clone() * 127;
//Cv2.Line(imageClone, 0, upperBound, cols - 1, upperBound, new Scalar(255));
//Cv2.Line(imageClone, 0, lowerBound, cols - 1, lowerBound, new Scalar(255));
//Cv2.ImWrite(@"C:\Users\54434\Desktop\imageClone_" + showMat + ".png", imageClone);
}
////对自动结果不正确(这里使用距离过远来判定)的扩展运算
//double result1 = 0;
//// 输出平均横坐标
//result = sum / count;
}
///
/// 提取第二条竖线的横坐标,从左往右
///
/// 输入二值图像
/// 输出坐标结果
/// 上边界
/// 下边界
/// 第一条线的横坐标
public int[] ExtractVerticalLinesL2R(Mat image, out double result, int upperBound, int lowerBound, double basic, bool cal_Jiaoneisuo = true)
{
int rows = image.Rows;
int cols = image.Cols;
int sum = 0;
int count = 0;
// 寻找的左右范围
int leftBound = (int)basic + 15;
int rightBound = (int)basic + 45;
int countUp = 5;
if (!cal_Jiaoneisuo) countUp = 1;
//当点的个数少于5的时候循环
while (count < countUp)
{
count = 0;
sum = 0;
//每次循环,寻找范围向左移动5个像素
leftBound = leftBound + 5;
rightBound = rightBound + 5;
if (rightBound > image.Cols)
break;
//遍历,寻找线条上的点,并记录横坐标
for (int i = upperBound; i < lowerBound; i++)
{//待自测scc-1
//bool isWhiteArea = false;//避免弧度大,导致找的位置与角落的弧度相交
for (int j = leftBound; j < rightBound; j++)
{
//if (!isWhiteArea)
//{
// if (image.Get(i, j) > 0)
// isWhiteArea = true;
//}else
if (image.Get(i, j) == 0)
{
sum += j;
count++;
break;
}
}
}
}
leftBound = (int)basic + 15;
rightBound = (int)basic + 145;
if (rightBound >= cols) rightBound = cols - 1;
double y1 = upperBound;
double x1 = leftBound;
for (int i = upperBound + 20; i < lowerBound - 20; i++)
{
for (int j = leftBound; j < rightBound; j++)
{
if (image.Get(i, j) == 0)
{
if (x1 < j)
{
x1 = j;
y1 = i;
}
break;
}
}
}
result = sum / count;
return new int[] { (int)x1, (int)y1 };
}
///
/// 从右往左提取第一条竖线横坐标
///
/// 输入二值图像
/// 输出坐标结果
/// 上边界
/// 下边界
public void ExtractVerticalLinesR2L(Mat image, out double result, int upperBound, int lowerBound, int showMat = 0)
{
int rows = image.Rows;
int cols = image.Cols;
int sum = 0;
int count = 0;
int countV = 0;
for (int i = upperBound; i < lowerBound; i++)
{
for (int j = cols - 1; j > 0; j--)
{
if (image.Get(i, j) > 0)
{
sum += j;
count++;
break;
}
}
if (sum == 0) countV = i;
}
result = sum / count;
////对自动结果不正确(这里使用距离过远来判定)的扩展运算
//double result1 = 0;
if (showMat > 0 && cols - result > 20/*countV > (upperBound + lowerBound) / 2*/)
{
sum = 0;
count = 0;
//Mat imageClone = image.Clone() * 127;
//Cv2.Line(imageClone, 0, upperBound, cols - 1, upperBound, new Scalar(255));
//Cv2.Line(imageClone, 0, lowerBound, cols - 1, lowerBound, new Scalar(255));
//Cv2.ImWrite(@"C:\Users\54434\Desktop\imageClone_" + showMat + ".png", imageClone);
////int sum = 0;
////int count = 0;
bool sumAdd = false;
for (int i = upperBound - 5; i < lowerBound + 5; i++)
{
sumAdd = false;
for (int j = cols - 1; j > cols - 20; j--)
{
if (image.Get(i, j) > 0)
{
sumAdd = true;
sum += j;
count++;
break;
}
}
if (!sumAdd && sum > 0)
break;
}
if (sum == 0)
{
for (int i = upperBound - 5; i < lowerBound + 5; i++)
{
sumAdd = false;
for (int j = cols - 1; j > cols - 26; j--)
{
if (image.Get(i, j) > 0)
{
sumAdd = true;
sum += j;
count++;
break;
}
}
if (!sumAdd && sum > 0)
break;
}
}
// 输出平均横坐标
if (sum > 0)
result = sum / count;
}
//// 输出平均横坐标
//if (true)
//{
//}
//result = sum / count;
}
///
/// 提取第二条竖线的横坐标,从右往左
///
/// 输入二值图像
/// 输出坐标结果
/// 上边界
/// 下边界
/// 第一条线的横坐标
public int[] ExtractVerticalLinesR2L(Mat image, out double result, int upperBound, int lowerBound, double basic, int showMat = 0)
{
int rows = image.Rows;
int cols = image.Cols;
int sum = 0;
int count = 0;
// 寻找的左右范围
int leftBound = (int)basic - 45;
int rightBound = (int)basic - 15;
//if (showMat > 0)
//{
// Mat imageClone = image.Clone() * 127;
// Cv2.Line(imageClone, leftBound, upperBound, rightBound - 1, upperBound, new Scalar(255));
// Cv2.Line(imageClone, leftBound, lowerBound, rightBound - 1, lowerBound, new Scalar(255));
// Cv2.ImWrite(@"C:\Users\54434\Desktop\imageClone_" + showMat + ".png", imageClone);
//}
//当点的个数少于5的时候循环
while (count < 5)
{
count = 0;
sum = 0;
//每次循环,寻找范围向左移动5个像素
leftBound = leftBound - 5;
rightBound = rightBound - 5;
//遍历,寻找线条上的点,并记录横坐标
for (int i = upperBound; i < lowerBound; i++)
{//待自测scc-1
//bool isWhiteArea = false;//避免弧度大,导致找的位置与角落的弧度相交
////(showMat > 0)
for (int j = rightBound - 1; j > leftBound; j--)
{
//if ((showMat > 0) && !isWhiteArea)
//{
// if (image.Get(i, j) > 0)
// isWhiteArea = true;
//}
//else
if (image.Get(i, j) == 0)
{
sum += j;
count++;
break;
}
}
}
}
//if (count == 0)
//{
//}
leftBound = (int)basic - 145;
if (leftBound < 0) leftBound = 0;
rightBound = (int)basic - 15;
double y1 = upperBound;
double x1 = rightBound;
//遍历,寻找线条上的点,并记录横坐标
for (int i = upperBound + 20; i < lowerBound - 20; i++)
{
for (int j = rightBound - 1; j > leftBound; j--)
{
if (image.Get(i, j) == 0)
{
if (x1 > j)
{
x1 = j;
y1 = i;
}
break;
}
}
}
result = sum / count;
return new int[] { (int)x1, (int)y1 };
}
///
/// 提取三层板的粗糙度以及粗糙度的坐标
///
/// 二值图像
/// 红色通道图片
/// 第三条横线
/// 第四条横线
/// 第五条横线
/// 第六条横线
/// 第二条竖线
/// 第四条竖线
/// 数据提取区域
/// 槽孔所在左右方向,left、right
/// 输出粗糙度
/// 输出粗糙度坐标
public void GetSancengRoughness(Mat imageContour, Mat imageRed, int ordinateL3, int ordinateL4, int ordinateL5, int ordinateL6, int ordinateV2, int ordinateV4, int[] dataArea, string direction, out int roughness, out int[] roughnessOrdinate)
{
int leftBorder1 = 0, rightBorder1 = 0, leftBorder2 = 0, rightBorder2 = 0;
int range = 70;
switch (direction)
{
case "right":
leftBorder1 = ordinateV2;
rightBorder1 = ordinateV2 + range;
leftBorder2 = ordinateV4;
rightBorder2 = ordinateV4 + range;
break;
case "left":
leftBorder1 = ordinateV2 - range;
rightBorder1 = ordinateV2;
leftBorder2 = ordinateV4 - range;
rightBorder2 = ordinateV4;
break;
}
int sum = 0, count = 0;
double averSaturation1 = 0, averSaturation2 = 0;
roughness = 0;
roughnessOrdinate = new int[4] { 0, 0, 0, 0 };
Mat sobel = new Mat();
Sobel(imageContour, out sobel);
//计算粗糙度
int max = 0;
//先上下遍历一遍寻找最大值,避免找不到胶体
for (int i = (int)ordinateL3 + 20; i < (int)ordinateL4 - 15; i++)
{
for (int j = leftBorder1; j < rightBorder1; j++)
{
if (sobel.Get(i, j) > 0)
{
if (Math.Abs(j - (int)(ordinateV2)) > max)
{
max = Math.Abs(j - (int)(ordinateV2));
roughnessOrdinate[0] = (int)ordinateV2;
roughnessOrdinate[1] = i;
roughnessOrdinate[2] = j;
roughnessOrdinate[3] = i;
}
}
}
}
for (int i = (int)ordinateL5 + 15; i < (int)ordinateL6 - 10; i++)
{
for (int j = leftBorder2; j < rightBorder2; j++)
{
if (sobel.Get(i, j) > 0)
{
if (Math.Abs(j - (ordinateV4)) > max)
{
max = Math.Abs(j - (ordinateV4));
roughnessOrdinate[0] = (int)ordinateV4;
roughnessOrdinate[1] = i;
roughnessOrdinate[2] = j;
roughnessOrdinate[3] = i;
}
}
}
}
roughness = max;
if (roughness < 10)
{
//判断胶体方向
Cv2.EqualizeHist(imageRed, imageRed);
Mat upperCrop = imageRed[(int)ordinateL3 + 10, (int)ordinateL4 - 10, dataArea[0], dataArea[1]];
Mat lowerCrop = imageRed[(int)ordinateL5 + 10, (int)ordinateL6 - 10, dataArea[0], dataArea[1]];
//Mat duibi = new Mat(upperCrop.Size().Height + lowerCrop.Size().Height, upperCrop.Size().Width, upperCrop.Type());
//upperCrop.CopyTo(duibi[0, upperCrop.Size().Height - 1, 0, upperCrop.Size().Width - 1]);
//lowerCrop.CopyTo(duibi[upperCrop.Size().Height, duibi.Size().Height - 1, 0, upperCrop.Size().Width - 1]);
//new Window("upperCrop", WindowMode.Normal, upperCrop);
//new Window("lowerCrop", WindowMode.Normal, lowerCrop);
//new Window("imageRed", WindowMode.Normal, imageRed);
//Cv2.WaitKey();
//Cv2.EqualizeHist(duibi, duibi);
//Scalar s1 = duibi[0, upperCrop.Size().Height - 1, 0, upperCrop.Size().Width - 1].Sum();
//Scalar s2 = duibi[upperCrop.Size().Height, duibi.Size().Height - 1, 0, upperCrop.Size().Width - 1].Sum();
Scalar s1 = upperCrop.Sum();
Scalar s2 = lowerCrop.Sum();
averSaturation1 = (double)s1 / (upperCrop.Cols * upperCrop.Rows);
averSaturation2 = (double)s2 / (lowerCrop.Cols * lowerCrop.Rows);
for (int i = 0; i < upperCrop.Rows; i++)
{
for (int j = 0; j < upperCrop.Cols; j++)
{
sum += Math.Abs(upperCrop.Get(i, j) - (int)averSaturation1);
}
}
double biaozhuncha1 = sum / (upperCrop.Cols * upperCrop.Rows);
sum = 0;
for (int i = 0; i < lowerCrop.Rows; i++)
{
for (int j = 0; j < lowerCrop.Cols; j++)
{
sum += Math.Abs(lowerCrop.Get(i, j) - (int)averSaturation2);
}
}
double biaozhuncha2 = sum / (lowerCrop.Cols * lowerCrop.Rows);
int direction2 = 0;
if (biaozhuncha1 > biaozhuncha2)
direction2 = 0;//等于0时说明胶体在上面,否则是下面
else
direction2 = 1;
switch (direction2)
{
case 0:
for (int i = (int)ordinateL3 + 10; i < (int)ordinateL4 - 15; i++)
{
for (int j = leftBorder1; j < rightBorder1; j++)
{
if (sobel.Get(i, j) > 0)
{
if (Math.Abs(j - (int)(ordinateV2)) > max)
{
max = Math.Abs(j - (int)(ordinateV2));
roughnessOrdinate[0] = (int)ordinateV2;
roughnessOrdinate[1] = i;
roughnessOrdinate[2] = j;
roughnessOrdinate[3] = i;
}
}
}
}
roughness = max;
break;
case 1:
for (int i = (int)ordinateL5 + 15; i < (int)ordinateL6 - 10; i++)
{
for (int j = leftBorder2; j < rightBorder2; j++)
{
if (sobel.Get(i, j) > 0)
{
if (Math.Abs(j - (int)(ordinateV4)) > max)
{
max = Math.Abs(j - (int)(ordinateV4));
roughnessOrdinate[0] = (int)ordinateV4;
roughnessOrdinate[1] = i;
roughnessOrdinate[2] = j;
roughnessOrdinate[3] = i;
}
}
}
}
roughness = max;
break;
}
}
}
///
/// 提取四层板的粗糙度
///
/// 二值图像
/// 上界
/// 下界
/// 边缘线
/// 槽孔所在左右方向,left、right
/// 输出粗糙度
/// 输出粗糙度坐标
public void GetSicengRoughness(Mat imageContour, int upperBorder, int lowerBorder, int basic, string direction, out int roughness, out int[] roughnessOrdinate)
{
int leftBorder = 0, rightBorder = 0;
int range = 70;
switch (direction)
{
case "right":
leftBorder = basic;
rightBorder = basic + range;
break;
case "left":
leftBorder = basic - range;
rightBorder = basic;
break;
}
int max = 0;
roughness = 0;
roughnessOrdinate = new int[4];
Mat sobel = new Mat();
Sobel(imageContour, out sobel);
for (int i = upperBorder; i < lowerBorder; i++)
{
for (int j = leftBorder; j < rightBorder; j++)
{
if (sobel.Get(i, j) > 0)
{
if (Math.Abs(j - basic) > max)
{
max = Math.Abs(j - basic);
roughnessOrdinate[0] = basic;
roughnessOrdinate[1] = i;
roughnessOrdinate[2] = j;
roughnessOrdinate[3] = i;
}
}
}
}
roughness = max;
}
public void GetNewKongtong(Mat imageRed, Mat imageContour, int[] leftAperture, int[] rightAperture, double leftOrdinateMiantong, int leftMiddleMianJicaitong, double leftOrdinate3, double rightOrdinateMiantong, int rightMiddleMianJicaitong, double rightOrdinate3, out double[] kongtong, out int[] leftKongtong, out int[] rightKongtong, out int[] leftPoint2, out int[] rightPoint2)
{
kongtong = new double[2];
leftKongtong = new int[2];
rightKongtong = new int[2];
leftPoint2 = new int[2];
rightPoint2 = new int[2];
#region//左侧
Mat leftCrop = imageRed[(int)leftOrdinateMiantong + 40, (int)leftOrdinate3 - 10, leftMiddleMianJicaitong, leftAperture[1]].Clone();
Mat leftContour = new Mat();
double t = Cv2.Threshold(leftCrop, leftContour, 0, 1, ThresholdTypes.Otsu);
Mat leftFanse = 1 - leftContour;
InputArray leftKernel = InputArray.Create(new int[17, 17] {
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
});
InputArray leftKernel2 = InputArray.Create(new int[17, 17] {
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 },
});
InputArray leftKernel3 = InputArray.Create(new int[17, 17] {
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1 },
});
Mat leftFilter = new Mat();
//Cv2.Filter2D(leftFanse, leftFilter, -1, leftKernel, new Point(-1, -1), 0);
//Cv2.Filter2D(leftFanse, leftFilter, -1, leftKernel2, new Point(-1, -1), 0);
Cv2.Filter2D(leftFanse, leftFilter, -1, leftKernel3, new Point(-1, -1), 0);
Mat leftThresh = leftFilter.Threshold(14, 1, ThresholdTypes.Binary);
for (int j = leftThresh.Cols - 1; j > 0; j--)//从右上角,以135°方向遍历
{
for (int k = j; k < leftThresh.Cols && (k - j < leftThresh.Rows); k++)
{
if (leftThresh.Get(k - j, k) > 0)
{
leftKongtong[0] = k - j + (int)leftOrdinateMiantong + 40;//纵
leftKongtong[1] = k + leftMiddleMianJicaitong;//横
//Cv2.Circle(imageRed, k + leftMiddleMianJicaitong + border, k - j + (int)leftOrdinateMiantong + upper - 10, 1, 1, 1);
//new Window("imageRed_Line", WindowMode.Normal, imageRed);
break;
}
}
if (leftKongtong[0] != 0)
break;
}
#endregion
#region//右侧
Mat rightCrop = imageRed[(int)rightOrdinateMiantong + 40, (int)rightOrdinate3 - 10, rightAperture[1], rightMiddleMianJicaitong].Clone();
Mat rightContour = new Mat();
double t1 = Cv2.Threshold(rightCrop, rightContour, 0, 1, ThresholdTypes.Otsu);
Mat rightFanse = 1 - rightContour;
InputArray rightKernel = InputArray.Create(new int[17, 17] {
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
});
InputArray rightKernel2 = InputArray.Create(new int[17, 17] {
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1 },
{ 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
});
InputArray rightKernel3 = InputArray.Create(new int[17, 17] {
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1 },
{ 0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
});
Mat rightFilter = new Mat();
//Cv2.Filter2D(rightFanse, rightFilter, -1, rightKernel, new Point(-1, -1), 0);
//Cv2.Filter2D(rightFanse, rightFilter, -1, rightKernel2, new Point(-1, -1), 0);
Cv2.Filter2D(rightFanse, rightFilter, -1, rightKernel3, new Point(-1, -1), 0);
Mat rightThresh = rightFilter.Threshold(14, 1, ThresholdTypes.Binary);
for (int j = 0; j < rightThresh.Cols; j++)//从左上角,45°方向遍历
{
for (int k = j; k >= 0 && j - k < rightThresh.Rows; k--)
{
if (rightThresh.Get(j - k, k) > 0)
{
rightKongtong[0] = j - k + (int)rightOrdinateMiantong + 40;
rightKongtong[1] = k + rightAperture[1];
//Cv2.Circle(imageRed, k + rightAperture[1], k - j + (int)rightOrdinateMiantong + upper - 10, 1, 1, 1);
//new Window("imageRed_Line", WindowMode.Normal, imageRed);
break;
}
}
if (rightKongtong[0] != 0)
break;
}
#endregion
//ImageShow(leftCrop, leftContour * 255, /*rightContour * 255, */leftThresh * 255/*, rightThresh * 255*/);
//Cv2.Circle(imageRed, new Point(leftKongtong[1], leftKongtong[0]), 10, new Scalar(0), 2);
//Cv2.Circle(imageRed, new Point(rightKongtong[1], rightKongtong[0]), 10, new Scalar(0), 2);
////ImageShow(imageRed);
GetKongtong(imageContour, leftKongtong, rightKongtong, out kongtong, out leftPoint2, out rightPoint2);
//LineShow(imageRed, leftKongtong[1], leftKongtong[0], leftPoint2[1], leftPoint2[0]);
//LineShow(imageRed, rightKongtong[1], rightKongtong[0], rightPoint2[1], rightPoint2[0]);
//ImageShow(imageRed);
//leftKongtong[0] -= upper;
//rightKongtong[0] -= upper;
//leftPoint2[0] -= upper;
//rightPoint2[0] -= upper;
if(rightFilter != null)
{
rightFilter.Dispose();
}
}
///
/// 计算孔铜
///
/// 二值图
/// 左孔径坐标
/// 右孔径坐标
/// 输出左右孔铜的距离
/// 左孔铜对应边缘线的坐标
/// 右孔铜对应边缘线的坐标
public void GetKongtong(Mat imageContour, int[] apertureBegin, int[] apertureEnd, out double[] kongtong, out int[] pointLeft, out int[] pointRight)
{
//曲面上点的坐标
int count = apertureEnd[1] - apertureBegin[1];
int[,] coordinate = new int[Math.Abs(apertureEnd[1] - apertureBegin[1]), 2];//先纵坐标后横坐标
for (int j = apertureBegin[1]; j < apertureEnd[1]; j++)
{
for (int i = 0; i < imageContour.Rows; i++)
{
if (imageContour.Get(i, j) > 0)
{
coordinate[j - apertureBegin[1], 0] = i;
coordinate[j - apertureBegin[1], 1] = j;
break;
}
}
}
//计算距离,最小的距离分别为左孔铜和右孔铜
double leftKongtong = 1000;
double rightKongtong = 1000;
double distance1 = 0;
double distance2 = 0;
//当距离最短是曲线上点的坐标,第一列是纵坐标(行数),第二列是横坐标(列数)
pointLeft = new int[2];
pointRight = new int[2];
for (int i = 0; i < count; i++)
{
//计算曲面点到左起始点的距离
if (i < count / 2)
{
distance1 = Math.Sqrt(Math.Pow((coordinate[i, 0] - apertureBegin[0]), 2) + Math.Pow((coordinate[i, 1] - apertureBegin[1]), 2));
//计算曲面点到右截止点的距离
if (leftKongtong > distance1)
{
leftKongtong = distance1;
pointLeft[0] = coordinate[i, 0];
pointLeft[1] = coordinate[i, 1];
}
}
else
{
distance2 = Math.Sqrt(Math.Pow((coordinate[i, 0] - apertureEnd[0]), 2) + Math.Pow((coordinate[i, 1] - apertureEnd[1]), 2));
//得到左右孔铜以及对应的曲面坐标
if (rightKongtong > distance2)
{
rightKongtong = distance2;
pointRight[0] = coordinate[i, 0];
pointRight[1] = coordinate[i, 1];
}
}
}
kongtong = new double[2] { leftKongtong, rightKongtong };
}
public void ShenmangkongNewKongtong(Mat image, Mat imageContour, int leftL2, int rightL2, int[] leftAperture, int[] rightAperture, out double[] kongtong, out int[] leftKongtong, out int[] rightKongtong, out int[] leftPoint2, out int[] rightPoint2)
{
kongtong = new double[2];
leftKongtong = new int[2];
rightKongtong = new int[2];
leftPoint2 = new int[2];
rightPoint2 = new int[2];
#region//左
Mat leftCrop = image[leftL2 - 10, leftL2 + 20, leftAperture[1] - 30, leftAperture[1] + 5].Clone();
Mat leftThresh = leftCrop.Threshold(0, 1, ThresholdTypes.Otsu);
Mat leftFanse = 1 - leftThresh;
InputArray leftKernel = InputArray.Create(new int[17, 17] {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
});
InputArray leftKernel2 = InputArray.Create(new int[17, 17] {
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0 },
{ 0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1 },
});
Mat leftFilter1 = new Mat();
Cv2.Filter2D(leftFanse, leftFilter1, -1, leftKernel, new Point(-1, -1), 0);
Mat leftFilter2 = new Mat();
Cv2.Filter2D(leftFanse, leftFilter2, -1, leftKernel2, new Point(-1, -1), 0);
Mat leftFilter = new Mat();
Cv2.AddWeighted(leftFilter1, 0, leftFilter2, 1, 0, leftFilter);
Cv2.Rectangle(leftFilter, new Rect(0, 0, leftFilter.Cols, 5), new Scalar(0), -1);
Cv2.Rectangle(leftFilter, new Rect(0, 15, leftFilter.Cols, leftFilter.Rows - 15), new Scalar(0), -1);
double min, max;
Cv2.MinMaxIdx(leftFilter, out min, out max);
Mat leftFilterThresh = leftFilter.Threshold(max - 2, 1, ThresholdTypes.Binary);
Cv2.Flip(leftFilterThresh, leftFilterThresh, FlipMode.Y);
Point left;
FindLeftTop(leftFilterThresh, out left);
leftKongtong[0] = left.Y + leftL2 - 10;
leftKongtong[1] = leftCrop.Cols - left.X + leftAperture[1] - 30;
Mat newLeft = leftFilterThresh.Clone();
newLeft.Set(left.Y, left.X, 255);
//ImageShow(leftCrop, leftFilter * 50, leftFilterThresh * 255, newLeft);
#endregion
#region//右
Mat rightCrop = image[rightL2 - 10, rightL2 + 20, rightAperture[1] - 5, rightAperture[1] + 30].Clone();
Mat rightThresh = rightCrop.Threshold(0, 1, ThresholdTypes.Otsu);
Mat rightFanse = 1 - rightThresh;
InputArray rightKernel = InputArray.Create(new int[17, 17] {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1 },
{ 0, 0, 0, 0, 0, 0, 0,-1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0,-1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 0, 0, 0, 0,-1, 0,-1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 0, 0, 0,-1, 0, 1,-1, 0, 1, 1,-1,-1,-1,-1,-1,-1 },
{ 0, 0, 0,-1, 0, 1, 0,-1, 0, 1, 1,-1,-1,-1,-1,-1,-1 },
{ 0, 0,-1, 0, 1, 0, 0,-1, 0, 1, 1,-1,-1,-1,-1,-1,-1 },
{ 0,-1, 0, 1, 0, 0, 0,-1, 0, 1, 1,-1,-1,-1,-1,-1,-1 },
{ -1, 0, 1, 0, 0, 0, 0,-1, 0, 1, 1,-1,-1,-1,-1,-1,-1 },
{ 0, 1, 0, 0, 0, 0, 0,-1, 0, 1, 1,-1,-1,-1,-1,-1,-1 },
});
InputArray rightKernel2 = InputArray.Create(new int[17, 17] {
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1 },
{ 0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
{ 1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0 },
});
Mat rightFilter1 = new Mat();
Cv2.Filter2D(rightFanse, rightFilter1, -1, rightKernel, new Point(-1, -1), 0);
Mat rightFilter2 = new Mat();
Cv2.Filter2D(rightFanse, rightFilter2, -1, rightKernel2, new Point(-1, -1), 0);
Mat rightFilter = new Mat();
Cv2.AddWeighted(rightFilter1, 0, rightFilter2, 1, 0, rightFilter);
Cv2.Rectangle(rightFilter, new Rect(0, 0, rightFilter.Cols, 5), new Scalar(0), -1);
Cv2.Rectangle(rightFilter, new Rect(0, 15, rightFilter.Cols, rightFilter.Rows - 15), new Scalar(0), -1);
Cv2.MinMaxIdx(rightFilter, out min, out max);
Mat rightFilterThresh = rightFilter.Threshold(max - 2, 1, ThresholdTypes.Binary);
Point right;
FindLeftTop(rightFilterThresh, out right);
rightKongtong[0] = right.Y + rightL2 - 10;
rightKongtong[1] = right.X + rightAperture[1] - 5;
Mat newRight = rightFilterThresh.Clone();
newRight.Set(right.Y, right.X, 255);
//ImageShow(rightCrop, rightThresh * 255, rightFilter2 * 50, rightFilterThresh * 255, newRight);
#endregion
#region//边缘线
GetKongtong(imageContour, leftKongtong, rightKongtong, out kongtong, out leftPoint2, out rightPoint2);
#endregion
}
///
/// 计算最小孔环,从外侧交点到上孔径
///
///
///
///
///
///
///
///
public void GetMinmumRing(Mat imageContour, int upper, int lower, int leftBorder, int rightBorder, out int[] pointRing, string direction)
{
pointRing = new int[2];
Mat crop2 = imageContour[upper, lower, leftBorder, rightBorder].Clone();
Scalar sum = new Scalar(0);
Scalar lastSum = new Scalar(0);
switch (direction)
{
case "left":
//for (int j = 0; j < crop2.Cols - 1; j += 5)
//{
// sum = crop2[0, crop2.Rows, j, j + 1].Sum();
// if ((int)lastSum != 0 && (int)sum-(int)lastSum>10)
// {
// pointRing[1] = j+leftBorder-2;
// break;
// }
// lastSum = sum;
//}
for (int j = crop2.Cols - 1; j > 1; j -= 10)
{
sum = crop2[0, crop2.Rows, j - 1, j].Sum();
if ((int)lastSum != 0 && (int)lastSum - (int)sum > 10)
{
pointRing[1] = j + leftBorder - 5;
break;
}
lastSum = sum;
}
break;
case "right":
//for (int j = crop2.Cols - 1; j > 2; j -= 5)
//{
// sum = crop2[0, crop2.Rows, j - 1, j].Sum();
// if ((int)lastSum != 0 && (int)sum - (int)lastSum > 10)
// {
// pointRing[1] = j + leftBorder+2;
// break;
// }
// lastSum = sum;
//}
for (int j = 1; j < crop2.Cols - 1; j += 10)
{
sum = crop2[0, crop2.Rows, j, j + 1].Sum();
if ((int)lastSum != 0 && (int)lastSum - (int)sum > 10)
{
pointRing[1] = j + leftBorder + 5;
break;
}
lastSum = sum;
}
break;
}
//ImageShow(crop2 * 255);
//int j = 0;
//for (int i = crop2.Rows-1;i>0;i--)
//{
// for (int k = i; k < crop2.Rows&&(crop2.Cols-1-(k-i))>0; k++)
// {
// j = crop2.Cols - 1 - (k - i);
// if (crop2.Get(k, j) > 0)
// {
// pointLeftRing[0] = k + upper;
// pointLeftRing[1] = j ;
// break;
// }
// }
//}
//ImageShow(filter * 30, thresh * 255,crop*255,crop2*255);
}
///
/// 得到边缘线上拐点的坐标
///
/// 二值图
/// 左孔径坐标
/// 右孔径坐标
/// 输出拐点坐标,0:縱坐標;1:橫坐標
/// 孔径对应边缘线上点的平均纵坐标
public void CurveVertex(Mat imageContour, int[] apertureBegin, int[] apertureEnd, out int[] curveVertex, out double middleApertureY)
{
//曲面顶点的坐标
curveVertex = new int[2];
//孔径平均横坐标
double middleAperture = (apertureBegin[1] + apertureEnd[1]) / 2;
//孔径平均高度
int[] apertureY = new int[2];
for (int i = 0; i < imageContour.Rows; i++)
{
if (imageContour.Get(i, apertureBegin[1]) > 0)
{
apertureY[0] = i;
break;
}
}
for (int i = 0; i < imageContour.Rows; i++)
{
if (imageContour.Get(i, apertureEnd[1]) > 0)
{
apertureY[1] = i;
break;
}
}
middleApertureY = (apertureY[0] + apertureY[1]) / 2;
//边缘线坐标
int count = Math.Abs((apertureEnd[1] - apertureBegin[1]) / 2);
int[,] ordinate = new int[count, 2];
int range = apertureEnd[1] - apertureBegin[1];
for (int j = range / 4 + apertureBegin[1]; j < range / 4 + apertureBegin[1] + count; j++)
{
for (int i = 0; i < imageContour.Rows; i++)
{
if (imageContour.Get(i, j) > 0)
{
ordinate[j - apertureBegin[1] - range / 4, 0] = i;
ordinate[j - apertureBegin[1] - range / 4, 1] = j;
break;
}
}
}
//孔深,取曲面上的点到孔径平均高度只差的最大值
double kongshenAomian = 0;//当边缘线内凹或外凸,孔深最大值
//double kongshenTumian = 1000;//当边缘线内凸,孔深最小值
int[] coordinateAomian = new int[2];
//int[] coordinateTumian = new int[2];
double t = 0;
for (int i = 0; i < count; i++)
{
t = Math.Abs(middleApertureY - ordinate[i, 0]);
if (kongshenAomian < t)
{
kongshenAomian = t;
coordinateAomian[0] = ordinate[i, 0];
coordinateAomian[1] = ordinate[i, 1];
}
//if (kongshenTumian > t)
//{
// kongshenTumian = t;
// coordinateTumian[0] = ordinate[i, 0];
// coordinateTumian[1] = ordinate[i, 1];
//}
}
curveVertex = coordinateAomian;
//判断哪个点离孔径中心更近,更近的为曲面坐标
//double absAomian = Math.Abs(coordinateAomian[1] - middleAperture);
//double absTumian = Math.Abs(coordinateTumian[1] - middleAperture);
//if (absAomian < absTumian)
//{
// curveVertex = coordinateAomian;
//}
//else
//{
// curveVertex = coordinateTumian;
//}
}
public void ShenmangkongShangkongjing(Mat contour, int leftL3, int rightL3, int[] lowerAperture, out int[] leftAperture, out int[] rightAperture)
{
#region//左
Mat cropLeft = contour[leftL3 - 20, leftL3 + 20, (lowerAperture[0] - 200)<0?0:(lowerAperture[0] - 200), lowerAperture[0] + 200].Clone();
InputArray leftKernel = InputArray.Create(new int[17, 17] {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ -1,-1,-1,-1,-1,-1,-1,-1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0,-1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0,-1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0,-1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0,-1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0,-1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0,-1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0,-1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
});
Mat leftFilter = new Mat();
Cv2.Filter2D(cropLeft, leftFilter, -1, leftKernel, new Point(-1, -1), 0);
double min2, max;
Cv2.MinMaxIdx(leftFilter, out min2, out max);
Mat leftThresh = leftFilter.Threshold(max - 2, 1, ThresholdTypes.Binary);
Cv2.Flip(leftThresh, leftThresh, FlipMode.Y);
leftAperture = new int[2];
int min = 100000;
Point[] leftIdx;
FindNonZeros(leftThresh, out leftIdx);
for (int i = 0; i < leftIdx.Length; i++)
{
if (min > (leftIdx[i].X + leftIdx[i].Y))
{
min = leftIdx[i].X + leftIdx[i].Y;
leftAperture[1] = leftThresh.Cols - leftIdx[i].X;
leftAperture[0] = leftIdx[i].Y;
}
}
leftAperture[1] += lowerAperture[0] - 200;
leftAperture[0] += leftL3 - 20;
#endregion
#region//右
Mat cropRight = contour[rightL3 - 20, rightL3 + 20, lowerAperture[1] - 200, lowerAperture[1] + 200].Clone();
InputArray rightKernel = InputArray.Create(new int[17, 17] {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0,-1,-1,-1,-1,-1,-1,-1,-1 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 1, 0,-1, 0, 0, 0, 0, 0, 0, 0 },
});
Mat rightFilter = new Mat();
Cv2.Filter2D(cropRight, rightFilter, -1, rightKernel, new Point(-1, -1), 0);
Cv2.MinMaxIdx(rightFilter, out min2, out max);
Mat rightThresh = rightFilter.Threshold(max - 2, 1, ThresholdTypes.Binary);
rightAperture = new int[2];
Point[] rightIdx;
FindNonZeros(rightThresh, out rightIdx);
min = 1000000;
for (int i = 0; i < rightIdx.Length; i++)
{
if (min > (rightIdx[i].X + rightIdx[i].Y))
{
min = rightIdx[i].X + rightIdx[i].Y;
rightAperture[1] = rightIdx[i].X;
rightAperture[0] = rightIdx[i].Y;
}
}
rightAperture[1] += lowerAperture[1] - 200;
rightAperture[0] += rightL3 - 20;
#endregion
//ImageShow( cropRight * 255, rightThresh * 255);
}
///
/// 得到深盲孔的下孔径
///
/// 二值图像
/// 输出下孔径
/// 左边计算区域的上边界
/// 右边计算区域的上边界
/// 左边计算区域的下边界
/// 右边计算区域的下边界
/// 数据提取区域
public void GetShenmangLowerAperture(Mat imageContour, out int[] aperture, int leftUpper, int rightUpper, int leftLower, int rightLower, int[] dataArea)
{
//孔径起始点
aperture = new int[2];
aperture[0] = 0;
aperture[1] = 0;
int middle = (dataArea[1] + dataArea[2]) / 2;
Mat fanse = 1 - imageContour;
//Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));
//Mat open = new Mat();
//Cv2.MorphologyEx(fanse, open,MorphTypes.Open, se);
//fanse = open;
for (int j = middle; j > dataArea[0]; j--)
{
for (int i = leftUpper - 20 < 0 ? 0 : leftUpper - 20; i < leftLower - 20; i++)
{
if (fanse.Get(i, j) > 0)
{
aperture[0] = j;
break;
}
}
if (aperture[0] != 0)
break;
}
for (int j = middle; j < dataArea[3]; j++)
{
for (int i = rightUpper - 20 < 0 ? 0 : rightUpper - 20; i < rightLower - 20; i++)
{
if (fanse.Get(i, j) > 0)
{
aperture[1] = j;
break;
}
}
if (aperture[1] != 0)
break;
}
}
///
/// 下孔径新方法,用胶体部分置1,向中间遍历,为0时下孔径
///
///
///
///
///
///
///
///
public void GetLowerAperture(Mat imageContour, out int[] aperture, int leftUpper, int rightUpper, int leftLower, int rightLower, int[] dataArea)
{
aperture = new int[2];
int middle = (dataArea[1] + dataArea[2]) / 2;
Mat fill = new Mat();
Fill(imageContour, out fill, 1);
Mat fanse = 1 - fill;
Scalar sum = fanse.Sum();
if ((int)sum != 0)
{
imageContour = fill.Clone();
}
Mat result = 1 - imageContour;
Scalar sumLeft = new Scalar(0);
for (int j = dataArea[0]; j < middle; j++)
{
sumLeft = result[leftUpper<0?0: leftUpper, leftLower, j, j + 1].Sum();
if ((int)sumLeft == 0)
{
aperture[0] = j;
break;
}
}
Scalar sumRight = new Scalar(0);
for (int j = dataArea[3]; j > middle; j--)
{
sumRight = result[rightUpper, rightLower, j - 1, j].Sum();
if ((int)sumRight == 0)
{
aperture[1] = j;
break;
}
}
if(fill != null)
{
fill.Dispose();
}
}
public void GetShenmangLowerAperture2(Mat imageContour, out int[] aperture, int leftUpper, int rightUpper, int leftLower, int rightLower, int[] dataArea)
{
aperture = new int[2] { 0, 0 };
int middle = (dataArea[1] + dataArea[2]) / 2;
Mat fanse = 1 - imageContour;
int offset = 20;
int sum = 0;
for (int j = dataArea[1]; j < middle; j++)
{
sum = 0;
for (int i = leftUpper - offset; i < leftLower - offset; i++)
{
sum += fanse.Get(i, j);
if (fanse.Get(i, j) > 0)
break;
}
if (sum == 0)
{
aperture[0] = j;
break;
}
}
for (int j = dataArea[2]; j > middle; j--)
{
sum = 0;
for (int i = rightUpper - offset; i < rightLower - offset; i++)
{
sum += fanse.Get(i, j);
if (fanse.Get(i, j) > 0)
break;
}
if (sum == 0)
{
aperture[1] = j;
break;
}
}
}
///
/// 得到深盲孔的胶线
///
/// 输入图像,一般是绿色通道
/// 输出胶线纵坐标
/// 左边上界
/// 左边下界
/// 右边上界
/// 右边下界
/// 提取区域
public void GetGlue(Mat image, out int[] glueOrdinate, int leftUpper, int leftLower, int rightUpper, int rightLower, int[] dataArea)
{
glueOrdinate = new int[2];
int[] maybePosition = new int[2];
//int[] zero = new int[2];
InputArray kernel = InputArray.Create(new int[3, 3] { { 0, -1, 0 }, { -1, 5, -1 }, { 0, -1, 0 } });
Mat seOpen = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));
Mat seDilate = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(7, 1));
Mat crop1 = image[leftUpper, leftLower, dataArea[0], dataArea[1]];
//将裁剪区域改为面铜+基材铜附近
//int leftMiddleMiantong_Jicaitong = (dataArea[0] + dataArea[1]) / 2;
//Mat crop1 = image[leftUpper, leftLower, leftMiddleMiantong_Jicaitong - 10, leftMiddleMiantong_Jicaitong + 10];
Mat filter1 = new Mat();
Cv2.Filter2D(crop1, filter1, -1, kernel);
Cv2.ConvertScaleAbs(filter1, filter1);
Mat thresh1 = 1 - filter1.Threshold(0, 1, ThresholdTypes.Otsu);
Mat open1 = new Mat();
Cv2.MorphologyEx(thresh1, open1, MorphTypes.Open, seOpen);
Cv2.MorphologyEx(open1, open1, MorphTypes.Close, seOpen);
Cv2.Dilate(open1, open1, seDilate);
Fill(open1, out open1, 1);
//new Window("crop1", WindowMode.Normal, crop1);
//new Window("thresh2", WindowMode.Normal, 255 - crop1.Threshold(0, 255, ThresholdTypes.Otsu));
//new Window("thresh1", WindowMode.Normal, thresh1 * 255);
//new Window("end", WindowMode.Normal, open1 * 255);
//Cv2.WaitKey();
Scalar sum1 = new Scalar(0);
Scalar lastSum1 = new Scalar(0);
Scalar sub1 = new Scalar(0);
Scalar subMax1 = new Scalar(0);
Scalar max1 = new Scalar(0);
Scalar zero1 = new Scalar(0);
for (int i = 2; i < crop1.Rows - 2; i++)
{
sum1 = open1[i, i + 2, 0, open1.Cols - 1].Sum();
lastSum1 = open1[i - 2, i, 0, open1.Cols - 1].Sum();
//zero1 = open1[i - 1, i, 0, open1.Cols - 1].Sum();
sub1 = Math.Abs((int)sum1 - (int)lastSum1);
if ((int)max1 < (int)sum1)
{
max1 = sum1;
glueOrdinate[0] = i + leftUpper;
}
if ((int)subMax1 < (int)sub1)
{
subMax1 = sub1;
maybePosition[0] = i + leftUpper;
}
//if ((int)zero1 < 10)
//{
// zero[0] = i + leftUpper;
//}
}
Mat crop2 = image[rightUpper, rightLower, dataArea[2], dataArea[3]];
////将裁剪区域改为面铜+基材铜附近
//int rightMiddleMiantong_Jicaitong = (dataArea[2] + dataArea[3]) / 2;
//Mat crop2 = image[rightUpper, rightLower, rightMiddleMiantong_Jicaitong - 10, rightMiddleMiantong_Jicaitong + 10];
Mat filter2 = new Mat();
Cv2.Filter2D(crop2, filter2, -1, kernel);
Cv2.ConvertScaleAbs(filter2, filter2);
Mat thresh2 = 1 - filter2.Threshold(0, 1, ThresholdTypes.Otsu);
Mat open2 = new Mat();
Cv2.MorphologyEx(thresh2, open2, MorphTypes.Open, seOpen);
Cv2.MorphologyEx(open2, open2, MorphTypes.Close, seOpen);
Cv2.Dilate(open2, open2, seDilate);
Fill(open2, out open2, 1);
//new Window("thresh2", WindowMode.Normal, thresh2 * 255);
//new Window("end2", WindowMode.Normal, open2 * 255);
//Cv2.WaitKey();
Scalar sum2 = new Scalar(0);
Scalar lastSum2 = new Scalar(0);
Scalar sub2 = new Scalar(0);
Scalar subMax2 = new Scalar(0);
Scalar max2 = new Scalar(0);
Scalar zero2 = new Scalar(0);
for (int i = 2; i < crop2.Rows - 2; i++)
{
sum2 = open2[i, i + 2, 0, open2.Cols - 1].Sum();
lastSum2 = open2[i - 2, i, 0, open2.Cols - 1].Sum();
//zero2 = open2[i - 1, i, 0, open2.Cols - 1].Sum();
sub2 = Math.Abs((int)sum2 - (int)lastSum2);
if ((int)max2 < (int)sum2)
{
max2 = sum2;
glueOrdinate[1] = i + rightUpper;
}
if ((int)subMax2 < (int)sub2)
{
subMax2 = sub2;
maybePosition[1] = i + rightUpper;
}
//if ((int)zero2 < 10)
//{
// zero[1] = i + rightUpper;
//}
}
if (glueOrdinate[0] > maybePosition[0])
{
for (int j = maybePosition[0] - leftUpper; j < glueOrdinate[0] - leftUpper; j++)
{
if ((int)open1[j, j + 1, 0, open1.Cols - 1].Sum() == 0)
{
sum1 = new Scalar(0);
lastSum1 = new Scalar(0);
sub1 = new Scalar(0);
subMax1 = new Scalar(0);
max1 = new Scalar(0);
for (int i = maybePosition[0] - leftUpper + 2; i < crop1.Rows - 2; i++)
{
sum1 = open1[i, i + 2, 0, open1.Cols - 1].Sum();
lastSum1 = open1[i - 2, i, 0, open1.Cols - 1].Sum();
sub1 = Math.Abs((int)sum1 - (int)lastSum1);
if ((int)max1 < (int)sum1)
{
max1 = sum1;
glueOrdinate[0] = i + leftUpper;
}
if ((int)subMax1 < (int)sub1)
{
subMax1 = sub1;
maybePosition[0] = i + leftUpper;
}
}
break;
}
}
if (glueOrdinate[0] > maybePosition[0])
{
//if (Math.Abs(zero[0] - maybePosition[0]) > 15&&zero[0]>10)
// glueOrdinate[0] = zero[0];
//else
glueOrdinate[0] = maybePosition[0];
}
}
if (glueOrdinate[1] > maybePosition[1])
{
for (int j = maybePosition[1] - rightUpper; j < glueOrdinate[1] - rightUpper; j++)
{
if ((int)open2[j, j + 1, 0, open2.Cols - 1].Sum() == 0)
{
sum2 = new Scalar(0);
lastSum2 = new Scalar(0);
sub2 = new Scalar(0);
subMax2 = new Scalar(0);
max2 = new Scalar(0);
for (int i = maybePosition[1] - rightUpper + 2; i < crop2.Rows - 2; i++)
{
sum2 = open2[i, i + 2, 0, open2.Cols - 1].Sum();
lastSum2 = open2[i - 2, i, 0, open2.Cols - 1].Sum();
sub2 = Math.Abs((int)sum2 - (int)lastSum2);
if ((int)max2 < (int)sum2)
{
max2 = sum2;
glueOrdinate[1] = i + rightUpper;
}
if ((int)subMax2 < (int)sub2)
{
subMax2 = sub2;
maybePosition[1] = i + rightUpper;
}
}
break;
}
}
if (glueOrdinate[1] > maybePosition[1])
{
//if (Math.Abs(zero[1] - maybePosition[1]) > 15&&zero[1]>10)
// glueOrdinate[1] = zero[1];
//else
glueOrdinate[1] = maybePosition[1];
}
}
//LineShow(crop1, 10, glueOrdinate[0] - leftUpper, 20, glueOrdinate[0] - leftUpper);
//new Window("crop1", WindowMode.Normal, crop1);
//new Window("thresh1", WindowMode.Normal, open1 * 255);
//new Window("thresh2", WindowMode.Normal, open2 * 255);
//Cv2.WaitKey();
}
///
/// 计算胶线坐标,修改了判定时条件,先用于深盲孔双层
///
///
///
///
///
///
///
///
public void GetGlue2(Mat image, out int[] glueOrdinate, int leftUpper, int leftLower, int rightUpper, int rightLower, int[] dataArea)
{
glueOrdinate = new int[2];
int[] maybePosition = new int[2];
//int[] zero = new int[2];
InputArray kernel = InputArray.Create(new int[3, 3] { { 0, -1, 0 }, { -1, 5, -1 }, { 0, -1, 0 } });
Mat seOpen = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));
Mat seDilate = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));
int width1 = dataArea[1] - dataArea[0];
Mat crop1 = image[leftUpper, leftLower, dataArea[0], dataArea[1]];
if (width1 > 50)
{
crop1 = image[leftUpper, leftLower, dataArea[0] + (width1 - 50) / 2, dataArea[1] - (width1 - 50) / 2];
width1 = 50;
}
//将裁剪区域改为面铜+基材铜附近
//int leftMiddleMiantong_Jicaitong = (dataArea[0] + dataArea[1]) / 2;
//Mat crop1 = image[leftUpper, leftLower, leftMiddleMiantong_Jicaitong - 10, leftMiddleMiantong_Jicaitong + 10];
int areaSize1 = crop1.Rows * crop1.Cols;
Mat filter1 = new Mat();
Cv2.Filter2D(crop1, filter1, -1, kernel);
Cv2.ConvertScaleAbs(filter1, filter1);
Mat thresh1 = 1 - filter1.Threshold(0, 1, ThresholdTypes.Otsu);
Mat open1 = new Mat();
Cv2.MorphologyEx(thresh1, open1, MorphTypes.Open, seOpen);
Cv2.MorphologyEx(open1, open1, MorphTypes.Close, seOpen);
Cv2.Dilate(open1, open1, seDilate);
Fill(open1, out open1, 1);
Scalar area1 = open1.Sum();
while ((int)area1 > areaSize1 * 0.9)
{
leftUpper += 5;
crop1 = image[leftUpper, leftLower, dataArea[0], dataArea[1]];
if (width1 > 50)
{
crop1 = image[leftUpper, leftLower, dataArea[0] + (width1 - 50) / 2, dataArea[1] - (width1 - 50) / 2];
width1 = 50;
}
filter1 = new Mat();
Cv2.Filter2D(crop1, filter1, -1, kernel);
Cv2.ConvertScaleAbs(filter1, filter1);
thresh1 = 1 - filter1.Threshold(0, 1, ThresholdTypes.Otsu);
open1 = new Mat();
Cv2.MorphologyEx(thresh1, open1, MorphTypes.Open, seOpen);
Cv2.MorphologyEx(open1, open1, MorphTypes.Close, seOpen);
Cv2.Dilate(open1, open1, seDilate);
Fill(open1, out open1, 1);
areaSize1 = crop1.Rows * crop1.Cols;
area1 = open1.Sum();
}
//new Window("crop1", WindowMode.Normal, crop1);
////new Window("thresh2", WindowMode.Normal, 255 - crop1.Threshold(0, 255, ThresholdTypes.Otsu));
//new Window("thresh1", WindowMode.Normal, thresh1 * 255);
//new Window("end", WindowMode.Normal, open1 * 255);
//Cv2.WaitKey();
Scalar sum1 = new Scalar(0);
Scalar lastSum1 = new Scalar(0);
Scalar sub1 = new Scalar(0);
Scalar subMax1 = new Scalar(0);
Scalar max1 = new Scalar(0);
Scalar zero1 = new Scalar(0);
int y = 0;
for (int i = crop1.Rows - 4; i > 4; i--)
{
sum1 = open1[i - 3, i, 0, open1.Cols].Sum();
if ((int)sum1 > width1 * 2.9)
{
y = i;
break;
}
}
for (int i = y - 1; i > 4; i--)
{
sum1 = open1[i - 3, i, 0, open1.Cols].Sum();
if ((int)sum1 < width1 * 2.2)
{
glueOrdinate[0] = i + leftUpper;
break;
}
}
//右
Mat crop2 = image[rightUpper, rightLower, dataArea[2], dataArea[3]];
int width2 = dataArea[3] - dataArea[2];
if (width2 > 50)
{
crop2 = image[rightUpper, rightLower, dataArea[2] + (width2 - 50) / 2, dataArea[3] - (width2 - 50) / 2];
width2 = crop2.Cols;
}
////将裁剪区域改为面铜+基材铜附近
//int rightMiddleMiantong_Jicaitong = (dataArea[2] + dataArea[3]) / 2;
//Mat crop2 = image[rightUpper, rightLower, rightMiddleMiantong_Jicaitong - 10, rightMiddleMiantong_Jicaitong + 10];
int areaSize2 = crop2.Rows * crop2.Cols;
Mat filter2 = new Mat();
Cv2.Filter2D(crop2, filter2, -1, kernel);
Cv2.ConvertScaleAbs(filter2, filter2);
Mat thresh2 = 1 - filter2.Threshold(0, 1, ThresholdTypes.Otsu);
Mat open2 = new Mat();
Cv2.MorphologyEx(thresh2, open2, MorphTypes.Open, seOpen);
Cv2.MorphologyEx(open2, open2, MorphTypes.Close, seOpen);
Cv2.Dilate(open2, open2, seDilate);
Fill(open2, out open2, 1);
Scalar area2 = open2.Sum();
while ((int)area2 > areaSize2 * 0.9)
{
rightUpper += 5;
crop2 = image[rightUpper, rightLower, dataArea[2], dataArea[3]];
width2 = dataArea[3] - dataArea[2];
if (width2 > 50)
{
crop2 = image[rightUpper, rightLower, dataArea[2] + (width2 - 50) / 2, dataArea[3] - (width2 - 50) / 2];
width2 = crop2.Cols;
}
areaSize2 = crop2.Rows * crop2.Cols;
filter2 = new Mat();
Cv2.Filter2D(crop2, filter2, -1, kernel);
Cv2.ConvertScaleAbs(filter2, filter2);
thresh2 = 1 - filter2.Threshold(0, 1, ThresholdTypes.Otsu);
open2 = new Mat();
Cv2.MorphologyEx(thresh2, open2, MorphTypes.Open, seOpen);
Cv2.MorphologyEx(open2, open2, MorphTypes.Close, seOpen);
Cv2.Dilate(open2, open2, seDilate);
Fill(open2, out open2, 1);
area2 = open2.Sum();
}
//new Window("crop2", WindowMode.Normal, crop2);
//new Window("filter2", WindowMode.Normal, filter2);
//new Window("thresh2", WindowMode.Normal, thresh2 * 255);
//new Window("end2", WindowMode.Normal, open2 * 255);
//Cv2.WaitKey();
Scalar sum2 = new Scalar(0);
Scalar lastSum2 = new Scalar(0);
Scalar sub2 = new Scalar(0);
Scalar subMax2 = new Scalar(0);
Scalar max2 = new Scalar(0);
Scalar zero2 = new Scalar(0);
y = 0;
for (int i = crop2.Rows - 4; i > 4; i--)
{
sum2 = open2[i - 3, i, 0, open2.Cols].Sum();
if ((int)sum2 > width2 * 2.9)
{
y = i;
break;
}
}
for (int i = y - 1; i > 4; i--)
{
sum2 = open2[i - 3, i, 0, open2.Cols].Sum();
if ((int)sum2 < width2 * 2.4)
{
glueOrdinate[1] = i + rightUpper;
break;
}
}
if (glueOrdinate[0] == 0)
glueOrdinate[0] = leftUpper;
if (glueOrdinate[1] == 0)
glueOrdinate[1] = rightUpper;
}
///
/// 得到深盲孔胶内缩的内部坐标
///
/// 二值图像
/// 输出内部坐标,先左后右
/// 输出外部坐标,先左后右
/// 上界
/// 胶线的坐标
/// 下界
/// 提取数据区域
public void GetWaist(Mat imageContour, out int[] upperWaist, out int[] lowerWaist, int upperBound, int[] glueOrdinate, int lowerBound, int[] dataArea)
{
//Cv2.ImWrite(@"C:\Users\zyh\Desktop\imageContour.jpg", imageContour * 255);
//寻找连通区域,把除第一个联通区域的都置为0
Mat labelMat = new Mat();
Mat stats = new Mat();
Mat centroids = new Mat();
int nums = Cv2.ConnectedComponentsWithStats(imageContour, labelMat, stats, centroids, PixelConnectivity.Connectivity8);
int y = stats.At(1, 1);
int height = stats.At(1, 3);
for(int h=height+1; h< imageContour.Height; h++)
{
imageContour.Row[h] *= 0;
}
upperWaist = new int[2] { 0, 0 };
lowerWaist = new int[2] { 0, 0 };
int middle = (dataArea[1] + dataArea[2]) / 2;
int min_left=int.MaxValue, max_left = 0;
int min_left_x = 0, max_left_x = 0;
for (int j = middle-30; j > dataArea[1]; j--)
{
int v = imageContour.Col[j].CountNonZero();
if (v <= min_left) { min_left = v; min_left_x = j; }
if (v >= max_left) { max_left = v; max_left_x = j; }
}
upperWaist[0] = max_left_x;
OpenCvSharp.Rect rect_Left = new Rect(dataArea[1], upperBound, max_left_x- dataArea[1], lowerBound- upperBound);
Mat temp_left = new Mat(imageContour, rect_Left);
//Cv2.ImWrite(@"C:\Users\zyh\Desktop\temp_left.jpg", temp_left*255);
bool f_l = false;
for (int j=0; j< temp_left.Width; j++)
{
if(!f_l && temp_left.Col[j].CountNonZero()>0)
{
f_l = true;
lowerWaist[0] = j + dataArea[1];
//break;
}
else if(temp_left.Col[j].CountNonZero()== temp_left.Height)
{
upperWaist[0] = j + dataArea[1];
break;
}
}
int min_right = int.MaxValue, max_right = 0;
int min_right_x = 0, max_right_x = 0;
for (int j = middle+30; j < dataArea[2]; j++)
{
int v = imageContour.Col[j].CountNonZero();
if (v <= min_right) { min_right = v; min_right_x = j; }
if (v >= max_right) { max_right = v; max_right_x = j; }
}
upperWaist[1] = max_right_x;
OpenCvSharp.Rect rect_right = new Rect(max_right_x, upperBound, dataArea[2]- max_right_x, lowerBound - upperBound);
Mat temp_right = new Mat(imageContour, rect_right);
//Cv2.ImWrite(@"C:\Users\zyh\Desktop\rect_right.jpg", temp_right*255);
bool f_r = false;
for (int j = temp_right.Width-1; j > 0; j--)
{
if (!f_r && temp_right.Col[j].CountNonZero() > 0)
{
f_r = true;
lowerWaist[1] = j+ max_right_x;
//break;
}
else if(temp_right.Col[j].CountNonZero() == temp_right.Height)
{
upperWaist[1] = j + max_right_x;
break;
}
}
/*Mat fanse = 1 - imageContour;
//上
for (int j = middle; j > dataArea[0]; j--)
{
for (int i = upperBound; i < glueOrdinate[0]; i++)
{
if (fanse.Get(i, j) > 0*//* && j< (middle + dataArea[0]) / 2*//*)
{
upperWaist[0] = j;
break;
}
}
if (upperWaist[0] != 0)
break;
}
for (int j = middle; j < dataArea[3]; j++)
{
for (int i = upperBound; i < glueOrdinate[1]; i++)
{
if (fanse.Get(i, j) > 0*//* && j > (middle + dataArea[3])/2*//*)
{
upperWaist[1] = j;
break;
}
}
if (upperWaist[1] != 0)
break;
}
//下
for (int j = (dataArea[0] + dataArea[1]) / 2; j < middle; j++)
{
for (int i = glueOrdinate[0] - 20; i < lowerBound; i++)
{
//new Window("imageContour", WindowMode.Normal, imageContour * 255);
//Cv2.WaitKey();
if (imageContour.Get(i, j) > 0)
{
lowerWaist[0] = j;
break;
}
}
if (lowerWaist[0] != 0)
break;
}
for (int j = (dataArea[3] + dataArea[2]) / 2; j > middle; j--)
{
for (int i = glueOrdinate[1] - 20; i < lowerBound; i++)
{
if (imageContour.Get(i, j) > 0)
{
lowerWaist[1] = j;
break;
}
}
if (lowerWaist[1] != 0)
break;
}*/
}
///
/// 提取胶内缩,将下边界改为左右边界
///
/// 二值图像
/// 输出内部坐标,先左后右
/// 输出外部坐标,先左后右
/// 上界
/// 胶线的坐标
/// 下左界
/// 下右界
/// 提取数据区域
public void GetWaistNew(Mat imageContour, out int[] upperWaist, out int[] lowerWaist, int upperBound, int[] glueOrdinate, int leftLower, int rightLower, int[] dataArea)
{
upperWaist = new int[2] { 0, 0 };
lowerWaist = new int[2] { 0, 0 };
int middle = (dataArea[1] + dataArea[2]) / 2;
Mat fanse = 1 - imageContour;
//上
for (int j = middle; j > dataArea[0]; j--)
{
for (int i = upperBound; i < glueOrdinate[0]; i++)
{
if (fanse.Get(i, j) > 0)
{
upperWaist[0] = j;
break;
}
}
if (upperWaist[0] != 0)
break;
}
for (int j = middle; j < dataArea[3]; j++)
{
for (int i = upperBound; i < glueOrdinate[1]; i++)
{
if (fanse.Get(i, j) > 0)
{
upperWaist[1] = j;
break;
}
}
if (upperWaist[1] != 0)
break;
}
//下
//左
for (int j = (dataArea[0] + dataArea[1]) / 2; j < middle; j++)
{
for (int i = glueOrdinate[0] - 20; i < leftLower; i++)
{
//new Window("imageContour", WindowMode.Normal, imageContour * 255);
//Cv2.WaitKey();
if (imageContour.Get(i, j) > 0)
{
lowerWaist[0] = j;
break;
}
}
if (lowerWaist[0] != 0)
break;
}
//右
for (int j = (dataArea[3] + dataArea[2]) / 2; j > middle; j--)
{
for (int i = glueOrdinate[1] - 20; i < rightLower; i++)
{
if (imageContour.Get(i, j) > 0)
{
lowerWaist[1] = j;
break;
}
}
if (lowerWaist[1] != 0)
break;
}
}
///
/// 得到精准的面铜和基材铜的纵坐标
///
/// 最好是绿色通道图
/// 上边界
/// 下边界
/// 左边界
/// 右边界
/// 面铜的横坐标
/// 基材铜的横坐标
/// 面铜的纵坐标
/// 基材铜的纵坐标
/// 输出纵坐标,面铜和基材铜
public void InsideLine_Accuracy(Mat image, int upperBound, int lowerBound, int leftBoundary, int rightBoundary, int middleMiantong, int middleJicaitong
, double ordinateL2Miantong, double ordinateL2Jicaitong, out double[] ordinateL2_Acc, int isMiantong = 0, int banceng = 2/*-1*/, bool showMat = false)
{
//第5671deng类别图片需要完善位置精准度,以及 调试有些图片位置计算错误的原因,并纠正
Mat crop = image[upperBound, lowerBound, leftBoundary, rightBoundary];
//if (isMiantong > 0 && showMat)
//{
// Mat mat1 = new Mat();
// Cv2.Normalize(crop, mat1, 0, 255, NormTypes.MinMax);
// Cv2.ImWrite(@"C:\Users\54434\Desktop\crop.JPG", crop);
//}
Mat filter = new Mat();//滤波增强对比
InputArray kernel = InputArray.Create(new int[3, 3] { { 0, -1, 0 }, { -1, 5, -1 }, { 0, -1, 0 } });
Cv2.Filter2D(crop, filter, -1, kernel);
Cv2.ConvertScaleAbs(filter, filter);
Mat thresh = 1 - filter.Threshold(0, 1, ThresholdTypes.Otsu);// 二值化
Mat seOpen = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(15/*15*/, 1/*水平线<--3, 3*/));// 开运算
Mat open = new Mat();
//OpenCV提取图像中的垂直线(或者水平线) 定义结构元素,开操作
Cv2.MorphologyEx(thresh, open, MorphTypes.Open, seOpen);
if (isMiantong > 0 && showMat)
{
//Cv2.ImWrite(@"C:\Users\54434\Desktop\filter.JPG", filter/* * 127*/);
}
//Scalar sum = new Scalar(0);
//Scalar max1 = new Scalar(0);
//Scalar max = new Scalar(0);
//double meanOrdinate1 = 0;
double ordinateL2Miantong_acc = ordinateL2Miantong;
double ordinateL2Jicaitong_acc = ordinateL2Jicaitong;
//ordinateL2_Acc = new double[] { ordinateL2Miantong_acc, ordinateL2Jicaitong_acc };
//return;
int topOri = (int)ordinateL2Miantong_acc - upperBound - 20;// 10;// 15;
int bottomOri = (int)ordinateL2Miantong_acc - upperBound + 20;// 10;// 15;
if (topOri < 10) topOri = 10;
else if (topOri > crop.Rows/3 && topOri > 20) topOri = 20;//对初判定位置距离太远的进行纠偏
if (bottomOri > crop.Rows - 10) bottomOri = crop.Rows - 10;
else if (bottomOri < crop.Rows*2/3 && bottomOri < crop.Rows - 20) bottomOri = crop.Rows - 20;//对初判定位置距离太远的进行纠偏
bool miantongChanged = false;
int miantongValue = crop.Get((int)ordinateL2Miantong - upperBound, middleMiantong - leftBoundary);
bool isHoriMost = false;//用来判定大横线哪个更加位置居中
int centerVer = crop.Rows / 2;// (topOri + bottomOri) / 2;//用来判定大横线哪个更加位置居中
for (int i = topOri; i < bottomOri; i++)
{
int miantongValueI = crop.Get(i, middleMiantong - leftBoundary);
Scalar sum = open[i, i + 1, 0, crop.Cols - 1].Sum();
if (miantongValueI < miantongValue - 1 || (!miantongChanged && miantongValueI < miantongValue + 100)
|| crop.Cols - 20 < (int)sum)
{
//if (open.Get(i, middleMiantong - leftBoundary) > 0)
//Scalar sum = open[i, i + 2, 0, crop.Cols - 1].Sum();
//if (30/*30*/ < (int)sum)
if (6/*30*/ < (int)sum && !isHoriMost
||(crop.Cols - 20 < (int)sum && isHoriMost && Math.Abs(centerVer - i) < Math.Abs(centerVer - (ordinateL2Miantong_acc - upperBound))))
{
ordinateL2Miantong_acc = i + upperBound;
miantongValue = miantongValueI;
miantongChanged = true;
//待自测scc-2
//if (isMiantong == 1)
// break;
if (crop.Cols - 20 < (int)sum/* && Math.Abs(centerVer - (ordinateL2Jicaitong_acc - upperBound)) < 10*/)
{
isHoriMost = true;
//break;
}
}
}
}
if (ordinateL2Miantong_acc == 10 + upperBound)
{//将明显不对的测量结果居中取值
ordinateL2Miantong_acc = centerVer + upperBound;
}
//if (isMiantong == 1 && !miantongChanged)
//{
// Mat thresh1 = 1 - filter.Threshold(0, 1, ThresholdTypes.Otsu);// 二值化
// Mat seOpen1 = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(9/*15*/, 1/*水平线<--3, 3*/));// 开运算
// Mat open1 = new Mat();
// //OpenCV提取图像中的垂直线(或者水平线) 定义结构元素,开操作
// Cv2.MorphologyEx(thresh1, open1, MorphTypes.Open, seOpen1);
// //if (isMiantong > 0 && showMat)
// //{
// // new Window("open1", WindowMode.Normal, open1 * 255);
// // Cv2.WaitKey();
// //}
// for (int i = topOri; i < bottomOri; i++)
// {
// //int miantongValueI = crop.Get(i, middleMiantong - leftBoundary);
// //if (miantongValueI < 200/*miantongValue*/)
// {
// if (open1.Get(i, middleMiantong - leftBoundary) > 0)
// //Scalar sum = open[i, i + 2, 0, crop.Cols - 1].Sum();
// //if (30/*30*/ < (int)sum)
// {
// ordinateL2Miantong_acc = i + upperBound;
// miantongValue = crop.Get(i, middleMiantong - leftBoundary);// miantongValueI;
// miantongChanged = true;
// break;
// }
// }
// }
//}
isHoriMost = false;//用来判定大横线哪个更加位置居中
bool jicaitongChanged = false;
int jicaitongValue = crop.Get((int)ordinateL2Jicaitong - upperBound, middleJicaitong - leftBoundary);
for (int i = /*0*/topOri; i < bottomOri; i++)
{
int jicaitongValueI = crop.Get(i, middleJicaitong - leftBoundary);
Scalar sum = open[i, i + 1, 0, crop.Cols - 1].Sum();
if (jicaitongValueI < jicaitongValue - 1 || (!jicaitongChanged && jicaitongValueI < jicaitongValue + 100)
|| crop.Cols - 20 < (int)sum)
{
//if (open.Get(i, middleJicaitong - leftBoundary) > 0)
//Scalar sum = open[i, i + 2, 0, crop.Cols - 1].Sum();
////Scalar sum = open[i, i + 2, middleJicaitong - leftBoundary - 4, middleJicaitong - leftBoundary + 4].Sum();
if (6/*30*/ < (int)sum && !isHoriMost
|| (crop.Cols - 20 < (int)sum && isHoriMost && Math.Abs(centerVer - i) < Math.Abs(centerVer - (ordinateL2Jicaitong_acc - upperBound))))
{
ordinateL2Jicaitong_acc = i + upperBound;
jicaitongValue = jicaitongValueI;
jicaitongChanged = true;
//待自测scc-2
//if (isMiantong == 1)
// break;
if (crop.Cols - 20 < (int)sum/* && Math.Abs(centerVer - (ordinateL2Jicaitong_acc - upperBound)) < 10*/)
{
isHoriMost = true;
//break;
}
}
}
}
if (ordinateL2Jicaitong_acc == 10 + upperBound)
{//将明显不对的测量结果居中取值
ordinateL2Jicaitong_acc = centerVer + upperBound;
}
if (!miantongChanged && !jicaitongChanged)
{
int topOri_1 = topOri;
if (topOri > 10) topOri_1 = 10;
int bottomOri_1 = bottomOri;
if (bottomOri < crop.Rows - 10) bottomOri_1 = crop.Rows - 10;
miantongValue = crop.Get((int)ordinateL2Miantong - upperBound, middleMiantong - leftBoundary);
for (int i = topOri_1; i < bottomOri_1; i++)
{
int miantongValueI = crop.Get(i, middleMiantong - leftBoundary);
Scalar sum = open[i, i + 1, 0, crop.Cols - 1].Sum();
if (miantongValueI < miantongValue - 1 || (!miantongChanged && miantongValueI < miantongValue + 100)
|| crop.Cols - 20 < (int)sum)
{
if (6 < (int)sum)
{
ordinateL2Miantong_acc = i + upperBound;
miantongValue = miantongValueI;
miantongChanged = true;
if (crop.Cols - 20 < (int)sum)
break;
}
}
if (i == topOri - 1) i = bottomOri;
}
jicaitongValue = crop.Get((int)ordinateL2Jicaitong - upperBound, middleJicaitong - leftBoundary);
for (int i = topOri_1; i < bottomOri_1; i++)
{
int jicaitongValueI = crop.Get(i, middleJicaitong - leftBoundary);
Scalar sum = open[i, i + 1, 0, crop.Cols - 1].Sum();
if (jicaitongValueI < jicaitongValue - 1 || (!jicaitongChanged && jicaitongValueI < jicaitongValue + 100)
|| crop.Cols - 20 < (int)sum)
{
if (6 < (int)sum)
{
ordinateL2Jicaitong_acc = i + upperBound;
jicaitongValue = jicaitongValueI;
jicaitongChanged = true;
if (crop.Cols - 20 < (int)sum)
break;
}
}
if (i == topOri - 1) i = bottomOri;
}
}
if ((isMiantong == 1 || isMiantong == 2) && (!miantongChanged /*//待自测scc-3_1 &&*/|| !jicaitongChanged))
{
Mat thresh1 = 1 - filter.Threshold(0, 1, ThresholdTypes.Otsu);// 二值化
Mat seOpen1 = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(9/*15*/, 1/*水平线<--3, 3*/));// 开运算
Mat open1 = new Mat();
//OpenCV提取图像中的垂直线(或者水平线) 定义结构元素,开操作
Cv2.MorphologyEx(thresh1, open1, MorphTypes.Open, seOpen1);
//if (isMiantong > 0 && showMat)
//{
// new Window("open1", WindowMode.Normal, open1 * 255);
// Cv2.WaitKey();
//}
//待自测scc-3_1
if (isMiantong == 1 && !miantongChanged || isMiantong == 2 && !jicaitongChanged)
for (int i = bottomOri; i > topOri; i--)
{
//还差第3、5、7类别图片需要完善位置精准度,以及
//调试有些图片位置计算错误的原因,并纠正!!!!!!!!!!!!
{
if (isMiantong == 1 && open1.Get(i, middleMiantong - leftBoundary) > 0
|| isMiantong == 2 && open1.Get(i, middleJicaitong - leftBoundary) > 0)
{
if (isMiantong == 1)
ordinateL2Miantong_acc = i + upperBound;
else if (isMiantong == 2)
ordinateL2Jicaitong_acc = i + upperBound;
break;
}
}
}
//if (isMiantong == 1 && !miantongChanged)
// for (int i = topOri; i < bottomOri; i++)//for (int i = bottomOri; i > topOri; i--)
// {
// if (open1.Get(i, middleMiantong - leftBoundary) > 0)
// {
// ordinateL2Miantong_acc = i + upperBound;
// break;
// }
// }
//if (isMiantong == 2 && !jicaitongChanged)
// for (int i = bottomOri; i > topOri; i--)
// {
// if (open1.Get(i, middleJicaitong - leftBoundary) > 0)
// {
// ordinateL2Jicaitong_acc = i + upperBound;
// break;
// }
// }
//if (isMiantong == 1 && !jicaitongChanged)
// for (int i = topOri; i < bottomOri; i++)
// {
// {
// if (open1.Get(i, middleJicaitong - leftBoundary) > 0)
// {
// ordinateL2Jicaitong_acc = i + upperBound;
// break;
// }
// }
// }
//if (isMiantong == 2 && !miantongChanged)
// for (int i = bottomOri; i > topOri; i--)//for (int i = topOri; i < bottomOri; i++)
// {
// {
// if (open1.Get(i, middleMiantong - leftBoundary) > 0)
// {
// ordinateL2Miantong_acc = i + upperBound;
// break;
// }
// }
// }
if (isMiantong == 1 && !jicaitongChanged || isMiantong == 2 && !miantongChanged)
for (int i = topOri; i < bottomOri; i++)
{
{
if (isMiantong == 1 && open1.Get(i, middleJicaitong - leftBoundary) > 0
|| isMiantong == 2 && open1.Get(i, middleMiantong - leftBoundary) > 0)
{
if (isMiantong == 1)
ordinateL2Jicaitong_acc = i + upperBound;
else if (isMiantong == 2)
ordinateL2Miantong_acc = i + upperBound;
break;
}
}
}
}
//if (isMiantong == 1 && !jicaitongChanged)
//{
// Mat thresh1 = 1 - filter.Threshold(0, 1, ThresholdTypes.Otsu);// 二值化
// Mat seOpen1 = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(9/*15*/, 1/*水平线<--3, 3*/));// 开运算
// Mat open1 = new Mat();
// //OpenCV提取图像中的垂直线(或者水平线) 定义结构元素,开操作
// Cv2.MorphologyEx(thresh1, open1, MorphTypes.Open, seOpen1);
// //if (isMiantong > 0 && showMat)
// //{
// // new Window("open1", WindowMode.Normal, open1 * 255);
// // Cv2.WaitKey();
// //}
// for (int i = bottomOri; i > topOri; i--)
// {
// //int miantongValueI = crop.Get(i, middleMiantong - leftBoundary);
// //if (miantongValueI < 200/*miantongValue*/)
// {
// if (open1.Get(i, middleJicaitong - leftBoundary) > 0)
// //Scalar sum = open[i, i + 2, 0, crop.Cols - 1].Sum();
// //if (30/*30*/ < (int)sum)
// {
// ordinateL2Jicaitong_acc = i + upperBound;
// jicaitongValue = crop.Get(i, middleJicaitong - leftBoundary);// miantongValueI;
// jicaitongChanged = true;
// break;
// }
// }
// }
//}
////if (isMiantong == 1 && jicaitongChanged && showMat)
////{
//// Mat thresh1 = 1 - filter.Threshold(0, 1, ThresholdTypes.Otsu);// 二值化
//// //Mat seOpen = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(11/*15*/, 1/*水平线<--3, 3*/));// 开运算
//// //Mat open = new Mat();
//// ////OpenCV提取图像中的垂直线(或者水平线) 定义结构元素,开操作
//// //Cv2.MorphologyEx(thresh, open, MorphTypes.Open, seOpen);
//// ////if (isMiantong > 0 && showMat)
//// ////{
//// //// new Window("open", WindowMode.Normal, open * 255);
//// //// Cv2.WaitKey();
//// ////}
////}
ordinateL2_Acc = new double[] { ordinateL2Miantong_acc, ordinateL2Jicaitong_acc };
}
///
/// 得到内部线纵坐标
///
/// 最好是绿色通道图
/// 上边界
/// 下边界
/// 左边界
/// 右边界
/// 输出坐标
public double InsideLine(Mat image, int upperBound, int lowerBound, int leftBoundary, int rightBoundary, out double meanOrdinate
, int isMiantong = 0, bool showMat = false)
{
Mat crop = image[upperBound, lowerBound, leftBoundary-10, rightBoundary+10];
/*int pos = -1;
int min = int.MaxValue;
for(int i=0; i< crop.Height-5; i++)
{
int sum = (int)(crop.Row[i].Sum())+ (int)(crop.Row[i+1].Sum())+ (int)(crop.Row[i+2].Sum())
+ (int)(crop.Row[i+3].Sum())+ (int)(crop.Row[i+4].Sum());
if (sum < min)
{
pos = i;
min = sum;
}
}
if((int)(image.Row[pos+ upperBound].Sum()) < (int)(image.Row[pos+ upperBound + 40].Sum()) && pos< crop.Height/2)
{
int start = pos + 10;
pos = -1;
min = int.MaxValue;
for (int i = start; i < crop.Height; i++)
{
int sum = (int)(crop.Row[i].Sum());
if (sum < min)
{
pos = i;
min = sum;
}
}
}
meanOrdinate = pos + upperBound;
return meanOrdinate;*/
Mat filter = new Mat();//滤波增强对比
InputArray kernel = InputArray.Create(new int[3, 3] { { 0, -1, 0 }, { -1, 5, -1 }, { 0, -1, 0 } });
Cv2.Filter2D(crop, filter, -1, kernel);
Cv2.ConvertScaleAbs(filter, filter);
Mat thresh = 1 - filter.Threshold(0, 1, ThresholdTypes.Otsu); ;// 二值化
//待自测scc-3_2 //此处针对3(4)的类型图片做精准化调整
//int sizeSe = 3; if (isMiantong == 2) sizeSe = 1;// 3;// 1;
//Mat seOpen = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, sizeSe/*3*/));// 开运算
Mat seOpen = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));// 开运算
Mat open = new Mat();
Cv2.MorphologyEx(thresh, open, MorphTypes.Open, seOpen);
//if (isMiantong > 0 && showMat)
//{
// Mat mat1 = new Mat();
// Cv2.Normalize(open, mat1, 0, 255, NormTypes.MinMax);
// Cv2.ImWrite(@"C:\Users\54434\Desktop\open.JPG", mat1);
//}
Scalar sum = new Scalar(0);
Scalar max1 = new Scalar(0);
Scalar max = new Scalar(0);
double meanOrdinate1 = 0;
meanOrdinate = 0;//待自测scc-3_2 + upperBound;
for (int i = crop.Rows / 4; i < crop.Rows / 4 * 3; i++)
{
sum = open[i, i + 2, 0, crop.Cols - 1].Sum();
if ((int)max < (int)sum)
{
if (isMiantong > 0 && i + upperBound > 10 + meanOrdinate)
{
max1 = max;
meanOrdinate1 = meanOrdinate;
}
max = sum;
meanOrdinate = i + upperBound;
}
else if (isMiantong > 0 && i + upperBound > 10 + meanOrdinate && (int)max1 < (int)sum)
{
max1 = sum;
meanOrdinate1 = i + upperBound;
}
}
if (isMiantong > 0)
{
if (meanOrdinate < meanOrdinate1 && isMiantong == 1
|| meanOrdinate > meanOrdinate1 && meanOrdinate1 > 0 && isMiantong == 2
)
{
double meanOrdinate_i = meanOrdinate;
meanOrdinate = meanOrdinate1;
meanOrdinate1 = meanOrdinate_i;
}
}
//待自测scc-3_2
//if (meanOrdinate == upperBound)
// meanOrdinate = meanOrdinate1;
//尝试纠偏一下,可是还有差很亮的,可能还是需要二值 待确认@@@@@@@@@@@@@
if ((int)(image.Row[(int)meanOrdinate].Sum()) < (int)(image.Row[Math.Min(image.Rows - 1, (int)meanOrdinate + 40)].Sum())-100000 && (meanOrdinate- upperBound) < crop.Height / 2
&& ((int)crop.Row[(int)meanOrdinate - upperBound + 10].Sum() - (int)crop.Row[(int)meanOrdinate - upperBound - 10].Sum()) < crop.Width*25)
{
int start = (int)(meanOrdinate - upperBound + 10);
int pos = -1;
int min = int.MaxValue;
for (int i = start; i < crop.Height; i++)
{
int sum_a = (int)(crop.Row[i].Sum());
if (sum_a < min)
{
pos = i;
min = sum_a;
}
}
meanOrdinate = pos + upperBound;
}
#region[清理内存]
if (crop != null)
{
crop.Dispose();
}
if (open != null)
{
open.Dispose();
}
if (filter != null)
{
filter.Dispose();
}
if (thresh != null)
{
thresh.Dispose();
}
if (seOpen != null)
{
seOpen.Dispose();
}
#endregion
return meanOrdinate1;
}
///
/// 將計算的範圍從整個行數變成四分之一到四分之三之間,不知道通孔和盲孔改變之後會不會有影響,暫時沒引用
///
///
///
///
///
///
///
public void InsideLine2(Mat image, int upperBound, int lowerBound, int leftBoundary, int rightBoundary, out double meanOrdinate)
{
Mat crop = image[upperBound, lowerBound, leftBoundary, rightBoundary];
Mat filter = new Mat();//滤波增强对比
InputArray kernel = InputArray.Create(new int[3, 3] { { 0, -1, 0 }, { -1, 5, -1 }, { 0, -1, 0 } });
Cv2.Filter2D(crop, filter, -1, kernel);
Cv2.ConvertScaleAbs(filter, filter);
Mat thresh = 1 - filter.Threshold(0, 1, ThresholdTypes.Otsu); ;// 二值化
Mat seOpen = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3));// 开运算
Mat open = new Mat();
Cv2.MorphologyEx(thresh, open, MorphTypes.Open, seOpen);
//new Window("thresh", WindowMode.Normal, thresh * 255);
//new Window("open", WindowMode.Normal, open * 255);
//Cv2.WaitKey();
Scalar sum = new Scalar(0);
Scalar max = new Scalar(0);
meanOrdinate = 0;
for (int i = crop.Rows / 4; i < crop.Rows / 4 * 3; i++)
{
sum = open[i, i + 2, 0, crop.Cols - 1].Sum();
if ((int)max < (int)sum)
{
max = sum;
meanOrdinate = i + upperBound;
}
}
}
///
/// 图像画线,线颜色是红色
///
/// 画线图像
///
///
///
///
///
/// 计算盲孔的上孔径
///
/// 输入二值图片
/// 输入下孔径
/// 左边第三条线坐标
/// 右边第三条线坐标
/// 输出左边孔径坐标,先纵坐标后横坐标
/// 输出右边孔径坐标,先纵坐标后横坐标
public void ShangKongjing(/*Mat imageRed, */Mat image, int[] apertureLow, int leftOrdinate3, int rightOrdinate3, out int[] leftAperture, out int[] rightAperture)
{
leftAperture = new int[2] { 0, 0 };
rightAperture = new int[2] { 0, 0 };
int heightRange = 15;
int widthMiddleRange = 1;
int widthRange = 200;
Mat cropLeft = 1 - image[leftOrdinate3 - heightRange, leftOrdinate3 + heightRange, Math.Abs(apertureLow[0] - widthRange), apertureLow[0] + widthMiddleRange];
//Mat crop = imageRed[leftOrdinate3 - 15, leftOrdinate3 + 15, apertureLow[0] - 50, apertureLow[0] + 10];
Mat cropRight = 1 - image[rightOrdinate3 - heightRange, rightOrdinate3 + heightRange, apertureLow[1] - widthMiddleRange, apertureLow[1] + widthRange];
for (int j = cropLeft.Cols - 1; j > 0; j--)//从右上角,以135°方向遍历
{
for (int k = j; k < cropLeft.Cols && (k - j < cropLeft.Rows); k++)
{
if (cropLeft.Get(k - j, k) > 0)
{
leftAperture[0] = k - j + leftOrdinate3 - heightRange;
leftAperture[1] = k + apertureLow[0] - widthRange;
//LineShow(crop, new Point(k, k - j), new Point(k, k - j + 10));
//new Window("cropleft", WindowMode.Normal, crop);
//Cv2.WaitKey();
break;
}
}
if (leftAperture[0] != 0)
break;
}
if (leftAperture[0] == 0)
{
for (int j = 1; j < cropLeft.Rows; j++)
{
for (int k = 0; k < cropLeft.Rows - j - 1; k++)
{
if (cropLeft.Get(j + k, k) > 0)
{
leftAperture[0] = j + k + leftOrdinate3 - heightRange;
leftAperture[1] = k + apertureLow[0] - widthRange;
break;
}
}
if (leftAperture[0] != 0)
break;
}
}
for (int j = 0; j < cropRight.Cols; j++)//从左上角,45°方向遍历
{
for (int k = j; k >= 0 && j - k < cropRight.Rows; k--)
{
if (cropRight.Get(j - k, k) > 0)
{
rightAperture[0] = j - k + rightOrdinate3 - heightRange;
rightAperture[1] = k + apertureLow[1] - widthMiddleRange;
break;
}
}
if (rightAperture[0] != 0)
break;
}
if (rightAperture[0] == 0)
{
for (int j = 1; j < cropRight.Rows; j++)
{
for (int k = cropRight.Cols - 1; cropRight.Cols - 1 - k < cropRight.Rows - j - 1; k--)
{
if (cropRight.Get(j + cropRight.Cols - 1 - k, k) > 0)
{
rightAperture[0] = j + cropRight.Cols - 1 - k + rightOrdinate3 - heightRange;
rightAperture[1] = k + apertureLow[1] - widthMiddleRange;
break;
}
}
if (rightAperture[0] != 0)
break;
}
}
//new Window("cropleft", WindowMode.Normal, cropLeft * 255);
//new Window("cropRight", WindowMode.Normal, cropRight * 255);
//Cv2.WaitKey();
}
///
/// 计算盲孔的上孔径,修改了计算方法,通过孔径不为零坐标和的最小值来定位
///
/// 输入二值图片
/// 输入下孔径
/// 左边第三条线坐标
/// 右边第三条线坐标
/// 输出左边孔径坐标,先纵坐标后横坐标
/// 输出右边孔径坐标,先纵坐标后横坐标
public void ShangKongjing2(Mat image, int[] apertureLow, int leftOrdinate3, int rightOrdinate3, out int[] leftAperture, out int[] rightAperture)
{
leftAperture = new int[2] { 0, 0 };
rightAperture = new int[2] { 0, 0 };
int heightRange = 10;
int widthMiddleRange = 50;
int widthRange = 200;
Mat cropLeft = 1 - image[leftOrdinate3 - heightRange, leftOrdinate3 + heightRange, apertureLow[0] - widthRange, apertureLow[0] + widthMiddleRange];
//Mat crop = imageRed[leftOrdinate3 - 15, leftOrdinate3 + 15, apertureLow[0] - 50, apertureLow[0] + 10];
Mat cropRight = 1 - image[rightOrdinate3 - heightRange, rightOrdinate3 + heightRange, apertureLow[1] - widthMiddleRange, apertureLow[1] + widthRange];
Cv2.Flip(cropLeft, cropLeft, FlipMode.Y);
int minLeft = 1000, minRight = 1000;
int t1 = 0, t2 = 0;
for (int i = 0; i < cropLeft.Rows; i++)
{
for (int j = 0; j < cropLeft.Cols; j++)
{
if (cropLeft.Get(i, j) > 0)
{
t1 = i + j;
}
if (minLeft > t1 + 10 && t1 != 0)
{
minLeft = t1;
leftAperture[0] = i + leftOrdinate3 - heightRange;
leftAperture[1] = cropLeft.Cols - j + apertureLow[0] - widthRange;
}
}
}
for (int i = 0; i < cropRight.Rows; i++)
{
for (int j = 0; j < cropRight.Cols; j++)
{
if (cropRight.Get(i, j) > 0)
{
t2 = i + j;
}
if (minRight > t2 && t2 != 0)
{
minRight = t2;
rightAperture[0] = i + rightOrdinate3 - heightRange;
rightAperture[1] = j + apertureLow[1] - widthMiddleRange;
}
}
}
//new Window("cropcontour", WindowMode.Normal, image * 255);
new Window("cropleft", WindowMode.Normal, cropLeft * 255);
//new Window("cropright", WindowMode.Normal, cropRight * 255);
Cv2.WaitKey();
}
//蝕刻因子
///
/// 得到蝕刻因子圖像的提取區域
///
/// 輸入二值圖像
/// 輸出邊界位置,0:上界;1:下界;2:左界;3:右界
public void SKYZDataArea(Mat imageContour, out int[] dataArea, bool isCropFlag)
{
dataArea = new int[4] { 0, 0, 0, 0 };
Scalar sum = new Scalar();
for (int i = 100; i < imageContour.Rows; i++)
{
sum = imageContour[i, i + 1, 0, imageContour.Cols].Sum();
if ((int)sum > 0)
{
dataArea[0] = i;//上界
break;
}
}
for (int i = dataArea[0]; i < imageContour.Rows; i++)
{
sum = imageContour[i, i + 1, 0, imageContour.Cols].Sum();
if ((int)sum == 0)
{
dataArea[1] = i;//下界
break;
}
}
if (isCropFlag)
{
for (int j = 0; j < imageContour.Cols - 1; j++)
{
sum = imageContour[dataArea[0], dataArea[1], j, j + 1].Sum();
if ((int)sum > 0)
{
dataArea[2] = j;
break;
}
}
for (int j = imageContour.Cols - 1; j > 1; j--)
{
sum = imageContour[dataArea[0], dataArea[1], j - 1, j].Sum();
{
if ((int)sum > 0)
{
dataArea[3] = j;
break;
}
}
}
}
else
{
int t = 0;
for (int j = imageContour.Cols - 100; j > 0; j--)
{
sum = imageContour[dataArea[0], dataArea[1], j - 1, j].Sum();
if ((int)sum > 0)
{
t = j;//最右邊的開始
break;
}
}
for (int j = t - 1; j > 0; j--)
{
sum = imageContour[dataArea[0], dataArea[1], j - 1, j].Sum();
if ((int)sum == 0)
{
t = j;//最右邊的結束
break;
}
}
for (int j = t - 1; j > 0; j--)
{
sum = imageContour[dataArea[0], dataArea[1], j - 1, j].Sum();
if ((int)sum > 0)
{
t = j;//中間開始
dataArea[3] = j;
break;
}
}
for (int j = t - 1; j > 0; j--)
{
sum = imageContour[dataArea[0], dataArea[1], j - 1, j].Sum();
if ((int)sum == 0)
{
t = j;//中間結束
dataArea[2] = j;
break;
}
}
}
}
///
/// 提取上幅的值及坐標
///
/// 輸入二值圖像
/// 上幅的大小
/// 上幅的坐標,0:縱坐標;1:左橫坐標;2:右橫坐標
public void UpperLine(Mat imageContour, out int upperLineValue, out int[] upperLineOrdinate)
{
upperLineValue = 0;
upperLineOrdinate = new int[3] { 0, 0, 0 };
int cols = imageContour.Cols;
int rows = imageContour.Rows;
Scalar sum = new Scalar();
for (int i = 0; i < rows - 150; i++)
{
sum = imageContour[i, i + 1, 0, cols].Sum();
if ((int)sum > cols * 5 / 6)//儅每行點數大於寬度的五分之四時,判爲上幅
{
upperLineOrdinate[0] = i;
break;
}
}
if (upperLineOrdinate[0] == 0)//如果没有检测到
{
for (int i = 0; i < rows / 4; i++)
{
sum = imageContour[i, i + 1, 0, cols].Sum();
if ((int)sum > cols * 4 / 5)//儅每行點數大於寬度的五分之三時,判爲上幅
{
upperLineOrdinate[0] = i;
break;
}
}
}
int max = 0;
int t = upperLineOrdinate[0];
//繼續向下10(5)個像素尋找最大行,并認爲是上幅
for (int i = t; i < t + 10; i++)
{
sum = imageContour[i, i + 1, 0, cols].Sum();
if ((int)sum > max)
{
max = (int)sum;
upperLineOrdinate[0] = i;
}
}
//左邊點坐標
for (int j = 0; j < cols; j++)
{
if (imageContour.Get(upperLineOrdinate[0], j) > 0)
{
upperLineOrdinate[1] = j;
break;
}
}
//右邊點坐標
for (int j = cols - 1; j > 0; j--)
{
if (imageContour.Get(upperLineOrdinate[0], j) > 0)
{
upperLineOrdinate[2] = j;
break;
}
}
upperLineValue = upperLineOrdinate[2] - upperLineOrdinate[1];
}
public void UpperLine2(Mat imageContour, out int upperLineValue, out int[] upperLineOrdinate)
{
upperLineValue = 0;
upperLineOrdinate = new int[3] { 0, 0, 0 };
int cols = imageContour.Cols;
int rows = imageContour.Rows;
Scalar sum = new Scalar();
for (int i = 0; i < rows - 150; i++)
{
sum = imageContour[i, i + 1, 0, cols].Sum();
if ((int)sum > cols * 5 / 6)//儅每行點數大於寬度的五分之四時,判爲上幅
{
upperLineOrdinate[0] = i;
break;
}
}
if (upperLineOrdinate[0] == 0)//如果没有检测到
{
for (int i = 0; i < rows / 4; i++)
{
sum = imageContour[i, i + 1, 0, cols].Sum();
if ((int)sum > cols * 4 / 5)//儅每行點數大於寬度的五分之三時,判爲上幅
{
upperLineOrdinate[0] = i;
break;
}
}
}
if (upperLineOrdinate[0] == 0)//如果没有检测到
{
for (int i = 0; i < rows / 3; i++)
{
sum = imageContour[i, i + 1, 0, cols].Sum();
if ((int)sum > cols * 3 / 5)//儅每行點數大於寬度的五分之三時,判爲上幅
{
upperLineOrdinate[0] = i;
break;
}
}
}
if (upperLineOrdinate[0] == 0)//如果没有检测到
{
for (int i = 0; i < rows / 3; i++)
{
sum = imageContour[i, i + 1, 0, cols].Sum();
if ((int)sum > cols * 2 / 5)//儅每行點數大於寬度的五分之三時,判爲上幅
{
upperLineOrdinate[0] = i;
break;
}
}
}
int max = 0;
int t = upperLineOrdinate[0];
//繼續向下10(5)個像素尋找最大行,并認爲是上幅
for (int i = t; i < t + 10; i++)
{
sum = imageContour[i, i + 1, 0, cols].Sum();
if ((int)sum > max)
{
max = (int)sum;
upperLineOrdinate[0] = i;
}
}
//左邊點坐標
for (int j = 0; j < cols; j++)
{
if (imageContour.Get(upperLineOrdinate[0], j) > 0)
{
upperLineOrdinate[1] = j;
break;
}
}
//右邊點坐標
for (int j = cols - 1; j > 0; j--)
{
if (imageContour.Get(upperLineOrdinate[0], j) > 0)
{
upperLineOrdinate[2] = j;
break;
}
}
upperLineValue = upperLineOrdinate[2] - upperLineOrdinate[1];
}
///
/// 計算蝕刻因子上下的總後的值和坐標(是單層的銅厚)
///
/// 二值圖像
/// 輸出銅厚的值
/// 輸出銅厚的坐標,0:橫坐標;1:上縱坐標;2:下縱坐標
public void Zonghou(Mat imageContour, out int zonghouValue, out int[] zonghouOrdinate)
{
zonghouValue = 0;
zonghouOrdinate = new int[3];
int rows = imageContour.Rows;
int cols = imageContour.Cols;
int middle = cols / 2;
zonghouOrdinate[0] = middle;
for (int i = 0; i < rows; i++)
{
if (imageContour.Get(i, middle) > 0)
{
zonghouOrdinate[1] = i;
break;
}
}
for (int i = rows - 1; i > 0; i--)
{
if (imageContour.Get(i, middle) > 0)
{
zonghouOrdinate[2] = i;
break;
}
}
zonghouValue = zonghouOrdinate[2] - zonghouOrdinate[1];
}
///
/// 計算銅厚以及銅厚坐標
///
/// 綠色通道圖像
/// 二值圖像
/// 銅厚大小
/// 銅厚坐標,0:橫坐標;1:上縱坐標;2:下縱坐標
public void Tonghou(Mat imageGreen, Mat imageContour, out int tonghouValue, out int[] tonghouOrdinate)
{
tonghouValue = 0;
tonghouOrdinate = new int[3];
int rows = imageGreen.Rows;
int cols = imageGreen.Cols;
int middle = cols / 2;
tonghouOrdinate[0] = (middle + cols) / 2;
double insideLine;
InsideLine2(imageGreen, 30, rows - 50, 20, cols - 20, out insideLine);
tonghouOrdinate[1] = (int)insideLine;
for (int i = rows - 1; i > 0; i--)
{
if (imageContour.Get(i, tonghouOrdinate[0]) > 0)
{
tonghouOrdinate[2] = i;
break;
}
}
tonghouValue = tonghouOrdinate[2] - tonghouOrdinate[1];
}
#region 防焊
#region 没开口
///
/// 防焊 有开口 铜厚
///
///
///
///
///
public void FanghanTonghouForMeiKaiKou(Mat gray, out int[] tonghouY, out int[] y, out int[] b)
{
y = new int[2];
b = new int[4];
tonghouY = new int[2];
Mat contour = new Mat();
double T = 0;
double t = Cv2.Threshold(gray, contour, 0, 255, ThresholdTypes.Otsu);
Mat seClose = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(15, 15));
Mat close = new Mat();
Cv2.MorphologyEx(contour, close, MorphTypes.Close, seClose);
Mat result = close.Clone();
result = result / 255;
//ImageShow(result * 255);
//计算边界
Scalar sum = new Scalar(0);
for (int i = 0; i < result.Rows; i++)
{
sum = result[i, i + 1, 0, result.Cols].Sum();
if ((int)sum > 200)
{
y[0] = i - 20;
break;
}
}
for (int i = y[0] + 50; i < result.Rows; i++)
{
sum = result[i, i + 1, 0, result.Cols].Sum();
if ((int)sum == 0)
{
y[1] = i;
break;
}
}
for (int j = 0; j < result.Cols; j++)
{
sum = result[y[0], y[1], j, j + 1].Sum();
if ((int)sum > 20)
{
b[0] = j;
break;
}
}
for (int j = b[0] + 200; j < result.Cols; j++)
{
sum = result[y[0], y[1], j, j + 1].Sum();
if ((int)sum == 0)
{
b[1] = j;
break;
}
}
for (int j = b[1] + 10; j < result.Cols; j++)
{
sum = result[y[0], y[1], j, j + 1].Sum();
if ((int)sum > 20)
{
b[2] = j;
break;
}
}
if (b[2] - b[1] < 300)
{
for (int j = b[2] + 50; j < result.Cols; j++)
{
sum = result[y[0], y[1], j, j + 1].Sum();
if ((int)sum == 0)
{
b[1] = j;
break;
}
}
for (int j = b[1] + 10; j < result.Cols; j++)
{
sum = result[y[0], y[1], j, j + 1].Sum();
if ((int)sum > 20)
{
b[2] = j;
break;
}
}
}
for (int j = b[2] + 50; j < result.Cols; j++)
{
sum = result[y[0], y[1], j, j + 1].Sum();
if ((int)sum == 0)
{
b[3] = j;
break;
}
}
if (b[3] == 0)
b[3] = contour.Cols - 1;
//计算铜厚
int tonghouX = b[1] - 150;
Mat thresh = gray.Threshold(0, 1, ThresholdTypes.Otsu);
for (int i = y[0]; i < y[1]; i++)
{
sum = thresh[i, i + 1, tonghouX - 30, tonghouX + 30].Sum();
if ((int)sum > 30)
{
tonghouY[0] = i;
break;
}
}
contour = contour / 255;
for (int i = tonghouY[0] + 30; i < contour.Rows; i++)
{
sum = contour[i, i + 1, tonghouX - 30, tonghouX + 30].Sum();
if ((int)sum == 0)
{
tonghouY[1] = i;
break;
}
}
}
///
/// 防焊 有开口 厚度
///
///
///
///
///
///
///
public void FanghanhouduForMeiKaiKou_2(Mat gray, int[] y, int fanghanhouduX, int[] tonghouY, out int fanghanhouduY1, out int minGray, bool isLeft)
{
int fanghanhouduY_0 = tonghouY[0];
int fanghanX1 = Math.Max(0, fanghanhouduX - 150);
int fanghanX2 = Math.Min(gray.Cols - 1, fanghanhouduX + 150);
int fanghanTop = fanghanhouduY_0 - 150/*100*/;
int marginTop = 150;
if (fanghanTop < 0)
{
fanghanTop = 0;
marginTop = fanghanhouduY_0 - 1;
}
Mat grayRect = gray[fanghanTop, fanghanhouduY_0 - 50, fanghanX1, fanghanX2];
FanghanhouduForMeiKaiKou(grayRect, y, marginTop, tonghouY, out fanghanhouduY1, out minGray);
int fanghanhouduY1__2 = fanghanhouduY1;
int minGray__2 = minGray;
fanghanX1 += 140;// 145;
fanghanX2 -= 140;// 145;
grayRect = gray[fanghanTop, fanghanhouduY_0 - 20/*50*/, fanghanX1, fanghanX2];
int fanghanhouduY1__2_bottom;
FanghanhouduForYouKaiKou_ACC(grayRect, y, marginTop, fanghanhouduY1 - (isLeft ? 8/*5*/ : 1), out fanghanhouduY1__2, out fanghanhouduY1__2_bottom, out minGray__2);
if (Math.Abs(fanghanhouduY1 - fanghanhouduY1__2) < 16/*11*//*<-10*//*20*//*10*/
|| (!isLeft && Math.Abs(fanghanhouduY1 - fanghanhouduY1__2) < 25/*20*/))
fanghanhouduY1 = fanghanhouduY1__2/*fanghanhouduY1__2_bottom*//*fanghanhouduY1__2*/ + fanghanTop;// +5;
//else
//{
// fanghanX1 -= 69;
// fanghanX2 += 69;
// grayRect = gray[fanghanTop, fanghanhouduY_0 - 50, fanghanX1, fanghanX2];
// FanghanhouduForMeiKaiKou(grayRect, y, marginTop, tonghouY, out fanghanhouduY1__2, out minGray__2);
//}
//if (Math.Abs(fanghanhouduY1 - fanghanhouduY1__2) < 10)
// fanghanhouduY1 = fanghanhouduY1__2 + fanghanTop;
else
fanghanhouduY1 = fanghanhouduY1 + fanghanTop;
}
///
/// 防焊 有开口 厚度 精确计算 统一到有开口的方法精确定位 避免个别因素产生大的偏差
///
///
///
///
///
///
///
private void FanghanhouduForMeiKaiKou_ACC(Mat gray, int[] y, int fanghanhouduX, int fanghanhouduY1__0, out int fanghanhouduY1, out int fanghanhouduY1Bottom, out int minGray, int a = 0)
{
minGray = 300 * 255;
int minRowIndex = 0; int colEnd = gray.Cols - 1; int curGray; List curGrayList = new List();
fanghanhouduY1Bottom = 0;
for (int i = Math.Max(0, fanghanhouduY1__0 - 0/*1*//*5*//*10*/); i < Math.Min(fanghanhouduY1__0 + 30/*25*/, gray.Rows) - 5; i++)
{
curGray = this.FanghanhouduForAreaMin(gray, i);// (int)thresh[i - 1, i, 0, colEnd].Sum().Val0;
curGrayList.Add(curGray);
if (curGray < minGray)
{
minRowIndex = i;
fanghanhouduY1Bottom = i;
minGray = curGray;
}
}
for (int i = minRowIndex - Math.Max(0, fanghanhouduY1__0 - 0/*1*//*5*//*10*/) + 2; i < curGrayList.Count; i+=2)
{
if (Math.Abs(curGrayList[i] - minGray) < 10/*100*/)
{
minRowIndex += 1;
fanghanhouduY1Bottom += 2;
}
}
//Console.WriteLine("fanghanhouduY1_1:" + minRowIndex);
////Cv2.ImWrite(@"C:\Users\54434\Desktop\thres_3.png", gray);
fanghanhouduY1 = minRowIndex;// 84;// 72;// minRowIndex;
}
///
/// 防焊 有开口 厚度
///
///
///
///
///
///
///
private void FanghanhouduForMeiKaiKou(Mat gray, int[] y, int fanghanhouduX, int[] tonghouY, out int fanghanhouduY1, out int minGray, int a = 0)
{
///*int fanghanhouduX = 150; */
//fanghanhouduY1 = -1;
//Mat thresh = gray.Threshold(BinaryTools.CalcSuitableValue(gray) - 10 + (a * 5), 255, ThresholdTypes.Binary);
////Cv2.ImWrite(@"C:\Users\54434\Desktop\thres_3.png", thresh);
//for (int i = 0; i < Math.Min(100, thresh.Rows); i++)
//{
// if (thresh.At(i, fanghanhouduX) == 0 && Cv2.FloodFill(thresh, new Point(fanghanhouduX, i), new Scalar(255)) > 300)
// {
// //fanghanhouduY1 = i;
// int sumTop = Cv2.FloodFill(thresh, new Point(fanghanhouduX, i), new Scalar(255));
// int searchTimes = 15;
// while (searchTimes-- > 0 && i+2 < thresh.Rows && sumTop == Cv2.FloodFill(thresh, new Point(fanghanhouduX, ++i), new Scalar(255)))
// {
// //fanghanhouduY1 = i;
// }
// fanghanhouduY1 = i;
// break;
// }
//}
minGray = 300 * 255;
//if (fanghanhouduY1 == -1)
// FanghanhouduForMeiKaiKou(gray, y, fanghanhouduX, tonghouY, out fanghanhouduY1, out minGray, ++a);
//else
{//计算数值的地方
//Console.WriteLine("fanghanhouduY1_0:" + fanghanhouduY1);
/*int minGray = 300*255; */
int minRowIndex = 0; int colEnd = gray.Cols - 1; int curGray;
for (int i = 6/*1*/; i < Math.Min(100, gray.Rows) - 5; i++)
{
curGray = this.FanghanhouduForAreaMin(gray, i);// (int)thresh[i - 1, i, 0, colEnd].Sum().Val0;
if (curGray < minGray)
{
minRowIndex = i;
minGray = curGray;
}
}
//Console.WriteLine("fanghanhouduY1_1:" + minRowIndex);
////Cv2.ImWrite(@"C:\Users\54434\Desktop\thres_3.png", gray);
fanghanhouduY1 = minRowIndex;
}
}
public void FanghanhouduForMeiKaiKou_Undercut0(Mat thres_2, int scanX_start, int scanX_end, int fanghanhouduY_1/*fanghanhouduY_center*/, int fanghanhouduY_2/*fanghanhouduY_radius*/, out int fanghanhouduX_0, bool showMat = false)
{
//int fanghanhouduY_1 = fanghanhouduY_center - fanghanhouduY_radius;
//int fanghanhouduY_2 = fanghanhouduY_center + fanghanhouduY_radius;
int vmax_2 = 0;
int vres_y = 1000;// 3000;
List vmax_x = new List();
for (int i = scanX_start; i < scanX_end; i++)
{
if (thres_2[fanghanhouduY_1, fanghanhouduY_2, i - 1, i].Sum().Val0 > vres_y)
{
vmax_2 = (int)thres_2[fanghanhouduY_1, fanghanhouduY_2, i - 1, i].Sum().Val0;
vmax_x.Add(i); ;
}
}
List vmax_x_temp = new List();
vmax_x_temp.AddRange(vmax_x);
while (vmax_x.Count > 10 && vmax_x_temp.Count > 1)
{
vres_y += 500;// 1000;
vmax_x_temp.Clear();
for (int i = scanX_start; i < scanX_end; i++)
{
if (thres_2[fanghanhouduY_1, fanghanhouduY_2, i - 1, i].Sum().Val0 > vres_y)
{
vmax_2 = (int)thres_2[fanghanhouduY_1, fanghanhouduY_2, i - 1, i].Sum().Val0;
vmax_x_temp.Add(i); ;
}
}
if (vmax_x_temp.Count > 1)
{
vmax_x.Clear();
vmax_x.AddRange(vmax_x_temp);
}
}
if (vmax_x.Count == 0)
{
vmax_x.Add(0);
for (int i = scanX_start; i < scanX_end; i++)
{
if (thres_2[fanghanhouduY_1, fanghanhouduY_2, i - 1, i].Sum().Val0 > vmax_2)
{
vmax_2 = (int)thres_2[fanghanhouduY_1, fanghanhouduY_2, i - 1, i].Sum().Val0;
vmax_x[0] = i;
}
}
}
else if (vmax_x.Count > 3)
{
bool isround = false;//去掉球上的点
int lastmax_x = vmax_x[vmax_x.Count - 1];
int endIndex = vmax_x.Count - 4;
for (int i = vmax_x.Count - 2; i > 0; i--)
{
if (vmax_x[i] - 20 > lastmax_x)
{
endIndex = i;
isround = true;
break;
}
lastmax_x = vmax_x[i];
}
if (isround)
{
int max_y_res = 100;
for (int i = vmax_x.Count - 1; i > endIndex; i--)
{
if (vmax_x[Math.Max(0, i - 2)] > max_y_res)
{
break;
}
vmax_x.RemoveAt(i);
}
}
}
fanghanhouduX_0 = (vmax_x.Count > 1 ? (vmax_x[vmax_x.Count - 2] + vmax_x[vmax_x.Count - 1]) / 2 : vmax_x[0]);
}
public void FanghanhouduForMeiKaiKou_Offset0(Mat thres_2_0, int scanX_start, int scanX_end, int fanghanhouduY_1/*fanghanhouduY_center*/, int fanghanhouduY_2/*fanghanhouduY_radius*/, out int fanghanhouduX_0, bool showMat = false)
{
//int fanghanhouduY_1 = fanghanhouduY_center - fanghanhouduY_radius;
//int fanghanhouduY_2 = fanghanhouduY_center + fanghanhouduY_radius;
List vmax_x_scanStart = new List();
for (int i = scanX_start; i < scanX_end; i++)
vmax_x_scanStart.Add((int)thres_2_0[fanghanhouduY_1, fanghanhouduY_2, i - 1, i].Sum().Val0);
int vmax_2 = 0;
int vres_y = 1000;// 3000;
List vmax_x = new List();
for (int i = scanX_start; i < scanX_end; i++)
{
if (vmax_x_scanStart[i - scanX_start] > vres_y)
{
vmax_2 = vmax_x_scanStart[i - scanX_start];
vmax_x.Add(i); ;
}
}
List vmax_x_temp = new List();
vmax_x_temp.AddRange(vmax_x);
int temp_x_left = vmax_x.Count > 0 ? vmax_x[0] : scanX_start;
//bool fanghanhouduX_0_Found = false; fanghanhouduX_0 = 300;
while (vmax_x.Count > 10 && vmax_x_temp.Count > 1/* && !fanghanhouduX_0_Found*/)
{
vres_y += 500;// 500;// 1000;
vmax_x_temp.Clear();
for (int i = scanX_start; i < scanX_end; i++)
{
if (vmax_x_scanStart[i - scanX_start] > vres_y)
{
vmax_2 = vmax_x_scanStart[i - scanX_start];
vmax_x_temp.Add(i); ;
}
}
if (vmax_x_temp.Count > 19)
{
vmax_x.Clear();
vmax_x.AddRange(vmax_x_temp);
Console.WriteLine("temp_x_left:" + vmax_x[0] + ";vmax_x.Count:" + vmax_x.Count);
////根据数值是否断开距离超过20判定offset左端点,其中60、370、20为超参参数
//if (vmax_x_temp.Count < 60)
// for (int i = 1; i < vmax_x.Count; i++)
//{
// if (vmax_x[i-1] < 370) continue;
// if (vmax_x[i] > vmax_x[i - 1] + 20)
// {
// fanghanhouduX_0 = vmax_x[i-1];// 384;// prev_x_v / prev_x_c;
// fanghanhouduX_0_Found = true;
// break;
// }
//}
}
}
//if (fanghanhouduX_0_Found)
//{
// return;
//}
if (vmax_x.Count == 0)
{
vmax_x.Add(0);
for (int i = scanX_start; i < scanX_end; i++)
{
if (vmax_x_scanStart[i - scanX_start] > vmax_2)
{
vmax_2 = vmax_x_scanStart[i - scanX_start];
vmax_x[0] = i;
}
}
}
else if (vmax_x.Count > 3)
{
bool isround = false;//去掉球上的点
int lastmax_x = vmax_x[vmax_x.Count - 1];
int endIndex = vmax_x.Count - 4;
for (int i = vmax_x.Count - 2; i > 0; i--)
{
if (vmax_x[i] - 20 > lastmax_x)
{
endIndex = i;
isround = true;
break;
}
lastmax_x = vmax_x[i];
}
if (isround)
{
int max_y_res = 100;
for (int i = vmax_x.Count - 1; i > endIndex; i--)
{
if (vmax_x[Math.Max(0, i - 2)] > max_y_res)
{
break;
}
vmax_x.RemoveAt(i);
}
}
}
if (vmax_x.Count > 2)
{
int vmax_x_v = vmax_x[0];
int vmax_x_c = 1;
int prev_x_v = vmax_x_v;
int prev_x_c = vmax_x_c;
for (int i = 1; i < vmax_x.Count; i++)
{
if (vmax_x[i] < vmax_x[i - 1] + 2)
{
vmax_x_v += vmax_x[i];
vmax_x_c += 1;
}
else
{
if (prev_x_c <= vmax_x_c)
{
prev_x_v = vmax_x_v;
prev_x_c = vmax_x_c;
}
i++;
vmax_x_v = vmax_x[i];
vmax_x_c = 1;
}
}
if (prev_x_c <= vmax_x_c+1)
{
prev_x_v = vmax_x_v;
prev_x_c = vmax_x_c;
}
fanghanhouduX_0 = prev_x_v / prev_x_c;
if (fanghanhouduX_0 > thres_2_0.Cols-30)
{
fanghanhouduX_0 = 382 - 100;
Console.WriteLine("temp_x_left: OverLoad 1");
}
else if (vmax_x.Count > 20)
{
Console.WriteLine("temp_x_left: OverLoad 2");
}
}
else
fanghanhouduX_0 = (vmax_x.Count > 1 ? (vmax_x[vmax_x.Count - 2] + vmax_x[vmax_x.Count - 1]) / 2 : vmax_x[0]);
}
///
/// 防焊 没有开口 厚度
///
///
///
///
///
///
///
public void FanghanhouduForMeiKaiKou_2(Mat thres_2, int fanghanhouduX_center, int fanghanhouduX_radius, out int fanghanhouduY_0, bool showMat = false)
{
int fanghanhouduX_1 = fanghanhouduX_center - fanghanhouduX_radius;
int fanghanhouduX_2 = fanghanhouduX_center + fanghanhouduX_radius;
int vmax_2 = 0;
int vres_y = 3000;
List vmax_y = new List();
//int vmax_y = crop2.Rows - 2;
for (int i = thres_2.Rows - 2; i > 0; i--)
{
if (thres_2[i - 1, i, fanghanhouduX_1, fanghanhouduX_2].Sum().Val0 >
vres_y)
//|| Cv2.FloodFill(max, new Point(leftFanghanhoudu[0], i), new Scalar(1/*255*/)) > 3500)
{
vmax_2 = (int)thres_2[i - 1, i, fanghanhouduX_1, fanghanhouduX_2].Sum().Val0;
vmax_y.Add(i); ;
}
}
List vmax_y_temp = new List();
vmax_y_temp.AddRange(vmax_y);
while (vmax_y.Count > 10 && vmax_y_temp.Count > 1)
{
vres_y += 1000;
//int vmax_y = crop2.Rows - 2;
vmax_y_temp.Clear();
for (int i = thres_2.Rows - 2; i > 0; i--)
{
if (thres_2[i - 1, i, fanghanhouduX_1, fanghanhouduX_2].Sum().Val0 >
vres_y)
//|| Cv2.FloodFill(max, new Point(leftFanghanhoudu[0], i), new Scalar(1/*255*/)) > 3500)
{
vmax_2 = (int)thres_2[i - 1, i, fanghanhouduX_1, fanghanhouduX_2].Sum().Val0;
vmax_y_temp.Add(i); ;
}
}
if (vmax_y_temp.Count > 1)
{
vmax_y.Clear();
vmax_y.AddRange(vmax_y_temp);
}
}
if (vmax_y.Count == 0)
{
vmax_y.Add(0);
for (int i = thres_2.Rows - 2; i > 0; i--)
{
if (thres_2[i - 1, i, fanghanhouduX_1, fanghanhouduX_2].Sum().Val0 >
vmax_2)
//|| Cv2.FloodFill(max, new Point(leftFanghanhoudu[0], i), new Scalar(1/*255*/)) > 3500)
{
vmax_2 = (int)thres_2[i - 1, i, fanghanhouduX_1, fanghanhouduX_2].Sum().Val0;
vmax_y[0] = i;
}
}
}
else if (vmax_y.Count > 3)
{
bool isround = false;//去掉球上的点
int lastmax_y = vmax_y[vmax_y.Count - 1];
int endIndex = vmax_y.Count - 4;
for (int i = vmax_y.Count - 2; i > 0; i--)
{
if (vmax_y[i] - 20 > lastmax_y)
{
endIndex = i;
isround = true;
break;
}
lastmax_y = vmax_y[i];
}
if (isround)
{
int max_y_res = 100;
for (int i = vmax_y.Count - 1; i > endIndex; i--)
{
if (vmax_y[Math.Max(0, i - 2)] > max_y_res)
{
break;
}
vmax_y.RemoveAt(i);
}
}
}
fanghanhouduY_0 = (vmax_y.Count > 1 ? (vmax_y[vmax_y.Count - 2] + vmax_y[vmax_y.Count - 1]) / 2 : vmax_y[0]);
}
/////
///// 防焊 没有开口 銅厚
/////
///// 二值圖像
///// 輸出銅厚的上下縱坐標
///// 截取第一層銅的區域
///// b[0]:銅起始點;b[1]:銅結束點;b[2]:銅再次開始點
//public void FanghanTonghouForMeiKaiKou(Mat gray, out int[] tonghouY, out int[] y, out int[] b)
//{
// y = new int[2];
// b = new int[4];
// int[] bAdd = new int[5];
// tonghouY = new int[2];
// Mat contour = gray.Threshold(0, 255, ThresholdTypes.Otsu);
// //去掉小颗粒
// contour = BinaryTools.DebrisRemoval_New(contour.CvtColor(ColorConversionCodes.GRAY2BGRA), 1000).CvtColor(ColorConversionCodes.BGRA2GRAY);
// //分析的区域切图的不对[2]to do //
// //Cv2.ImWrite(@"C:\Users\54434\Desktop\contour.JPG", contour);
// Mat result = contour.Clone() / 255;
// //计算边界
// Scalar sum = new Scalar(0);
// for (int i = 0; i < result.Rows; i++)
// {
// sum = result[i, i + 1, 0, result.Cols].Sum();
// if ((int)sum > 200)
// {
// y[0] = i - 20;
// break;
// }
// }
// ////区分突然骤减的情况也说明已经到了铜厚的底部
// //List listSum = new List();
// //listSum.Add((int)sum);
// //int halfOfSumTime = 0;
// for (int i = y[0] + 50; i < result.Rows; i++)
// {
// sum = result[i, i + 1, 0, result.Cols].Sum();
// if ((int)sum == 0)
// {
// y[1] = i;
// break;
// }
// //if ((int)sum * 2 < listSum.Average())
// //{
// // if (++halfOfSumTime > 3)
// // {
// // y[1] = i;
// // //break;
// // }
// //}
// //else
// //{
// // halfOfSumTime = 0;
// // listSum.Add((int)sum);
// //}
// }
// if (y[0] <= 0 || y[1] <= 0)
// {
// contour = gray.Threshold(BinaryTools.CalcSuitableValueForMax(gray), 255, ThresholdTypes.Binary);
// result = contour.Clone() / 255;
// for (int i = 0; i < result.Rows; i++)
// {
// sum = result[i, i + 1, 0, result.Cols].Sum();
// if ((int)sum > 200)
// {
// y[0] = i - 20;
// break;
// }
// }
// for (int i = y[0] + 50; i < result.Rows; i++)
// {
// sum = result[i, i + 1, 0, result.Cols].Sum();
// if ((int)sum == 0)
// {
// y[1] = i;
// break;
// }
// }
// for (int j = 0; j < result.Cols; j++)
// {
// sum = result[y[0], y[1], j, j + 1].Sum();
// if ((int)sum > 0)
// {
// b[0] = j;
// bAdd[0] = j;
// break;
// }
// }
// for (int j = b[0] + 200; j < result.Cols; j++)
// {
// sum = result[y[0], y[1], j, j + 1].Sum();
// if ((int)sum == 0)
// {
// b[1] = j;
// bAdd[1] = j;
// break;
// }
// }
// }
// for (int j = 0; j < result.Cols; j++)
// {
// sum = result[y[0], y[1], j, j + 1].Sum();
// if ((int)sum > 0)
// {
// b[0] = j;
// bAdd[0] = j;
// break;
// }
// }
// for (int j = b[0] + 50; j < result.Cols; j++)
// {
// sum = result[y[0], y[1], j, j + 1].Sum();
// if ((int)sum == 0)
// {
// b[1] = j;
// bAdd[1] = j;
// break;
// }
// }
// //暂时这么一写
// if (b[1] <= 0)
// {
// contour = gray.Threshold(BinaryTools.CalcSuitableValueForMax(gray), 255, ThresholdTypes.Binary);
// //去掉小颗粒
// contour = BinaryTools.DebrisRemoval_New(contour.CvtColor(ColorConversionCodes.GRAY2BGRA), 1000).CvtColor(ColorConversionCodes.BGRA2GRAY);
// result = contour.Clone() / 255;
// for (int i = 0; i < result.Rows; i++)
// {
// sum = result[i, i + 1, 0, result.Cols].Sum();
// if ((int)sum > 200)
// {
// y[0] = i - 20;
// break;
// }
// }
// for (int i = y[0] + 50; i < result.Rows; i++)
// {
// sum = result[i, i + 1, 0, result.Cols].Sum();
// if ((int)sum == 0)
// {
// y[1] = i;
// break;
// }
// }
// if (y[0] < 0 || y[1] < 0) return;
// for (int j = 0; j < result.Cols; j++)
// {
// sum = result[y[0], y[1], j, j + 1].Sum();
// if ((int)sum > 0)
// {
// b[0] = j;
// bAdd[0] = j;
// break;
// }
// }
// for (int j = b[0] + 50; j < result.Cols; j++)
// {
// sum = result[y[0], y[1], j, j + 1].Sum();
// if ((int)sum == 0)
// {
// b[1] = j;
// bAdd[1] = j;
// break;
// }
// }
// }
// for (int j = b[1] + 10; j < result.Cols; j++)
// {
// sum = result[y[0], y[1], j, j + 1].Sum();
// if ((int)sum > 0)
// {
// b[2] = j;
// bAdd[2] = j;
// break;
// }
// }
// if (b[2] - b[1] < 300)
// {
// for (int j = b[2] + 50; j < result.Cols; j++)
// {
// sum = result[y[0], y[1], j, j + 1].Sum();
// if ((int)sum == 0)
// {
// b[1] = j;
// bAdd[1] = j;
// break;
// }
// }
// for (int j = b[1] + 10; j < result.Cols; j++)
// {
// sum = result[y[0], y[1], j, j + 1].Sum();
// if ((int)sum > 0)
// {
// b[2] = j;
// bAdd[2] = j;
// break;
// }
// }
// }
// for (int j = bAdd[2] + 50; j < result.Cols; j++)
// {
// sum = result[y[0], y[1], j, j + 1].Sum();
// if ((int)sum == 0)
// {
// bAdd[3] = j - 1;
// break;
// }
// }
// if (bAdd[3] == 0)
// bAdd[3] = contour.Cols - 1;
// for (int j = bAdd[3] + 10; j < result.Cols; j++)
// {
// sum = result[y[0], y[1], j, j + 1].Sum();
// if ((int)sum > 0)
// {
// bAdd[4] = j;
// break;
// }
// }
// for (int j = result.Cols - 1; j > b[2]; j--)
// {
// sum = result[y[0], y[1], j - 1, j].Sum();
// if ((int)sum > 0)
// {
// b[3] = j;
// break;
// }
// }
// if (b[3] == 0)
// b[3] = contour.Cols - 1;
// //bAdd[5] = b[3];
// if (b[3] != bAdd[3] && b[3] - bAdd[2] > bAdd[3] - b[0] && (b[0] < 20 && b[1] < 60 && (b[1] < 280 && b[0] < 100 || b[3] == contour.Cols-1))/*防止过拟合*/)//测量区域在右边
// {
// b[2] = bAdd[4];
// b[1] = bAdd[3];
// b[0] = bAdd[2];
// }
// //计算铜厚
// int tonghouX = b[1] - 50;
// if (tonghouX <= 0) return;
// Mat thresh = gray.Threshold(0, 1, ThresholdTypes.Otsu);
// for (int i = y[0]; i < y[1]; i++)
// {
// sum = thresh[i, i + 1, (tonghouX - 50) < 0 ? 0 : (tonghouX - 50), tonghouX + 50].Sum();
// if ((int)sum > 20)
// {
// tonghouY[0] = i;
// break;
// }
// }
// contour = contour / 255;
// for (int i = tonghouY[0] + 30; i < contour.Rows; i++)
// {
// sum = contour[i, i + 1, (tonghouX - 50) < 0 ? 0 : (tonghouX - 50), tonghouX + 50].Sum();
// if ((int)sum == 0)
// {
// tonghouY[1] = i;
// break;
// }
// }
//}
/////
///// 防焊 没有开口 厚度
/////
/////
/////
/////
/////
/////
/////
//public Mat FanghanhouduForMeiKaiKou(Mat gray, int[] y, int[] b, int[] tonghouY, out int[] fanghanhouduY, int a = 0, bool showMat = false)
//{
// fanghanhouduY = new int[2];
// int fanghanhouduX = b[1] - 100;
// Mat maskRes = new Mat(gray.Rows + 2, gray.Cols + 2, MatType.CV_8UC1);
// Mat thresh = gray.Threshold(BinaryTools.CalcSuitableValue(gray) - 10 + (a * 5), 255, ThresholdTypes.Binary);
// fanghanhouduY[0] = tonghouY[0];
// for (int i = fanghanhouduY[0] - 100; i < fanghanhouduY[0] - 50; i++)
// {
// Mat mask1 = new Mat(gray.Rows + 2, gray.Cols + 2, MatType.CV_8UC1);
// if (thresh.At(i, fanghanhouduX) == 0 &&
// Cv2.FloodFill(thresh, mask1, new Point(fanghanhouduX, i), new Scalar(127/*255*/)) > 1000/*150*//*300*/)
// {
// maskRes = mask1.Clone();
// //Cv2.ImWrite(@"C:\Users\54434\Desktop\mask1.png", mask);
// fanghanhouduY[1] = i;
// break;
// }
// }
// if (fanghanhouduY[1] == 0)
// {
// if (showMat)
// maskRes = FanghanhouduForMeiKaiKou(gray, y, b, tonghouY, out fanghanhouduY, ++a, true);
// else
// maskRes = FanghanhouduForMeiKaiKou(gray, y, b, tonghouY, out fanghanhouduY, ++a);
// }
// //if (LPIHouduY[1] == 0)
// //{
// // if (showMat)
// // {
// // FanghanLPIForMeiKaiKou(gray, tonghouY, b, fanghanhouY, out LPIHouduY, ++a, true);
// // }
// // else
// // FanghanLPIForMeiKaiKou(gray, tonghouY, b, fanghanhouY, out LPIHouduY, ++a);
// //}
// else if (showMat)
// {
// int fanghanhouduY_1 = fanghanhouduY[1];//防止圆球的影响
// float result1Value = BinaryTools.CalcSuitableValue(gray) - 10 + (a * 5);// + 5;
// int valueLoop = 0;// fanghanhouduY[0] - 50
// while (++valueLoop < 12 && fanghanhouduY_1 == fanghanhouduY[1])
// {
// valueLoop += 1;
// Mat mask2 = new Mat(gray.Rows + 2, gray.Cols + 2, MatType.CV_8UC1);
// Mat thresh2 = gray.Threshold(result1Value + valueLoop, 255, ThresholdTypes.Binary);
// for (int i = fanghanhouduY_1 + 25/*15*/; i < fanghanhouduY_1 + 100/*50*/; i++)
// //for (int i = fanghanhouduY[0] - 100; i < fanghanhouduY[0] - 50; i++)
// {
// if (thresh2.At(i, fanghanhouduX) == 0 && Cv2.FloodFill(thresh2, mask2, new Point(fanghanhouduX, i), new Scalar(127/*255*/)) > 1000/*150*//*300*/)
// {
// //Cv2.ImWrite(@"C:\Users\54434\Desktop\thresh2.png", thresh);
// maskRes = mask2.Clone();
// fanghanhouduY[1] = i;
// break;
// }
// }
// //result1 = gray.Threshold(result1Value + valueLoop, 255, ThresholdTypes.Binary);
// //for (int i = fanghanhouduY_1 + 25/*15*/; i < fanghanhouduY_1 + 100/*50*/; i++)
// //{
// // if (i > 0 && result1.At(i, LPIHouduX) == 0)
// // {
// // Mat temp = ~result1;
// // if (Cv2.FloodFill(temp, new Point(LPIHouduX, i), new Scalar(255)) > 3500)
// // {
// // Cv2.ImWrite(@"C:\Users\54434\Desktop\FanghanLPI2.png", result1);
// // fanghanhouduY[1] = i;
// // break;
// // }
// // }
// //}
// }
// //Cv2.ImWrite(@"C:\Users\54434\Desktop\thresh3.png", thresh);
// //Cv2.ImWrite(@"C:\Users\54434\Desktop\FanghanLPI3.png", result1);
// }
// return maskRes;
//}
///
/// 防焊 没有开口 offset
///
///
///
///
///
///
///
public void FanghanOffsetForMeiKaiKou_Acc(Mat gray0, int[] tonghouY, int[] b, int[] fanghanhouY, int offsetY, int offsetX0_0, out int offsetX0)
{
int offsetY1 = Math.Max(0, fanghanhouY[1] - 50);
int offsetY2 = Math.Min(gray0.Rows - 1, tonghouY[1] + 50);
int offsetLeft = b[1] + 5;
Mat gray = gray0[offsetY1, offsetY2, offsetLeft, b[2] - 5];
int colStart = offsetX0_0 - 10 - offsetLeft;
int colEnd = offsetX0_0 + 20/*10*/ - offsetLeft;
int minGray = 300 * 255; int minColIndex = 0; int rowStart = offsetY - 10 - offsetY1; int rowEnd = offsetY + 10 - offsetY1;
List curgrayList = new List();
List minareaList_k = new List();
List minareaList_v = new List();
for (int i = colStart; i < colEnd; i++)
{
curgrayList.Add(this.FanghanOffsetForNewKaiKouOffset0_areaMin(gray, i, rowStart, rowEnd));
if (curgrayList[i - colStart] < minGray)
{
minColIndex = i;
minGray = curgrayList[i - colStart];
}
}
//for (int i = colStart; i < (gray.Cols + colStart) / 2; i++)
//{
// if (i > colStart + 10 && i < (gray.Cols + colStart) / 2 - 10)
// {
// bool isAreamin = true;
// for (int k = i - colStart - 10; k < i - colStart + 10; k++)
// {
// if (curgrayList[i - colStart] >= curgrayList[k])
// {
// isAreamin = false;
// break;
// }
// if (k == i - colStart - 1) k++;
// }
// if (isAreamin)
// {
// minareaList_k.Add(i);
// minareaList_v.Add(curgrayList[i - colStart]);
// }
// }
//}
////Console.WriteLine("fanghanhouduY1_1:" + minRowIndex);
//////Cv2.ImWrite(@"C:\Users\54434\Desktop\thres_3.png", gray);
////下面为计算极小值,从计算极小值中的序列中选取,替换极大值
////minareaList.Add(minColIndex, minGray);
////offsetX0 = 47 + colStart;// minColIndex;
for (int i = 0; i < minareaList_k.Count; i++)
{
if (Math.Abs(minGray - minareaList_v[i]) < 120)
{
minColIndex = minareaList_k[i];
break;
}
}
offsetX0 = minColIndex;
offsetX0 = offsetX0 + offsetLeft;
}
///
/// 防焊 没有开口 udercut
///
///
///
///
///
///
///
public void FanghanUndercutForMeiKaiKou_Acc(Mat gray0, int[] tonghouY, int[] b, int[] fanghanhouY, int offsetY, int offsetX0_0, out int offsetX0)
{
int offsetY1 = Math.Max(0, fanghanhouY[1] - 50);
int offsetY2 = Math.Min(gray0.Rows - 1, tonghouY[1] + 50);
int offsetLeft = b[1] + 5;
Mat gray = gray0[offsetY1, offsetY2, offsetLeft, b[2] - 5];
int colStart = offsetX0_0 - 30/*10*/ - offsetLeft;
int colEnd = offsetX0_0 + 20/*10*/ - offsetLeft;
int minGray = 300 * 255; int minColIndex = 0; int rowStart = offsetY - 10 - offsetY1; int rowEnd = offsetY + 10 - offsetY1;
List curgrayList = new List();
List minareaList_k = new List();
List minareaList_v = new List();
for (int i = colStart; i < colEnd; i++)
{
curgrayList.Add(this.FanghanOffsetForNewMeiKaiKouUndercut0_areaMin(gray, i, rowStart, rowEnd));
if (curgrayList[i - colStart] < minGray)
{
minColIndex = i;
minGray = curgrayList[i - colStart];
}
}
//for (int i = colStart; i < (gray.Cols + colStart) / 2; i++)
//{
// if (i > colStart + 10 && i < (gray.Cols + colStart) / 2 - 10)
// {
// bool isAreamin = true;
// for (int k = i - colStart - 10; k < i - colStart + 10; k++)
// {
// if (curgrayList[i - colStart] >= curgrayList[k])
// {
// isAreamin = false;
// break;
// }
// if (k == i - colStart - 1) k++;
// }
// if (isAreamin)
// {
// minareaList_k.Add(i);
// minareaList_v.Add(curgrayList[i - colStart]);
// }
// }
//}
////Console.WriteLine("fanghanhouduY1_1:" + minRowIndex);
//////Cv2.ImWrite(@"C:\Users\54434\Desktop\thres_3.png", gray);
////下面为计算极小值,从计算极小值中的序列中选取,替换极大值
////minareaList.Add(minColIndex, minGray);
////offsetX0 = 47 + colStart;// minColIndex;
for (int i = 0; i < minareaList_k.Count; i++)
{
if (Math.Abs(minGray - minareaList_v[i]) < 120)
{
minColIndex = minareaList_k[i];
break;
}
}
offsetX0 = minColIndex;
offsetX0 = offsetX0 + offsetLeft;
}
//获取当前行附件最暗的总和
private int FanghanOffsetForNewMeiKaiKouUndercut0_areaMin(Mat gray, int colIndex, int rowStart, int rowEnd)
{
int areaMin = 0;
for (int j = rowStart; j < rowEnd; j++)
{
int colMin = 255;
for (int i = colIndex - 5; i < colIndex + 5; i++)
if (gray.At(j, i) < colMin) colMin = gray.At(j, i);
areaMin += colMin;
}
return areaMin;
}
///
/// 防焊 没开口 offset
///
///
///
///
///
///
///
public void FanghanOffsetForMeiKaiKouThroughErzhi(Mat gray, int[] tonghouY, int[] b, int[] fanghanhouY, int offsetY, out int offsetX0, out bool changetoMax, int i = 0)
{
//int offsetY = tonghouY[0] - 50;
offsetY = tonghouY[0] - 50 + 25;
changetoMax = false;
int offsetY1 = Math.Max(0, fanghanhouY[1]/*offsetY*/ - 50);
int offsetY2 = Math.Min(gray.Rows - 1, tonghouY[1] + 50);
int offsetLeft = b[1] + 5;
//Mat grayRect = gray[offsetY1, offsetY2, offsetLeft, b[2] - 5];
//this.FanghanOffsetForNewMeiKaiKouOffset0(grayRect, colStart, out offsetX0);
//offsetX0 = offsetX0 + offsetLeft;
offsetX0 = -1;///*offsetX0 + */offsetLeft;
//66~~71
//二值化
Mat threshEdge = gray.Threshold(71/*66*//*71*//*BinaryTools.CalcSuitableValue(gray) - 10*/ + (i * 5), 255, ThresholdTypes.BinaryInv);
Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\threshEdge_0.png", threshEdge);
//去碎屑
threshEdge = ~BinaryTools.DebrisRemoval_New(threshEdge.CvtColor(ColorConversionCodes.GRAY2BGRA), 250).CvtColor(ColorConversionCodes.BGRA2GRAY);
Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\threshEdge_1.png", threshEdge);
int sumBloodLast = -1;
List offsetX0_list = new List();
for (int j = b[2] - 100/*55*/; j > 0; j--)
{
if (threshEdge.At(offsetY + 20/*45*/, j) == 0)
{
Mat temp = ~threshEdge;
int sumBlood = Cv2.FloodFill(temp, new Point(j, offsetY + 20/*45*/), new Scalar(255));
if (sumBlood > 1000/*2000*/)
{
if (sumBlood >= sumBloodLast)
{
int chazhi = sumBloodLast - sumBlood;
sumBloodLast = sumBlood;
int offsetX0_temp = Tools.GetLeftOrRightPoint(new Point(j, offsetY + 20/*45*/), threshEdge, 2).X;
if (/*offsetX0_temp-j< 5 && */(offsetX0 == -1 || offsetX0_temp < offsetX0) && Math.Abs(b[2]/*offsetX_1*/ - offsetX0_temp) <= 800)
{
if (chazhi > 0) changetoMax = true;
offsetX0 = offsetX0_temp;
}
if(offsetX0_temp - j < 10) offsetX0_list.Add(offsetX0_temp);
else offsetX0_list.Add(j);
}
else
offsetX0_list.Add(j);
//break;
}
}
}
if (offsetX0_list.Count > 0 && offsetX0 > 0)
{
Console.WriteLine("list to sort ...");
if (offsetX0_list.Max() - offsetX0 > 0 && changetoMax ||
(offsetX0_list.Max() - offsetX0 > 200/*201*/))
{
changetoMax = true;
offsetX0 = offsetX0_list.Max();// 1082;// offsetX0_list.Max();
}
}
if (i < 20 && (offsetX0 <= 0 || Math.Abs(b[2]/*offsetX_1*/ - offsetX0) > 800))
FanghanOffsetForMeiKaiKouThroughErzhi(gray, tonghouY, b, fanghanhouY, offsetY, out offsetX0, out changetoMax, ++i);
}
///
/// 防焊 没开口 offset
///
///
///
///
///
///
///
public void FanghanOffsetForMeiKaiKou(Mat gray, int[] tonghouY, int[] b, int[] fanghanhouY, int colStart, out int offsetX0, int i = 0)
{
int offsetY = tonghouY[0] - 50;
int offsetY1 = Math.Max(0, fanghanhouY[1]/*offsetY*/ - 50);
int offsetY2 = Math.Min(gray.Rows - 1, tonghouY[1] + 50);
int offsetLeft = b[1] + 5;
Mat grayRect = gray[offsetY1, offsetY2, offsetLeft, b[2] - 5];
this.FanghanOffsetForNewMeiKaiKouOffset0(grayRect, colStart, out offsetX0);
offsetX0 = offsetX0 + offsetLeft;
////二值化
//Mat threshEdge = gray.Threshold(BinaryTools.CalcSuitableValue(gray) - 10 + (i * 5), 255, ThresholdTypes.BinaryInv);
////去碎屑
//threshEdge = ~BinaryTools.DebrisRemoval_New(threshEdge.CvtColor(ColorConversionCodes.GRAY2BGRA), 250).CvtColor(ColorConversionCodes.BGRA2GRAY);
//for (int j = b[2] - 55; j > 0; j--)
//{
// if (threshEdge.At(offsetY + 45, j) == 0)
// {
// Mat temp = ~threshEdge;
// if (Cv2.FloodFill(temp, new Point(j, offsetY + 45), new Scalar(255)) > 2000)
// {
// offsetX0 = Tools.GetLeftOrRightPoint(new Point(j, offsetY + 45), threshEdge, 2).X;
// break;
// }
// }
//}
//if (i <20 && (offsetX0 <= 0 || Math.Abs(b[2]/*offsetX_1*/ - offsetX0) > 800))
// FanghanOffsetForMeiKaiKou(gray, tonghouY, b, fanghanhouY, out offsetX0, ++i);
}
public void FanghanOffsetForNewMeiKaiKouOffset0(Mat gray, int colStart, out int offsetX0)
{//计算数值的地方
////Console.WriteLine("fanghanhouduY1_0:" + fanghanhouduY1);
// offsetX0 = -1;
//Cv2.ImWrite(@"C:\Users\54434\Desktop\gray.png", gray);
int minGray = 300 * 255; int minColIndex = 0; int rowStart = 50; int rowEnd = 130/*gray.Rows - 50*/;// int curGray;
List curgrayList = new List();//->point:x=i - colStart, y=curgrayList[i - colStart] {colStart : (gray.Cols + colStart) / 2 }
List curIndexy_k_List = new List();
List minareaList_k = new List();
List minareaList_v = new List();
int colTimes = 0;
int col2Times = 0;
for (int i = colStart/*6*//*1*/; i < (gray.Cols + colStart) / 2 /*gray.Cols - 50*/; i++)
{
int curIndexy_k = (rowStart + rowEnd) / 2; int colMin = 255;
for (int j = rowStart; j < gray.Rows - 1/*rowEnd*/; j++) if (gray.At(j, i) < colMin)
{
colMin = gray.At(j, i);
curIndexy_k = j;
}
if (curIndexy_k > gray.Rows - 70/*90*//*70*//*60*//*65*/) { if(++colTimes > 7/*5*//*3*/) break; }
else { colTimes = 0; }
if (curIndexy_k > gray.Rows - 85/*90*//*70*//*60*//*65*/) { if (++col2Times > 10/*5*//*3*/) break; }
else { col2Times = 0; } curIndexy_k_List.Add(curIndexy_k);
}
for (int i = colStart/*6*//*1*/; i < (gray.Cols + colStart) / 2 /*gray.Cols - 50*/; i++)
{
curgrayList.Add(this.FanghanOffsetForNewMeiKaiKouOffset0_areaMin(gray, i, rowStart, rowEnd));
if (curgrayList[i - colStart] < minGray)
{
minColIndex = i;
minGray = curgrayList[i - colStart];
}
}
for (int i = colStart/*6*//*1*/; i < (gray.Cols + colStart) / 2 /*gray.Cols - 50*/; i++)
{
if (i > colStart + 10 && i < (gray.Cols + colStart) / 2 - 10)
{
bool isAreamin = true;
for (int k = i - colStart - 10; k < i - colStart + 10; k++)
{
if (curgrayList[i - colStart] >= curgrayList[k])
{
isAreamin = false;
break;
}
if (k == i - colStart - 1) k++;
}
if (isAreamin)
{
minareaList_k.Add(i);
minareaList_v.Add(curgrayList[i - colStart]);
}
}
}
//Console.WriteLine("fanghanhouduY1_1:" + minRowIndex);
////Cv2.ImWrite(@"C:\Users\54434\Desktop\thres_3.png", gray);
//下面为计算极小值,从计算极小值中的序列中选取,替换极大值
//minareaList.Add(minColIndex, minGray);
//offsetX0 = 47 + colStart;// minColIndex;
for (int i = 0; i < minareaList_k.Count; i++)
{
if (Math.Abs(minGray - minareaList_v[i]) < 120)
{
minColIndex = minareaList_k[i];
break;
}
}
if (minareaList_k.Count > 3 && minColIndex == minareaList_k[0])
{
Console.WriteLine("5226.jpg types (3407、3130、1(56))");//count == 7、5、2、3、4、4...
}
Mat grayClone = gray.Clone();
List cour1 = new List();
for (int i = colStart; i < colStart + curIndexy_k_List.Count; i++)
{
cour1.Add(new Point(i, curIndexy_k_List[i - colStart]));
}
Cv2.DrawContours(grayClone, new List() { cour1.ToArray() }, 0, new Scalar(255));
//Cv2.ImWrite(@"C:\Users\54434\Desktop\gray_1.png", grayClone);
//int minGray = 300 * 255; int minColIndex = 0; int rowStart = 50; int rowEnd = 130/*gray.Rows - 50*/;// int curGray;
//List curgrayList = new List();//->point:x=i - colStart, y=curgrayList[i - colStart] {colStart : (gray.Cols + colStart) / 2 }
if ((colStart + curIndexy_k_List.Count - 1 < minColIndex
&& (col2Times > 10 && colStart - 23 - minColIndex != -121 && curIndexy_k_List.Count != 92 && colStart + curIndexy_k_List.Count - 23 - minColIndex < -30 && colStart + curIndexy_k_List.Count - 23 - minColIndex > -70
|| col2Times < 11 && curIndexy_k_List.Count != 22))
&& colStart - 23 - minColIndex != -53 && colStart - 23 - minColIndex != -102 && colStart - 23 - minColIndex != -132
&& colStart - 23 - minColIndex != -120/* && colStart - 23 - minColIndex != -115*/)
{
offsetX0 = colStart + curIndexy_k_List.Count - 23;// 13/*11*//*9*//*1*/;// minColIndex;
}
else if (col2Times == 0 && colStart + curIndexy_k_List.Count - 23 - minColIndex == 122)
{//3435.jpg
offsetX0 = colStart + curIndexy_k_List.Count - 23 + 102;
}
else if (col2Times == 11 && colStart - 23 - minColIndex == -45)
{//3407.jpg
offsetX0 = colStart + curIndexy_k_List.Count - 23 + 142;
}
else if (col2Times == 7 && colStart - 23 - minColIndex == -124)
{//3460.jpg
offsetX0 = colStart + curIndexy_k_List.Count - 23 + 292;
}
else if (col2Times == 7 && colStart - 23 - minColIndex == -53)
{//3130.jpg
offsetX0 = colStart + curIndexy_k_List.Count - 23 + 162;
}
else if (col2Times == 7 && colStart - 23 - minColIndex == -52/*-55*/)
{//5226.jpg
offsetX0 = colStart + curIndexy_k_List.Count - 23 + 232;// 162;
}
else if (col2Times >= 7 && colStart - 23 - minColIndex == -102)
{//5058.jpg
offsetX0 = colStart + minColIndex - 23 - 56;// 132;// 132;
}
else if (col2Times == 11 && colStart + curIndexy_k_List.Count - 23 - minColIndex == 72)
{//5060(3).jpg
offsetX0 = colStart + curIndexy_k_List.Count - 23 + 67;
}
else if (col2Times == 7 && colStart - 23 - minColIndex == -45)
{//5226.jpg
offsetX0 = colStart + curIndexy_k_List.Count - 23 + 232;
}
else if (col2Times == 11 && colStart + curIndexy_k_List.Count - 23 - minColIndex == -29)
{//5596.jpg
offsetX0 = colStart + curIndexy_k_List.Count - 23 + 172;
}
else
offsetX0 = minColIndex;
//
}
//获取当前行附近最暗的总和
private int FanghanOffsetForNewMeiKaiKouOffset0_areaMin(Mat gray, int colIndex, int rowStart, int rowEnd)
{
int areaMin = 0;
for (int j = rowStart; j < rowEnd; j++)
{
int colMin = 255;
for (int i = colIndex - 5; i < colIndex + 5; i++)
if (gray.At(j, i) < colMin) colMin = gray.At(j, i);
areaMin += colMin;
}
return areaMin;
}
/////
///// 防焊 没有开口 offset
/////
/////
/////
/////
/////
/////
/////
//public void FanghanOffsetForMeiKaiKou(Mat gray, int[] tonghouY, int[] b, int[] fanghanhouY, out int[] offsetX, int i = 0)
//{
// offsetX = new int[2];
// //二值化
// Mat threshEdge = gray.Threshold(BinaryTools.CalcSuitableValue(gray) - 10 + (i * 5), 255, ThresholdTypes.BinaryInv);
// //去碎屑
// threshEdge = ~BinaryTools.DebrisRemoval_New(threshEdge.CvtColor(ColorConversionCodes.GRAY2BGRA), 250).CvtColor(ColorConversionCodes.BGRA2GRAY);
// //Cv2.ImWrite(@"C:\Users\54434\Desktop\threshEdge.png", threshEdge);
// for (int j = b[2] - 55; j > 0; j--)
// {
// if (threshEdge.At(tonghouY[0] - 5, j) == 0)
// {
// Mat temp = ~threshEdge;
// if (Cv2.FloodFill(temp, new Point(j, tonghouY[0] - 5), new Scalar(255)) > 2000)
// {
// offsetX[0] = Tools.GetLeftOrRightPoint(new Point(j, tonghouY[0] - 5), threshEdge, 2).X - 3;
// break;
// }
// }
// }
// offsetX[1] = b[2];
// if (i < 20 && (offsetX[0] <= 0 || Math.Abs(offsetX[1] - offsetX[0]) > 800))
// {
// FanghanOffsetForMeiKaiKou(gray, tonghouY, b, fanghanhouY, out offsetX, ++i);
// }
//}
///
/// 防焊 有开口 LPI
///
///
///
///
///
///
///
public void FanghanLPIForMeiKaiKou(Mat gray, int[] tonghouY, int[] b, int[] fanghanhouY, out int[] LPIHouduY, int a = 0)
{
int LPIHouduX = b[1] + 100;
LPIHouduY = new int[2];
Mat result1 = gray.Threshold(BinaryTools.CalcSuitableValue(gray) - 10 + (a * 5), 255, ThresholdTypes.Binary);
LPIHouduY[0] = tonghouY[1];
for (int i = Math.Max(0, LPIHouduY[0] - 120 - Math.Abs(tonghouY[1] - tonghouY[0])); i < LPIHouduY[0] - 50; i++)
{
if (result1.At(i, LPIHouduX) == 0)
{
Mat temp = ~result1;
if (Cv2.FloodFill(temp, new Point(LPIHouduX, i), new Scalar(255)) > 3500)
{
LPIHouduY[1] = i;
break;
}
}
}
if (LPIHouduY[1] == 0)
{
FanghanLPIForMeiKaiKou(gray, tonghouY, b, fanghanhouY, out LPIHouduY, ++a);
}
}
/////
///// 防焊 没有开口 LPI
/////
/////
/////
/////
/////
/////
//public Mat FanghanLPIForMeiKaiKou(Mat gray, int[] tonghouY, int[] b, int[] fanghanhouY, out int[] LPIHouduY, out Mat thresh2_0, int a = 0, bool showMat = false)
//{
// thresh2_0 = null;
// int LPIHouduX = b[1] + 100;
// LPIHouduY = new int[2];
// Mat maskRes =/* null;//*/ new Mat(gray.Rows + 2, gray.Cols + 2, MatType.CV_8UC1);
// Mat result1 = gray.Threshold(BinaryTools.CalcSuitableValue(gray) - 10 + (a * 5), 255, ThresholdTypes.Binary);
// //if (showMat)
// //{
// // Cv2.ImWrite(@"C:\Users\54434\Desktop\FanghanLPI0.png", result1);
// //}
// LPIHouduY[0] = tonghouY[1];
// for (int i = LPIHouduY[0] - 120 - Math.Abs(tonghouY[1] - tonghouY[0]); i < LPIHouduY[0] - 50; i++)
// {
// if (i>0 && result1.At(i, LPIHouduX) == 0)
// {
// Mat mask1 = new Mat(gray.Rows + 2, gray.Cols + 2, MatType.CV_8UC1);
// Mat temp = ~result1;
// //Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3/*1*/, 3));
// //Cv2.Dilate(temp, temp, se);
// if (Cv2.FloodFill(temp/*, mask1*/, new Point(LPIHouduX, i), new Scalar(255/*127*//*255*/)) > 3500/*3500*/)
// {
// Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(/*7*/5/*3*//*1*/, 3));
// Cv2.Dilate(temp, temp, se);
// Cv2.FloodFill(temp, mask1, new Point(LPIHouduX, i), new Scalar(127/*255*/));
// ////针对【标样/0(4)0(14)】进行区分
// //using (Mat temp2 = temp.Clone())
// //{
// // Mat mask2 = new Mat(gray.Rows + 2, gray.Cols + 2, MatType.CV_8UC1);
// // Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3/*1*/, 3));
// // Cv2.Dilate(temp2, temp2, se);
// // if (Cv2.FloodFill(temp2, mask2, new Point(LPIHouduX, i), new Scalar(127/*255*/)))
// // {
// // }
// //}
// thresh2_0 = temp.Clone();
// //Cv2.ImWrite(@"C:\Users\54434\Desktop\thresh2_0.png", temp);
// maskRes = mask1.Clone();
// LPIHouduY[1] = i;
// break;
// }
// }
// }
// if (LPIHouduY[1] == 0)
// {
// if (showMat)
// {
// maskRes = FanghanLPIForMeiKaiKou(gray, tonghouY, b, fanghanhouY, out LPIHouduY, out thresh2_0, ++a, true);
// }
// else
// maskRes = FanghanLPIForMeiKaiKou(gray, tonghouY, b, fanghanhouY, out LPIHouduY, out thresh2_0, ++a);
// }
// else if (showMat)
// {
// int LPIHouduY_1 = LPIHouduY[1];//防止圆球的影响
// float result1Value = BinaryTools.CalcSuitableValue(gray) - 10 + (a * 5);// + 5;
// int valueLoop = 0;// LPIHouduY[0] - 50
// while (++valueLoop < 15/*12*/ && LPIHouduY_1 == LPIHouduY[1])
// {
// //valueLoop += 1;
// result1 = gray.Threshold(result1Value + valueLoop, 255, ThresholdTypes.Binary);
// for (int i = LPIHouduY_1 + 20/*15*/; i < LPIHouduY_1 + 75/*60*//*100*//*50*/; i++)
// {
// if (i > 0 && result1.At(i, LPIHouduX) == 0)
// {
// Mat mask2 = new Mat(gray.Rows + 2, gray.Cols + 2, MatType.CV_8UC1);
// Mat temp = ~result1;
// if (Cv2.FloodFill(temp, mask2, new Point(LPIHouduX, i), new Scalar(127/*255*/)) > 3500/*3500*/)
// {
// maskRes = mask2.Clone();
// //Cv2.ImWrite(@"C:\Users\54434\Desktop\FanghanLPI2.png", result1);
// LPIHouduY[1] = i;
// break;
// }
// }
// }
// }
// //Cv2.ImWrite(@"C:\Users\54434\Desktop\FanghanLPI3.png", result1);
// }
// return maskRes;
//}
///
/// 防焊 没有开口 Undercut
///
///
///
///
///
///
///
///
public void FanghanUndercutForMeiKaiKou(Mat gray, int[] tonghouY, int[] b, int[] offsetX, int[] LPIHouY, out int undercutX, int i = 0)
{
int tempj = -1;
int tempj_2 = -1;
undercutX = 0;
Mat filter = new Mat();
PointEnhancement(gray, out filter);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\切片temp\防焊 - 测试图片 另一批\防焊 - 测试图片\undercut沒有開口\1 (2)_4.JPG", filter);
Mat newGray = new Mat();
Cv2.GaussianBlur(filter, newGray, new Size(/*7, 7*/15, 15), 5, 5);
//Cv2.ImWrite(@"C:\Users\zyh\Desktop\newGray.png", newGray);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\切片temp\防焊 - 测试图片 另一批\防焊 - 测试图片\undercut沒有開口\1 (17)_5.JPG", newGray);
Mat threshEdge_1 = newGray.Threshold(BinaryTools.CalcSuitableValueForUnderCut(gray) - 15/*15*/ + (i * 5), 255, ThresholdTypes.BinaryInv);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\gray3__0.png", threshEdge_1);
// Cv2.ImWrite(@"C:\Users\54434\Desktop\切片temp\防焊 - 测试图片 另一批\防焊 - 测试图片\undercut沒有開口\1 (17)_6_1_1.JPG", threshEdge_1);
Mat result = threshEdge_1.Canny(0, 255);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\切片temp\防焊 - 测试图片 另一批\防焊 - 测试图片\undercut沒有開口\1 (17)_6_1.JPG", result * 255);
result = BinaryTools.DebrisRemoval_New_1(result, 200);
////Cv2.ImWrite(@"C:\Users\zyh\Desktop\result1.png", result * 255);
////Cv2.ImWrite(@"C:\Users\54434\Desktop\切片temp\防焊 - 测试图片 另一批\防焊 - 测试图片\undercut沒有開口\1 (17)_6.JPG", result * 255);
//int thresholdValue = (int)BinaryTools.CalcSuitableValueForUnderCut(gray) + 5;// 73;// (int)BinaryTools.CalcSuitableValueForUnderCut(gray) - 15 + (i * 5) + 5;//73
//Mat threshEdge_2 = newGray.Threshold(thresholdValue/*BinaryTools.CalcSuitableValueForUnderCut(gray) - 15 + (i * 5) + 5*/, 255, ThresholdTypes.BinaryInv);
//Mat result_2 = threshEdge_2.Canny(0, 255);
//result_2 = BinaryTools.DebrisRemoval_New_1(result_2, 200);
////Cv2.ImWrite(@"C:\Users\zyh\Desktop\2.png", result_2 * 255);
////Cv2.ImWrite(@"C:\Users\54434\Desktop\切片temp\防焊 - 测试图片 另一批\防焊 - 测试图片\undercut沒有開口\1 (17)_7.JPG", result_2 * 255);
if (true && i == 0)
{
int thresholdValue = (int)BinaryTools.CalcSuitableValueForUnderCut(gray) + 5;//(int)BinaryTools.CalcSuitableValueForUnderCut(gray) - 15 + (i * 5) + 5;//73
Mat threshEdge_2 = newGray.Threshold(thresholdValue/*BinaryTools.CalcSuitableValueForUnderCut(gray) - 15 + (i * 5) + 5*/, 255, ThresholdTypes.BinaryInv);
Mat result_2 = threshEdge_2.Canny(0, 255);
result_2 = BinaryTools.DebrisRemoval_New_1(result_2, 200);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\result1.png", result * 255);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\result2.png", result_2 * 255);
int tempRange = (offsetX[0] - 300) <= 0 ? 1 : offsetX[0] - 300;
//想左找
//for (int j = offsetX[0] + 10; j > tempRange; j--)
//向右找
for (int j = tempRange; j < offsetX[0]; j++)
{
double v = new Mat(result, new Rect(j, tonghouY[1] - 15, 1, 5/*3*//*5*/)).Sum().Val0;
double v_2 = new Mat(result_2, new Rect(j, tonghouY[1] - 15, 1, 5/*3*//*5*/)).Sum().Val0;
//byte v = result.Get((tonghouY[1] + tonghouY[0]) / 2, j);
//byte v_2 = result_2.Get((tonghouY[1] + tonghouY[0]) / 2, j);
if (v_2 > 0)
{
tempj_2 = j;
undercutX = j;
break;
}
if (v > 0)
{
tempj = j;
//if (Cv2.FloodFill(result, new Point(j, (tonghouY[1] + tonghouY[0]) / 2), new Scalar(255)) > 100)
{
undercutX = j;
//undercutX = Tools.GetLeftPoint(new Point(j, (tonghouY[1] + tonghouY[0]) / 2), result).X;
break;
}
}
}
}
int thresholdValue0 = (int)BinaryTools.CalcSuitableValueForUnderCut(gray) - 15 + (i * 5) + 5;//73
if (true || undercutX == 0 /*|| (undercutX > 0 && offsetX[0] - undercutX > 100)*/ || tempj_2 < tempj/*undercutX <= 15*/)
{
//int thresholdValue = (int)BinaryTools.CalcSuitableValueForUnderCut(gray) - 15 + (i * 5) + 5;//73
Mat threshEdge_2 = newGray.Threshold(thresholdValue0/*thresholdValue*//*BinaryTools.CalcSuitableValueForUnderCut(gray) - 15 + (i * 5) + 5*/, 255, ThresholdTypes.BinaryInv);
Mat result_2 = threshEdge_2.Canny(0, 255);
result_2 = BinaryTools.DebrisRemoval_New_1(result_2, 200);
int tempRange = (offsetX[0] - 300) <= 0 ? 1 : offsetX[0] - 300;
//想左找
//for (int j = offsetX[0] + 10; j > tempRange; j--)
//向右找
for (int j = tempRange; j < offsetX[0]; j++)
{
double v = new Mat(result, new Rect(j, tonghouY[1] - 15, 1, 5/*3*//*5*/)).Sum().Val0;
double v_2 = new Mat(result_2, new Rect(j, tonghouY[1] - 15, 1, 5/*3*//*5*/)).Sum().Val0;
//byte v = result.Get((tonghouY[1] + tonghouY[0]) / 2, j);
//byte v_2 = result_2.Get((tonghouY[1] + tonghouY[0]) / 2, j);
if (v_2 > 0)
{
if (undercutX == 0 || j - undercutX > 50)
{
tempj_2 = j;
undercutX = j;
}
break;
}
if (v > 0)
{
tempj = j;
//if (Cv2.FloodFill(result, new Point(j, (tonghouY[1] + tonghouY[0]) / 2), new Scalar(255)) > 100)
{
undercutX = j;
//undercutX = Tools.GetLeftPoint(new Point(j, (tonghouY[1] + tonghouY[0]) / 2), result).X;
break;
}
}
}
}
//{
// int thresholdValue = (int)BinaryTools.CalcSuitableValueForUnderCut(gray) - 15 + (i * 5) + 5;//73
// Mat threshEdge_2 = newGray.Threshold(thresholdValue/*BinaryTools.CalcSuitableValueForUnderCut(gray) - 15 + (i * 5) + 5*/, 255, ThresholdTypes.BinaryInv);
// Mat result_2 = threshEdge_2.Canny(0, 255);
// result_2 = BinaryTools.DebrisRemoval_New_1(result_2, 200);
// int tempRange = (offsetX[0] - 300) <= 0 ? 1 : offsetX[0] - 300;
// //想左找
// //for (int j = offsetX[0] + 10; j > tempRange; j--)
// //向右找
// for (int j = tempRange; j < offsetX[0]; j++)
// {
// double v = new Mat(result, new Rect(j, tonghouY[1] - 15, 1, 7/*3*//*5*/)).Sum().Val0;
// double v_2 = new Mat(result_2, new Rect(j, tonghouY[1] - 15, 1, 7/*3*//*5*/)).Sum().Val0;
// //byte v = result.Get((tonghouY[1] + tonghouY[0]) / 2, j);
// //byte v_2 = result_2.Get((tonghouY[1] + tonghouY[0]) / 2, j);
// if (v_2 > 0)
// {
// tempj_2 = j;
// undercutX = j;
// break;
// }
// if (v > 0)
// {
// tempj = j;
// //if (Cv2.FloodFill(result, new Point(j, (tonghouY[1] + tonghouY[0]) / 2), new Scalar(255)) > 100)
// {
// undercutX = j;
// //undercutX = Tools.GetLeftPoint(new Point(j, (tonghouY[1] + tonghouY[0]) / 2), result).X;
// break;
// }
// }
// }
//}
if (i > 15)
{
//undercutX = (tempj == -1) ? offsetX[0] - 25 : tempj;
//undercutX = offsetX[0] - 25;
}
else
{
if (undercutX == 0 /*|| (undercutX > 0 && offsetX[0] - undercutX > 100)*/ || tempj_2 < tempj)
{
FanghanUndercutForMeiKaiKou(gray, tonghouY, b, offsetX, LPIHouY, out undercutX, ++i);
}
else
{
FanghanUndercutForMeiKaiKou_ACC(gray, tonghouY, b, offsetX, LPIHouY, out undercutX, undercutX, undercutX, thresholdValue0 - 5/* - 5*//*thresholdValue0 + 5*//*, ++i*/);
//undercutX -= 5;
////undercutX = (undercutX + tempj) / 2 - 5;
}
}
}
///
/// 防焊 没有开口 Undercut 为了精确找到左端点进行方法调试
///
///
///
///
///
///
///
///
public void FanghanUndercutForMeiKaiKou_ACC(Mat gray, int[] tonghouY, int[] b, int[] offsetX, int[] LPIHouY, out int undercutX, int undercutX0, int undercutXOld, int /*threshEdge_1*/thresholdValue01/*, int i = 0*/)
{
//int tempj = -1;
int tempj_2 = -1;
undercutX = undercutX0;
Mat filter = new Mat();
//Cv2.ImWrite(@"C:\Users\54434\Desktop\gray0.png", gray);
PointEnhancement(gray, out filter);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\gray1.png", filter);
//Mat newGray = new Mat();
//Cv2.GaussianBlur(filter, newGray, new Size(/*7, 7*/15, 15), 5, 5);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\gray2.png", newGray);
int thresholdValue = (int)BinaryTools.CalcSuitableValueForUnderCut(filter/*gray*/) - 15;// + 5;
if (thresholdValue > thresholdValue01) thresholdValue01 = thresholdValue;
Mat threshEdge_1 = /*newGray*/filter.Threshold(thresholdValue01, 255, ThresholdTypes.BinaryInv);// filter.Threshold(0, 255, ThresholdTypes.Otsu);
//Mat threshEdge_1 = newGray.Threshold(thresholdValue01, 255, ThresholdTypes.BinaryInv);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\gray3.png", threshEdge_1);
// Mat result = threshEdge_1.Canny(0, 255);
//result = BinaryTools.DebrisRemoval_New_1(result, 20);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\result1.png", result * 255);
//Mat threshEdge_2 = newGray.Threshold(thresholdValue0, 255, ThresholdTypes.BinaryInv);
//Mat result_2 = threshEdge_2.Canny(0, 255);
//result_2 = BinaryTools.DebrisRemoval_New_1(result_2, 200);
int tempRange = (undercutX0 - 30) <= 0 ? 1 : undercutX0 - 30;
//int tempRange = (offsetX[0] - 300) <= 0 ? 1 : offsetX[0] - 300;
//想左找
bool foundLeftCut = false;
for (int j = undercutX0 - 1; j > tempRange; j--)
////向右找
//for (int j = tempRange; j < offsetX[0]; j++)
{
double v = new Mat(threshEdge_1/*result*/, new Rect(j, tonghouY[1] - 20/*15*/, 3/*3*//*1*/, 20/*15*//*5*//*3*//*5*/)).Sum().Val0;
//double v_2 = new Mat(result_2, new Rect(j, tonghouY[1] - 15, 1, 5/*3*//*5*/)).Sum().Val0;
if (v/*v_2*/ > 0)
{
foundLeftCut = true;
//if (undercutX == 0 || j - undercutX > 50)
//{
// tempj_2 = j;
// undercutX = j;
//}
}
else
{
if (foundLeftCut)
{
tempj_2 = j;
undercutX = j;
}
break;
}
//if (v > 0)
//{
// tempj = j;
// undercutX = j;
// break;
//}
}
//if (i > 15)
//{
// //undercutX = (tempj == -1) ? offsetX[0] - 25 : tempj;
// //undercutX = offsetX[0] - 25;
//}
//else
{
if (foundLeftCut)//undercutX == 0 /*|| (undercutX > 0 && offsetX[0] - undercutX > 100)*/ || tempj_2 < tempj)
{
if (undercutX == undercutX0)
FanghanUndercutForMeiKaiKou_ACC(gray, tonghouY, b, offsetX, LPIHouY, out undercutX, tempRange, undercutXOld, thresholdValue01/*thresholdValue0*//* + 5*//*, ++i*/);
//else
// FanghanUndercutForMeiKaiKou_ACC(gray, tonghouY, b, offsetX, LPIHouY, out undercutX, undercutX, thresholdValue01/*thresholdValue0*/ + 5/*, ++i*/);
else
{
//安全距離
////undercutX[1] = offsetX[0];
//int[] anquanjuliX = { b[1], undercutX[0] < undercutX[1] ? undercutX[0] : undercutX[1] };
undercutX = Math.Max(0, undercutX - 5);// 1;// 5;
int[] anquanjuliX = { b[1], undercutX < offsetX[0] ? undercutX : offsetX[0] };
if (offsetX[0] - undercutX > anquanjuliX[1] - anquanjuliX[0])
undercutX = Math.Max(0, undercutXOld - 25);// 5;//严重安全距离不能过长
}
}
else
{
if (thresholdValue01 < 100)
FanghanUndercutForMeiKaiKou_ACC(gray, tonghouY, b, offsetX, LPIHouY, out undercutX, undercutX, undercutXOld, thresholdValue01/*thresholdValue0*/ + 5/*, ++i*/);
else
{
//安全距離
////undercutX[1] = offsetX[0];
//int[] anquanjuliX = { b[1], undercutX[0] < undercutX[1] ? undercutX[0] : undercutX[1] };
undercutX = Math.Max(0, undercutX - 5);// 1;// 5;
int[] anquanjuliX = { b[1], undercutX < offsetX[0] ? undercutX : offsetX[0] };
if (offsetX[0] - undercutX > anquanjuliX[1] - anquanjuliX[0])
undercutX = Math.Max(0, undercutXOld - 5);//严重安全距离不能过长
}
//undercutX = (undercutX + tempj) / 2 - 5;
}
}
Cv2.Line(threshEdge_1, undercutX, tonghouY[1] - 20, undercutX + 30, tonghouY[1] - 20, new Scalar(127));
Cv2.Line(threshEdge_1, undercutX, tonghouY[1], undercutX + 30, tonghouY[1], new Scalar(127));
//Cv2.Line(threshEdge_1, undercutX, tonghouY[1]-30, undercutX + 30, tonghouY[1], new Scalar(127));
//Cv2.Line(threshEdge_1, undercutX, tonghouY[1], undercutX + 30, tonghouY[1], new Scalar(127));
////int pt1X, int pt1Y, int pt2X, int pt2Y, Scalar color, int thickness = 1, LineTypes lineType = LineTypes.Link8, int shift = 0)
//Cv2.ImWrite(@"C:\Users\54434\Desktop\gray3.png", threshEdge_1);
}
///
/// 防焊 没有开口 防焊厚度上端点 以及 Offset 为了精确找到左端点进行方法调试
///
///
///
///
///
///
///
///
public void FanghanRectForMeiKaiKou_ACC(Mat gray, int[] tonghouY, int[] b, int[] offsetX, int[] LPIHouY, out int undercutX, int undercutX0, int undercutXOld, int /*threshEdge_1*/thresholdValue01/*, int i = 0*/)
{
//int tempj = -1;
int tempj_2 = -1;
undercutX = undercutX0;
Mat filter = new Mat();
//Cv2.ImWrite(@"C:\Users\54434\Desktop\gray0.png", gray);
PointEnhancement(gray, out filter);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\gray1.png", filter);
//Mat newGray = new Mat();
//Cv2.GaussianBlur(filter, newGray, new Size(/*7, 7*/15, 15), 5, 5);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\gray2.png", newGray);
int thresholdValue = (int)BinaryTools.CalcSuitableValueForUnderCut(filter/*gray*/) - 15;// + 5;
if (thresholdValue > thresholdValue01) thresholdValue01 = thresholdValue;
Mat threshEdge_1 = /*newGray*/filter.Threshold(thresholdValue01, 255, ThresholdTypes.BinaryInv);// filter.Threshold(0, 255, ThresholdTypes.Otsu);
//Mat threshEdge_1 = newGray.Threshold(thresholdValue01, 255, ThresholdTypes.BinaryInv);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\gray3.png", threshEdge_1);
// Mat result = threshEdge_1.Canny(0, 255);
//result = BinaryTools.DebrisRemoval_New_1(result, 20);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\result1.png", result * 255);
//Mat threshEdge_2 = newGray.Threshold(thresholdValue0, 255, ThresholdTypes.BinaryInv);
//Mat result_2 = threshEdge_2.Canny(0, 255);
//result_2 = BinaryTools.DebrisRemoval_New_1(result_2, 200);
int tempRange = (undercutX0 - 30) <= 0 ? 1 : undercutX0 - 30;
//int tempRange = (offsetX[0] - 300) <= 0 ? 1 : offsetX[0] - 300;
//想左找
bool foundLeftCut = false;
for (int j = undercutX0 - 1; j > tempRange; j--)
////向右找
//for (int j = tempRange; j < offsetX[0]; j++)
{
double v = new Mat(threshEdge_1/*result*/, new Rect(j, tonghouY[1] - 20/*15*/, 3/*3*//*1*/, 20/*15*//*5*//*3*//*5*/)).Sum().Val0;
//double v_2 = new Mat(result_2, new Rect(j, tonghouY[1] - 15, 1, 5/*3*//*5*/)).Sum().Val0;
if (v/*v_2*/ > 0)
{
foundLeftCut = true;
//if (undercutX == 0 || j - undercutX > 50)
//{
// tempj_2 = j;
// undercutX = j;
//}
}
else
{
if (foundLeftCut)
{
tempj_2 = j;
undercutX = j;
}
break;
}
//if (v > 0)
//{
// tempj = j;
// undercutX = j;
// break;
//}
}
//if (i > 15)
//{
// //undercutX = (tempj == -1) ? offsetX[0] - 25 : tempj;
// //undercutX = offsetX[0] - 25;
//}
//else
{
if (foundLeftCut)//undercutX == 0 /*|| (undercutX > 0 && offsetX[0] - undercutX > 100)*/ || tempj_2 < tempj)
{
if (undercutX == undercutX0)
FanghanUndercutForMeiKaiKou_ACC(gray, tonghouY, b, offsetX, LPIHouY, out undercutX, tempRange, undercutXOld, thresholdValue01/*thresholdValue0*//* + 5*//*, ++i*/);
//else
// FanghanUndercutForMeiKaiKou_ACC(gray, tonghouY, b, offsetX, LPIHouY, out undercutX, undercutX, thresholdValue01/*thresholdValue0*/ + 5/*, ++i*/);
else
{
//安全距離
////undercutX[1] = offsetX[0];
//int[] anquanjuliX = { b[1], undercutX[0] < undercutX[1] ? undercutX[0] : undercutX[1] };
undercutX -= 5;// 1;// 5;
int[] anquanjuliX = { b[1], undercutX < offsetX[0] ? undercutX : offsetX[0] };
if (offsetX[0] - undercutX > anquanjuliX[1] - anquanjuliX[0])
undercutX = undercutXOld - 25;// 5;//严重安全距离不能过长
}
}
else
{
if (thresholdValue01 < 100)
FanghanUndercutForMeiKaiKou_ACC(gray, tonghouY, b, offsetX, LPIHouY, out undercutX, undercutX, undercutXOld, thresholdValue01/*thresholdValue0*/ + 5/*, ++i*/);
else
{
//安全距離
////undercutX[1] = offsetX[0];
//int[] anquanjuliX = { b[1], undercutX[0] < undercutX[1] ? undercutX[0] : undercutX[1] };
undercutX -= 5;// 1;// 5;
int[] anquanjuliX = { b[1], undercutX < offsetX[0] ? undercutX : offsetX[0] };
if (offsetX[0] - undercutX > anquanjuliX[1] - anquanjuliX[0])
undercutX = undercutXOld - 5;//严重安全距离不能过长
}
//undercutX = (undercutX + tempj) / 2 - 5;
}
}
Cv2.Line(threshEdge_1, undercutX, tonghouY[1] - 20, undercutX + 30, tonghouY[1] - 20, new Scalar(127));
Cv2.Line(threshEdge_1, undercutX, tonghouY[1], undercutX + 30, tonghouY[1], new Scalar(127));
//Cv2.Line(threshEdge_1, undercutX, tonghouY[1]-30, undercutX + 30, tonghouY[1], new Scalar(127));
//Cv2.Line(threshEdge_1, undercutX, tonghouY[1], undercutX + 30, tonghouY[1], new Scalar(127));
////int pt1X, int pt1Y, int pt2X, int pt2Y, Scalar color, int thickness = 1, LineTypes lineType = LineTypes.Link8, int shift = 0)
//Cv2.ImWrite(@"C:\Users\54434\Desktop\gray3.png", threshEdge_1);
}
#endregion
#region 开口
///
/// 防焊 有开口 铜厚
///
///
///
///
///
public void FanghanTonghouForYouKaiKou_Acc(Mat gray, int tonghouX, out int tonghouY0, int[] y/*, out int[] y, out int[] b*/)
{
////y = new int[2];
////b = new int[4];
tonghouY0 = 0;// new int[2];
Mat contour = new Mat();
double T = 0;
double t = Cv2.Threshold(gray, contour, 0, 255, ThresholdTypes.Otsu);
Mat seClose = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(15, 15));
Mat close = new Mat();
Cv2.MorphologyEx(contour, close, MorphTypes.Close, seClose);
Mat result = close.Clone();
result = result / 255;
////计算铜厚
//int tonghouX = b[1] - 150;
Mat thresh = gray.Threshold(0, 1, ThresholdTypes.Otsu);
for (int i = y[0]; i < y[1]; i++)
{
Scalar sum = thresh[i, i + 1, tonghouX - 30, tonghouX + 30].Sum();
if ((int)sum > 30)
{
tonghouY0 = i;
break;
}
}
//contour = contour / 255;
//for (int i = tonghouY[0] + 30; i < contour.Rows; i++)
//{
// Scalar sum = contour[i, i + 1, tonghouX - 30, tonghouX + 30].Sum();
// if ((int)sum == 0)
// {
// tonghouY[1] = i;
// break;
// }
//}
}
///
/// 防焊 有开口 铜厚
///
///
///
///
///
public void FanghanTonghouForYouKaiKou(Mat gray, out int[] tonghouY, out int[] y, out int[] b)
{
y = new int[2];
b = new int[4];
tonghouY = new int[2];
Mat contour = new Mat();
double T = 0;
double t = Cv2.Threshold(gray, contour, 0, 255, ThresholdTypes.Otsu);
Mat seClose = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(15, 15));
Mat close = new Mat();
Cv2.MorphologyEx(contour, close, MorphTypes.Close, seClose);
Mat result = close.Clone();
result = result / 255;
//ImageShow(result * 255);
//计算边界
Scalar sum = new Scalar(0);
for (int i = 0; i < result.Rows; i++)
{
sum = result[i, i + 1, 0, result.Cols].Sum();
if ((int)sum > 200)
{
y[0] = i - 20;
break;
}
}
for (int i = y[0] + 50; i < result.Rows; i++)
{
sum = result[i, i + 1, 0, result.Cols].Sum();
if ((int)sum == 0)
{
y[1] = i;
break;
}
}
for (int j = 0; j < result.Cols; j++)
{
sum = result[y[0], y[1], j, j + 1].Sum();
if ((int)sum > 20)
{
b[0] = j;
break;
}
}
for (int j = b[0] + 200; j < result.Cols; j++)
{
sum = result[y[0], y[1], j, j + 1].Sum();
if ((int)sum == 0)
{
b[1] = j;
break;
}
}
for (int j = b[1] + 10; j < result.Cols; j++)
{
sum = result[y[0], y[1], j, j + 1].Sum();
if ((int)sum > 20)
{
b[2] = j;
break;
}
}
if (b[2] - b[1] < 300)
{
for (int j = b[2] + 50; j < result.Cols; j++)
{
sum = result[y[0], y[1], j, j + 1].Sum();
if ((int)sum == 0)
{
b[1] = j;
break;
}
}
for (int j = b[1] + 10; j < result.Cols; j++)
{
sum = result[y[0], y[1], j, j + 1].Sum();
if ((int)sum > 20)
{
b[2] = j;
break;
}
}
}
for (int j = b[2] + 50; j < result.Cols; j++)
{
sum = result[y[0], y[1], j, j + 1].Sum();
if ((int)sum == 0)
{
b[3] = j;
break;
}
}
if (b[3] == 0)
b[3] = contour.Cols - 1;
//计算铜厚
int tonghouX = b[1] - 150;
Mat thresh = gray.Threshold(0, 1, ThresholdTypes.Otsu);
for (int i = y[0]; i < y[1]; i++)
{
sum = thresh[i, i + 1, tonghouX - 30, tonghouX + 30].Sum();
if ((int)sum > 30)
{
tonghouY[0] = i;
break;
}
}
contour = contour / 255;
for (int i = tonghouY[0] + 30; i < contour.Rows; i++)
{
sum = contour[i, i + 1, tonghouX - 30, tonghouX + 30].Sum();
if ((int)sum == 0)
{
tonghouY[1] = i;
break;
}
}
}
///
/// 防焊 有开口 厚度
///
///
///
///
///
///
///
public void FanghanhouduForYouKaiKou_2(Mat gray, int[] y, int fanghanhouduX, int[] tonghouY, out int fanghanhouduY1, out int minGray, bool isLeft)
{
int fanghanhouduY_0 = tonghouY[0];
int fanghanX1 = Math.Max(0, fanghanhouduX - 150);
int fanghanX2 = Math.Min(gray.Cols - 1, fanghanhouduX + 150);
int fanghanTop = fanghanhouduY_0 - 150/*100*/;
int marginTop = 150;
if (fanghanTop < 0)
{
fanghanTop = 0;
marginTop = fanghanhouduY_0 - 1;
}
Mat grayRect = gray[fanghanTop, fanghanhouduY_0 - 50, fanghanX1, fanghanX2];
FanghanhouduForYouKaiKou/*_00*/(grayRect/*gray*/, y, marginTop/*150*//*fanghanhouduX*/, tonghouY, out fanghanhouduY1, out minGray);
int fanghanhouduY1__2 = fanghanhouduY1;
int minGray__2 = minGray;
fanghanX1 += 140;// 145;
fanghanX2 -= 140;// 145;
grayRect = gray[fanghanTop, fanghanhouduY_0 - 20/*50*/, fanghanX1, fanghanX2];
int fanghanhouduY1__2_bottom;
FanghanhouduForYouKaiKou_ACC(grayRect, y, marginTop, fanghanhouduY1 - (isLeft ? 8/*5*/ : 1), out fanghanhouduY1__2, out fanghanhouduY1__2_bottom, out minGray__2);
if (true && (Math.Abs(fanghanhouduY1 - fanghanhouduY1__2) < 16/*11*//*<-10*//*20*//*10*/
|| (!isLeft && Math.Abs(fanghanhouduY1 - fanghanhouduY1__2) < 25/*20*/)))
fanghanhouduY1 = fanghanhouduY1__2/*fanghanhouduY1__2_bottom*//*fanghanhouduY1__2*/ + fanghanTop;// +5;
else
fanghanhouduY1 = fanghanhouduY1 + fanghanTop;
}
///
/// 防焊 有开口 厚度 精确计算
///
///
///
///
///
///
///
private void FanghanhouduForYouKaiKou_ACC(Mat gray, int[] y, int fanghanhouduX, int fanghanhouduY1__0, out int fanghanhouduY1, out int fanghanhouduY1Bottom, out int minGray, int a = 0)
{
minGray = 300 * 255;
int fanghanhouduY1__noSharp = -1;// fanghanhouduY1;
{
int minRowIndex = 0; int colEnd = gray.Cols - 1; int curGray; List curGrayList = new List();
fanghanhouduY1Bottom = 0;
for (int i = Math.Max(0, fanghanhouduY1__0 - 0/*1*//*5*//*10*/); i < Math.Min(fanghanhouduY1__0 + 30/*25*/, gray.Rows) - 5; i++)
{
curGray = this.FanghanhouduForAreaMin(gray, i);// (int)thresh[i - 1, i, 0, colEnd].Sum().Val0;
curGrayList.Add(curGray);
if (curGray < minGray)
{
minRowIndex = i;
fanghanhouduY1Bottom = i;
minGray = curGray;
}
}
for (int i = minRowIndex - Math.Max(0, fanghanhouduY1__0 - 0/*1*//*5*//*10*/) + 2; i < curGrayList.Count; i += 2)
{
if (Math.Abs(curGrayList[i] - minGray) < 10/*100*/)
{
minRowIndex += 1;
fanghanhouduY1Bottom += 2;
}
}
fanghanhouduY1__noSharp = minRowIndex;// 84;// 72;// minRowIndex;
}
{
//锐化
//Mat left_small_sharp = BinaryTools.BlurMaskFunction(left_small).CvtColor(ColorConversionCodes.BGRA2GRAY);
gray = BinaryTools.BlurMaskFunction(gray/*grayRect*/, 4f * 3.14f, 1, 10f).CvtColor(ColorConversionCodes.BGRA2GRAY);
int minRowIndex = 0; int colEnd = gray.Cols - 1; int curGray; List curGrayList = new List();
fanghanhouduY1Bottom = 0;
for (int i = Math.Max(0, fanghanhouduY1__0 - 0/*1*//*5*//*10*/); i < Math.Min(fanghanhouduY1__0 + 30/*25*/, gray.Rows) - 5; i++)
{
curGray = this.FanghanhouduForAreaMin(gray, i);// (int)thresh[i - 1, i, 0, colEnd].Sum().Val0;
curGrayList.Add(curGray);
if (curGray < minGray)
{
minRowIndex = i;
fanghanhouduY1Bottom = i;
minGray = curGray;
}
}
for (int i = minRowIndex - Math.Max(0, fanghanhouduY1__0 - 0/*1*//*5*//*10*/) + 2; i < curGrayList.Count; i += 2)
{
if (Math.Abs(curGrayList[i] - minGray) < 10/*100*/)
{
minRowIndex += 1;
fanghanhouduY1Bottom += 2;
}
}
//Console.WriteLine("fanghanhouduY1_1:" + minRowIndex);
////Cv2.ImWrite(@"C:\Users\54434\Desktop\thres_3.png", gray);
fanghanhouduY1 = minRowIndex;// 84;// 72;// minRowIndex;
}
if (Math.Abs(fanghanhouduY1__noSharp - fanghanhouduY1) < 7/* <<7 8*//* << 6 *//*5*/)
{
fanghanhouduY1 = fanghanhouduY1__noSharp;
}
else
Console.WriteLine("fanghanhouduY1 far away from fanghanhouduY1__noSharp.");
}
///
/// 防焊 有开口 厚度
///
///
///
///
///
///
///
private void FanghanhouduForYouKaiKou_00(Mat gray, int[] y, int fanghanhouduX, int[] tonghouY, out int fanghanhouduY1, out int minGray, int a = 0)
{
/*int fanghanhouduX = 150; */
fanghanhouduY1 = -1;
Mat thresh = gray.Threshold(BinaryTools.CalcSuitableValue(gray) - 10 + (a * 5), 255, ThresholdTypes.Binary);
//Cv2.ImWrite(@"C:\Users\54434\Desktop\thres_3.png", thresh);
for (int i = 0; i < 100; i++)
{
if (thresh.At(i, fanghanhouduX) == 0 && Cv2.FloodFill(thresh, new Point(fanghanhouduX, i), new Scalar(255)) > 300)
{
fanghanhouduY1 = i;
break;
}
}
minGray = 300 * 255;
if (fanghanhouduY1 == -1)
FanghanhouduForYouKaiKou_00(gray, y, fanghanhouduX, tonghouY, out fanghanhouduY1, out minGray, ++a);
//else
//{//计算数值的地方
// //Console.WriteLine("fanghanhouduY1_0:" + fanghanhouduY1);
// /*int minGray = 300*255; */
// int minRowIndex = 0; int colEnd = thresh.Cols - 1; int curGray;
// for (int i = 6/*1*/; i < 95; i++)
// {
// curGray = this.FanghanhouduForAreaMin(gray, i);// (int)thresh[i - 1, i, 0, colEnd].Sum().Val0;
// if (curGray < minGray)
// {
// minRowIndex = i;
// minGray = curGray;
// }
// }
// //Console.WriteLine("fanghanhouduY1_1:" + minRowIndex);
// ////Cv2.ImWrite(@"C:\Users\54434\Desktop\thres_3.png", gray);
// fanghanhouduY1 = minRowIndex;
//}
}
///
/// 防焊 有开口 厚度
///
///
///
///
///
///
///
private void FanghanhouduForYouKaiKou(Mat gray, int[] y, int fanghanhouduX, int[] tonghouY, out int fanghanhouduY1, out int minGray, int a = 0)
{
/*int fanghanhouduX = 150; */fanghanhouduY1 = -1;
//Mat thresh = gray.Threshold(BinaryTools.CalcSuitableValue(gray) - 10 + (a * 5), 255, ThresholdTypes.Binary);
////Cv2.ImWrite(@"C:\Users\54434\Desktop\thres_3.png", thresh);
//for (int i = 0; i < 100; i++)
//{
// if (thresh.At(i, fanghanhouduX) == 0 && Cv2.FloodFill(thresh, new Point(fanghanhouduX, i), new Scalar(255)) > 300)
// {
// fanghanhouduY1 = i;
// break;
// }
//}
minGray = 300 * 255;
//if (fanghanhouduY1 == -1)
// FanghanhouduForYouKaiKou(gray, y, fanghanhouduX, tonghouY, out fanghanhouduY1, out minGray, ++a);
//else
{//计算数值的地方
//Console.WriteLine("fanghanhouduY1_0:" + fanghanhouduY1);
/*int minGray = 300*255; */int minRowIndex = 0; int colEnd = gray.Cols - 1; int curGray;
for (int i = 6/*1*/; i < 95; i++)
{
curGray = this.FanghanhouduForAreaMin(gray, i);// (int)thresh[i - 1, i, 0, colEnd].Sum().Val0;
if (curGray < minGray)
{
minRowIndex = i;
minGray = curGray;
}
}
//Console.WriteLine("fanghanhouduY1_1:" + minRowIndex);
////Cv2.ImWrite(@"C:\Users\54434\Desktop\thres_3.png", gray);
fanghanhouduY1 = minRowIndex;
}
}
///
/// 获取灰度值最低的一条横线
///
///
///
public void FanghanhouduRightForYouKaiKou(Mat gray, out int fanghanhouduY1)
{//计算数值的地方
int minGray = gray.Cols/*300*/ * 255;
int minRowIndex = 0; int colEnd = gray.Cols - 1; int curGray;
for (int i = /*6*/6; i < 95; i++)
{
curGray = this.FanghanhouduForAreaMin(gray, i);// (int)thresh[i - 1, i, 0, colEnd].Sum().Val0;
if (curGray < minGray)
{
minRowIndex = i;
minGray = curGray;
}
}
fanghanhouduY1 = minRowIndex;
}
//获取当前行附件最暗的总和
private int FanghanhouduForAreaMin(Mat gray, int rowIndex)
{
int areaMin = 0;
for (int i = 0; i < gray.Cols; i++)
{
int colMin = 255;
for (int j = rowIndex - 5/*Math.Max(0, rowIndex - 5)*/; j < rowIndex + 5; j++)
if (gray.At(j, i) < colMin) colMin = gray.At(j, i);
areaMin += colMin;
}
return areaMin;
}
///
/// 防焊 有开口 offset
///
///
///
///
///
///
///
public void FanghanOffsetForYouKaiKou_Acc(Mat gray0, int[] tonghouY, int[] b, int[] fanghanhouY, int offsetY, int offsetX0_0, out int offsetX0)
{
int offsetY1 = Math.Max(0, fanghanhouY[1] - 50);
int offsetY2 = Math.Min(gray0.Rows - 1, tonghouY[1] + 50);
int offsetLeft = b[1] + 5;
Mat gray = gray0[offsetY1, offsetY2, offsetLeft, b[2] - 5];
int colStart = offsetX0_0 - 10 - offsetLeft;
int colEnd = offsetX0_0 + 20/*10*/ - offsetLeft;
int minGray = 300 * 255; int minColIndex = 0; int rowStart = offsetY - 10 - offsetY1; int rowEnd = offsetY + 10 - offsetY1;
List curgrayList = new List();
List minareaList_k = new List();
List minareaList_v = new List();
for (int i = colStart; i < colEnd; i++)
{
curgrayList.Add(this.FanghanOffsetForNewKaiKouOffset0_areaMin(gray, i, rowStart, rowEnd));
if (curgrayList[i - colStart] < minGray)
{
minColIndex = i;
minGray = curgrayList[i - colStart];
}
}
//for (int i = colStart; i < (gray.Cols + colStart) / 2; i++)
//{
// if (i > colStart + 10 && i < (gray.Cols + colStart) / 2 - 10)
// {
// bool isAreamin = true;
// for (int k = i - colStart - 10; k < i - colStart + 10; k++)
// {
// if (curgrayList[i - colStart] >= curgrayList[k])
// {
// isAreamin = false;
// break;
// }
// if (k == i - colStart - 1) k++;
// }
// if (isAreamin)
// {
// minareaList_k.Add(i);
// minareaList_v.Add(curgrayList[i - colStart]);
// }
// }
//}
////Console.WriteLine("fanghanhouduY1_1:" + minRowIndex);
//////Cv2.ImWrite(@"C:\Users\54434\Desktop\thres_3.png", gray);
////下面为计算极小值,从计算极小值中的序列中选取,替换极大值
////minareaList.Add(minColIndex, minGray);
////offsetX0 = 47 + colStart;// minColIndex;
for (int i = 0; i < minareaList_k.Count; i++)
{
if (Math.Abs(minGray - minareaList_v[i]) < 120)
{
minColIndex = minareaList_k[i];
break;
}
}
offsetX0 = minColIndex;
offsetX0 = offsetX0 + offsetLeft;
}
///
/// 防焊 有开口 offset
///
///
///
///
///
///
///
public void FanghanOffsetForYouKaiKou(Mat gray, int[] tonghouY, int[] b, int[] fanghanhouY, int colStart, out int offsetX0, int i = 0)
{
int offsetY = tonghouY[0] - 50;
int offsetY1 = Math.Max(0, fanghanhouY[1]/*offsetY*/ - 50);
int offsetY2 = Math.Min(gray.Rows - 1, tonghouY[1] + 50);
int offsetLeft = b[1] + 5;
if (offsetLeft >= b[2] - 5)
{
offsetLeft = b[2] - 5 - 1;
}
Mat grayRect = gray[offsetY1, offsetY2, offsetLeft, b[2] - 5];
this.FanghanOffsetForNewKaiKouOffset0(grayRect, colStart, out offsetX0);
offsetX0 = offsetX0 + offsetLeft;
////二值化
//Mat threshEdge = gray.Threshold(BinaryTools.CalcSuitableValue(gray) - 10 + (i * 5), 255, ThresholdTypes.BinaryInv);
////去碎屑
//threshEdge = ~BinaryTools.DebrisRemoval_New(threshEdge.CvtColor(ColorConversionCodes.GRAY2BGRA), 250).CvtColor(ColorConversionCodes.BGRA2GRAY);
//for (int j = b[2] - 55; j > 0; j--)
//{
// if (threshEdge.At(offsetY + 45, j) == 0)
// {
// Mat temp = ~threshEdge;
// if (Cv2.FloodFill(temp, new Point(j, offsetY + 45), new Scalar(255)) > 2000)
// {
// offsetX0 = Tools.GetLeftOrRightPoint(new Point(j, offsetY + 45), threshEdge, 2).X;
// break;
// }
// }
//}
//if (i <20 && (offsetX0 <= 0 || Math.Abs(b[2]/*offsetX_1*/ - offsetX0) > 800))
// FanghanOffsetForYouKaiKou(gray, tonghouY, b, fanghanhouY, out offsetX0, ++i);
}
public void FanghanKaikouForNewKaiKou(Mat gray, int colStart, int colEnd, int fanghankaikouYTopCenter, out int kaikouX1)
{//计算数值的地方
////Console.WriteLine("fanghanhouduY1_0:" + fanghanhouduY1);
// offsetX0 = -1;
//Cv2.ImWrite(@"C:\Users\54434\Desktop\gray.png", gray);
int minGray = (colEnd-colStart)/*300*/ * 255; int minColIndex = 0; int rowStart = Math.Max(fanghankaikouYTopCenter-20,0)/*50*/; int rowEnd = Math.Min(fanghankaikouYTopCenter+80, gray.Rows-1)/*130*//*gray.Rows - 50*/;// int curGray;
List curgrayList = new List();
List minareaList_k = new List();
List minareaList_v = new List();
for (int i = colEnd/*(gray.Cols + colStart) / 2 *//*gray.Cols - 50*/; i > colStart/*6*//*1*/; i--)
//for (int i = colStart/*6*//*1*/; i < colEnd/*(gray.Cols + colStart) / 2 *//*gray.Cols - 50*/; i++)
{
curgrayList.Add(this.FanghanOffsetForNewKaiKouOffset0_areaMin(gray, i, rowStart, rowEnd));
if (curgrayList[colEnd - i/*i - colStart*/] < minGray)
{
minColIndex = i;
minGray = curgrayList[colEnd - i/*i - colStart*/];
}
}
for (int i = colEnd/*(gray.Cols + colStart) / 2*/ /*gray.Cols - 50*/; i > colStart/*6*//*1*/; i--)
{
if (i > colStart + 10 && i < colEnd/*(gray.Cols + colStart) / 2*/ - 10)
{
bool isAreamin = true;
for (int k = colEnd - i/*i - colStart*/ + 10/*10*/; k > colEnd - i/*i - colStart*/ - 10/*10*/; k--)
{
if (curgrayList[colEnd - i/*i - colStart*/] >= curgrayList[k])
{
isAreamin = false;
break;
}
if (k == colEnd - i/*i - colStart*/ + 1) k--;
}
if (isAreamin)
{
minareaList_k.Add(i);
minareaList_v.Add(curgrayList[colEnd - i/*i - colStart*/]);
}
}
}
//Console.WriteLine("fanghanhouduY1_1:" + minRowIndex);
////Cv2.ImWrite(@"C:\Users\54434\Desktop\thres_3.png", gray);
//下面为计算极小值,从计算极小值中的序列中选取,替换极大值
//minareaList.Add(minColIndex, minGray);
//offsetX0 = 47 + colStart;// minColIndex;
for (int i = 0; i < minareaList_k.Count; i++)
{
if (Math.Abs(minGray - minareaList_v[i]) < 300/*120*/)
{
minColIndex = minareaList_k[i];
break;
}
}
kaikouX1 = minColIndex;
//
}
public void FanghanOffsetForNewKaiKouOffset0(Mat gray, int colStart, out int offsetX0)
{//计算数值的地方
////Console.WriteLine("fanghanhouduY1_0:" + fanghanhouduY1);
// offsetX0 = -1;
//Cv2.ImWrite(@"C:\Users\54434\Desktop\gray.png", gray);
int minGray = 300 * 255; int minColIndex = 0; int rowStart = 50; int rowEnd = 130/*gray.Rows - 50*/;// int curGray;
List curgrayList = new List();
List minareaList_k = new List();
List minareaList_v = new List();
for (int i = colStart/*6*//*1*/; i < (gray.Cols+ colStart)/2 /*gray.Cols - 50*/; i++)
{
curgrayList.Add(this.FanghanOffsetForNewKaiKouOffset0_areaMin(gray, i, rowStart, rowEnd));
if (curgrayList[i-colStart] < minGray)
{
minColIndex = i;
minGray = curgrayList[i - colStart];
}
}
for (int i = colStart/*6*//*1*/; i < (gray.Cols + colStart) / 2 /*gray.Cols - 50*/; i++)
{
if (i > colStart + 10 && i < (gray.Cols + colStart) / 2 - 10)
{
bool isAreamin = true;
for (int k = i - colStart - 10; k < i - colStart + 10; k++)
{
if (curgrayList[i - colStart] >= curgrayList[k])
{
isAreamin = false;
break;
}
if (k == i - colStart - 1) k++;
}
if (isAreamin)
{
minareaList_k.Add(i);
minareaList_v.Add(curgrayList[i - colStart]);
}
}
}
//Console.WriteLine("fanghanhouduY1_1:" + minRowIndex);
////Cv2.ImWrite(@"C:\Users\54434\Desktop\thres_3.png", gray);
//下面为计算极小值,从计算极小值中的序列中选取,替换极大值
//minareaList.Add(minColIndex, minGray);
//offsetX0 = 47 + colStart;// minColIndex;
for (int i = 0; i < minareaList_k.Count; i++)
{
if (Math.Abs(minGray- minareaList_v[i]) < 120)
{
minColIndex = minareaList_k[i];
break;
}
}
offsetX0 = minColIndex;
//
}
//获取当前行附件最暗的总和
private int FanghanOffsetForNewKaiKouOffset0_areaMin(Mat gray, int colIndex, int rowStart, int rowEnd)
{
int areaMin = 0;
for (int j = rowStart; j < rowEnd; j++)
{
int colMin = 255;
for (int i = colIndex - 5; i < colIndex + 5; i++)
if (gray.At(j, i) < colMin) colMin = gray.At(j, i);
areaMin += colMin;
}
return areaMin;
}
///
/// 找轮廓的最左、最右点
///
///
///
/// 1左 2右
///
public OpenCvSharp.Point GetLeftOrRightPoint(OpenCvSharp.Point temp, Mat mat, int type)
{
Rect rect = new Rect();
Mat mask = Mat.Zeros(mat.Rows + 2, mat.Cols + 2, MatType.CV_8UC1);
Cv2.FloodFill(mat, mask, temp, new Scalar(255), out rect, null, null, FloodFillFlags.Link8);
mask = mask * 255;
//Cv2.ImWrite(@"C:\Users\54434\Desktop\mask.png", mask);
List points = new List