using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using OpenCvSharp; using System.Collections; namespace ceju { class Classification { public static void Qianmangkong(string fileName) { //获取图片 Mat image = new Mat(fileName, ImreadModes.Color); //获取图片的长宽 int rows = image.Rows; int cols = image.Cols; //将图片转换为灰度图片 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); //获取图片的通道数 int channels = image.Channels(); //获得蓝色,绿色,红色通道图片 Mat imageBlue,imageGreen,imageRed = new Mat(imageGray.Size(), imageGray.Type()); SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed); double proportion = 0.2689; /* * 一、 * 1、对图像进行阈值分割,选取目标区域,阈值选取用Otsu方法 * 2、对于一些小的孔洞进行填充(没实现,待定) * 3、进行sobel算子的边缘检测,横纵向边缘的平均 * 4、去掉小面积(没实现,待定) * */ //Otsu阈值分割 Mat imageThresh = imageRed.Threshold(0, 255, ThresholdTypes.Otsu);//最大值调成1的话显示不出来,在转换成数组的时候注意255要变成1 //sobel算子边缘检测 //横向检测 Mat grad_x = new Mat(); Mat grad_x2 = new Mat(); Cv2.Sobel(imageThresh, grad_x, MatType.CV_16S, 1, 0); Cv2.ConvertScaleAbs(grad_x, grad_x2); //纵向检测 Mat grad_y = new Mat(); Mat grad_y2 = new Mat(); Cv2.Sobel(imageThresh, grad_y, MatType.CV_16S, 0, 1); Cv2.ConvertScaleAbs(grad_y, grad_y2); //横纵向混合平均 Mat imageSobel = new Mat(); Cv2.AddWeighted(grad_x2, 0.5, grad_y2, 0.5, 0, imageSobel); //将imageThresh的Mat类转换成数组,并且是0,1二值 //将Mat类中的数组转为数组 int[,] arrayThresh = BasFunction.Mat2Array(imageThresh); //将数组转为0,1数组 arrayThresh = BasFunction.ConversionRange(arrayThresh); //将sobel边缘检测后的轮廓线转为0,1二值 int[,] arraySobel = BasFunction.Mat2Array(imageSobel); arraySobel = BasFunction.ConversionRange(arraySobel); // 二、计算中部区域的边界,middleArea[0]中部左边界,middleArea[1]中部右边界 int[] middleArea = SubFunction.GetMiddleArea(imageThresh); //显示线条 //SubFunction.LineShow(image, middleArea[0], 0, middleArea[0], rows,"red"); //SubFunction.LineShow(image, middleArea[1], 0, middleArea[1], rows,"green"); //new Window("middleArea", WindowMode.Normal, image); //Cv2.WaitKey(0); // 三、计算数据提取区域的边界 //dataArea[0]左部分左边界,dataArea[1]左部分右边界,dataArea[2]右部分左边界,dataArea[3]右部分右边界 int[] dataArea = SubFunction.GetDataArea(imageThresh,middleArea); //叠加线条 //SubFunction.LineShow(image, dataArea[0], 0, dataArea[0], rows,"red"); //SubFunction.LineShow(image, dataArea[1], 0, dataArea[1], rows,"green"); //SubFunction.LineShow(image, dataArea[2], 0, dataArea[2], rows,"blue"); //SubFunction.LineShow(image, dataArea[3], 0, dataArea[3], rows,"red"); //new Window("middleArea", WindowMode.Normal, image); //Cv2.WaitKey(0); // 四、提取L1、L3、L4、L5 //腐蚀结构[1,1,1]; Mat seErode = Cv2.GetStructuringElement(MorphShapes.Rect,new Size(3,1)); //腐蚀 Mat outLine = new Mat();//轮廓线 Cv2.Erode(imageSobel, outLine, seErode); //将轮廓线的腐蚀后转为0,1二值 int[,] arrayOutline = BasFunction.Mat2Array(outLine); arrayOutline = BasFunction.ConversionRange(arrayOutline); //提取线条 //线条L1数组 int[,] line1 = new int[rows, cols]; //L1的纵坐标 double averageCoordinate1 = 0; //得到L1,以及L1的平均纵坐标。 SubFunction.ExtractLines(arraySobel,out line1,out averageCoordinate1, dataArea[0], dataArea[3]); //得到L1左部分,以及平均纵坐标 int[,] lineLeft1 = new int[rows, cols]; double meanOrdinateLeft1 = 0; SubFunction.ExtractLines(arraySobel, out lineLeft1, out meanOrdinateLeft1, dataArea[0], dataArea[1]); //得到L3左部分,以及平均纵坐标 int[,] lineLeft3 = new int[rows, cols]; double meanOrdinateLeft3 = 0; SubFunction.ExtractLines(arraySobel,out lineLeft3, out meanOrdinateLeft3, dataArea[0], dataArea[1], meanOrdinateLeft1); //得到L4左部分,以及平均纵坐标 int[,] lineLeft4 = new int[rows, cols]; double meanOrdinateLeft4 = 0; SubFunction.ExtractLines(arrayOutline, out lineLeft4, out meanOrdinateLeft4, dataArea[0], dataArea[1], meanOrdinateLeft3); //得到L5左部分,以及平均纵坐标 int[,] lineLeft5 = new int[rows, cols]; double meanOrdinateLeft5 = 0; SubFunction.ExtractLines(arrayOutline, out lineLeft5, out meanOrdinateLeft5, dataArea[0], dataArea[1], meanOrdinateLeft4); //得到L1右部分,以及平均纵坐标 int[,] lineRight1 = new int[rows, cols]; double meanOrdinateRight1 = 0; SubFunction.ExtractLines(arraySobel, out lineRight1, out meanOrdinateRight1, dataArea[2], dataArea[3]); //得到L3右部分,以及平均纵坐标 int[,] lineRight3 = new int[rows, cols]; double meanOrdinateRight3 = 0; SubFunction.ExtractLines(arraySobel, out lineRight3, out meanOrdinateRight3, dataArea[2], dataArea[3], meanOrdinateRight1); //得到L4右部分,以及平均纵坐标 int[,] lineRight4 = new int[rows, cols]; double meanOrdinateRight4 = 0; SubFunction.ExtractLines(arrayOutline, out lineRight4, out meanOrdinateRight4, dataArea[2], dataArea[3], meanOrdinateRight3); //得到L5右部分,以及平均纵坐标 int[,] lineRight5 = new int[rows, cols]; double meanOrdinateRight5 = 0; SubFunction.ExtractLines(arrayOutline, out lineRight5, out meanOrdinateRight5, dataArea[2], dataArea[3], meanOrdinateRight4); //显示线条重叠 SubFunction.LineShow(image, dataArea[0], (int)meanOrdinateLeft1, dataArea[1], (int)meanOrdinateLeft1); SubFunction.LineShow(image, dataArea[0], (int)meanOrdinateLeft3, dataArea[1], (int)meanOrdinateLeft3); SubFunction.LineShow(image, dataArea[0], (int)meanOrdinateLeft4, dataArea[1], (int)meanOrdinateLeft4); SubFunction.LineShow(image, dataArea[0], (int)meanOrdinateLeft5, dataArea[1], (int)meanOrdinateLeft5); SubFunction.LineShow(image, dataArea[2], (int)meanOrdinateRight1, dataArea[3], (int)meanOrdinateRight1); SubFunction.LineShow(image, dataArea[2], (int)meanOrdinateRight3, dataArea[3], (int)meanOrdinateRight3); SubFunction.LineShow(image, dataArea[2], (int)meanOrdinateRight4, dataArea[3], (int)meanOrdinateRight4); SubFunction.LineShow(image, dataArea[2], (int)meanOrdinateRight5, dataArea[3], (int)meanOrdinateRight5); //new Window("middleArea", WindowMode.Normal, image); //Cv2.WaitKey(0); //五、求L2 double meanOrdinateLeft2 = 0; double meanOrdinateRight2 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft1 + 10, (int)meanOrdinateLeft3 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft2); SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight1 + 10, (int)meanOrdinateRight3 - 10, dataArea[2], dataArea[3], out meanOrdinateRight2); //七、孔铜 //得到孔径起止点 //aperture[0]孔径起始点(左);aperture[1]孔径起始点(右) int[] aperture = new int[2]; SubFunction.GetAperture(arrayThresh,out aperture, (int)meanOrdinateLeft3, (int)meanOrdinateRight3, middleArea, dataArea); int[] apertureBegin = { (int)meanOrdinateLeft3, aperture[0] }; int[] apertureEnd = { (int)meanOrdinateRight3, aperture[1] }; //孔径中点 double middleAperture = (aperture[0] + aperture[1]) / 2; //求孔径起始点与曲面之间的最短距离,以及最短距离时的曲面坐标 double[] kongtong = new double[2]; int[] pointLeft = new int[2]; int[] pointRight = new int[2]; SubFunction.GetKongtong(line1, apertureBegin, apertureEnd, out kongtong,out pointLeft,out pointRight); //九、下孔径 int[] apertureLow = new int[2]; SubFunction.GetAperture(arrayThresh, out apertureLow, (int)meanOrdinateLeft4, (int)meanOrdinateRight4, middleArea, dataArea); //十、孔底与孔深 //提取曲面最凸点坐标 int[] curveVertex = new int[2]; //孔径平均高度 double middleApertureY; SubFunction.CurveVertex(line1, apertureBegin, apertureEnd, out curveVertex,out middleApertureY); //六、求L6 double t1 = 0; double t2 = 0; double meanOrdinateL6 = 0; BasFunction.ChooseSize(meanOrdinateLeft4, meanOrdinateRight4, "small", out t1); BasFunction.ChooseSize(meanOrdinateLeft5, meanOrdinateRight5, "small", out t2); SubFunction.InsideLine(imageGreen, (int)t1 - 10, (int)meanOrdinateLeft5-10, (int)middleAperture - 90, (int)middleAperture + 90,out meanOrdinateL6); //int[,] arrayIrg = new int[rows, cols]; // 十一、数据计算 double leftMiantong = meanOrdinateLeft2 - meanOrdinateLeft1; double rightMiantong = meanOrdinateRight2 - meanOrdinateRight1; double leftJicaitong = meanOrdinateLeft3 - meanOrdinateLeft2; double rightJicaitong = meanOrdinateRight3 - meanOrdinateRight2; double leftMian_Jicaitong = meanOrdinateLeft3 - meanOrdinateLeft1; double rightMian_Jicaitong = meanOrdinateRight3 - meanOrdinateRight1; double shangKongjing = aperture[1] - aperture[0]; double xiaKongjing = apertureLow[1] - aperture[0]; double leftKongtong = kongtong[0]; double rightKongtong = kongtong[1]; double averAperture = (apertureBegin[0] + apertureEnd[1]) / 2; //double kongshen = curveVertex[0]-middleApertureY; double kongdi = meanOrdinateL6 - curveVertex[0]; double leftKongdiyaoshiliang = meanOrdinateL6 - meanOrdinateLeft4; double rightKongdiyaoshiliang = meanOrdinateL6 - meanOrdinateRight4; // 十二、数据显示 double middleLeft = (dataArea[0] + dataArea[1]) / 2; double middleRight = (dataArea[2] + dataArea[3]) / 2; //左面铜标注 SubFunction.LineShow(image, (int)middleLeft - 20, (int)meanOrdinateLeft1, (int)middleLeft - 20, (int)meanOrdinateLeft2, "blue"); SubFunction.LineShow(image, (int)middleLeft - 25, (int)meanOrdinateLeft1, (int)middleLeft - 15, (int)meanOrdinateLeft1, "blue"); SubFunction.LineShow(image, (int)middleLeft - 25, (int)meanOrdinateLeft2, (int)middleLeft - 15, (int)meanOrdinateLeft2, "blue"); SubFunction.TextShow(image, leftMiantong * proportion, (int)middleLeft - 20, (int)meanOrdinateLeft2); //右面铜标注 SubFunction.LineShow(image, (int)middleRight + 20, (int)meanOrdinateRight1, (int)middleRight + 20, (int)meanOrdinateRight2, "blue"); SubFunction.LineShow(image, (int)middleRight + 15, (int)meanOrdinateRight1, (int)middleRight + 25, (int)meanOrdinateRight1, "blue"); SubFunction.LineShow(image, (int)middleRight + 15, (int)meanOrdinateRight2, (int)middleRight + 25, (int)meanOrdinateRight2, "blue"); SubFunction.TextShow(image, rightMiantong * proportion, (int)middleRight + 20, (int)meanOrdinateRight2); //左基材铜标注 SubFunction.LineShow(image, (int)middleLeft - 40, (int)meanOrdinateLeft2, (int)middleLeft - 40, (int)meanOrdinateLeft3, "blue"); SubFunction.LineShow(image, (int)middleLeft - 45, (int)meanOrdinateLeft2, (int)middleLeft - 35, (int)meanOrdinateLeft2, "blue"); SubFunction.LineShow(image, (int)middleLeft - 45, (int)meanOrdinateLeft3, (int)middleLeft - 35, (int)meanOrdinateLeft3, "blue"); SubFunction.TextShow(image, leftJicaitong * proportion, (int)middleLeft - 40, (int)meanOrdinateLeft3); //右基材铜标注 SubFunction.LineShow(image, (int)middleRight + 40, (int)meanOrdinateRight2, (int)middleRight + 40, (int)meanOrdinateRight3, "blue"); SubFunction.LineShow(image, (int)middleRight + 35, (int)meanOrdinateRight2, (int)middleRight + 45, (int)meanOrdinateRight2, "blue"); SubFunction.LineShow(image, (int)middleRight + 35, (int)meanOrdinateRight3, (int)middleRight + 45, (int)meanOrdinateRight3, "blue"); SubFunction.TextShow(image, rightJicaitong * proportion, (int)middleRight + 40, (int)meanOrdinateRight3); //左面铜+基材铜标注 SubFunction.LineShow(image, (int)middleLeft, (int)meanOrdinateLeft1, (int)middleLeft, (int)meanOrdinateLeft3, "blue"); SubFunction.LineShow(image, (int)middleLeft - 5, (int)meanOrdinateLeft1, (int)middleLeft + 5, (int)meanOrdinateLeft1, "blue"); SubFunction.LineShow(image, (int)middleLeft - 5, (int)meanOrdinateLeft3, (int)middleLeft + 5, (int)meanOrdinateLeft3, "blue"); SubFunction.TextShow(image, leftMian_Jicaitong*0.2689, (int)middleLeft, (int)meanOrdinateLeft3+50); //右面铜+基材铜标注 SubFunction.LineShow(image, (int)middleRight, (int)meanOrdinateRight1, (int)middleRight, (int)meanOrdinateRight3, "blue"); SubFunction.LineShow(image, (int)middleRight - 5, (int)meanOrdinateRight1, (int)middleRight + 5, (int)meanOrdinateRight1, "blue"); SubFunction.LineShow(image, (int)middleRight - 5, (int)meanOrdinateRight3, (int)middleRight + 5, (int)meanOrdinateRight3, "blue"); SubFunction.TextShow(image, rightMian_Jicaitong * 0.2689, (int)middleRight, (int)meanOrdinateRight3+50); //上孔径标注 SubFunction.LineShow(image, (int)aperture[0], (int)meanOrdinateLeft1 - 20, (int)aperture[1], (int)meanOrdinateLeft1-20, "blue"); SubFunction.LineShow(image, aperture[0], (int)meanOrdinateLeft1 - 25, aperture[0], (int)meanOrdinateLeft1 - 15, "blue"); SubFunction.LineShow(image, aperture[1], (int)meanOrdinateLeft1 - 25, aperture[1], (int)meanOrdinateLeft1 - 15, "blue"); SubFunction.TextShow(image, shangKongjing * 0.2689, (int)middleAperture, (int)meanOrdinateLeft1 - 20); //下孔径标注 SubFunction.LineShow(image, (int)apertureLow[0], (int)meanOrdinateLeft5 - 20, (int)apertureLow[1], (int)meanOrdinateLeft5 - 20, "blue"); SubFunction.LineShow(image, apertureLow[0], (int)meanOrdinateLeft5 - 25, apertureLow[0], (int)meanOrdinateLeft5 - 15, "blue"); SubFunction.LineShow(image, apertureLow[1], (int)meanOrdinateLeft5 - 25, apertureLow[1], (int)meanOrdinateLeft5 - 15, "blue"); SubFunction.TextShow(image, xiaKongjing * 0.2689, (int)(apertureLow[0] + apertureLow[1]) / 2, (int)meanOrdinateLeft5 + 50); //孔铜标注 //左 SubFunction.LineShow(image, (int)aperture[0], (int)meanOrdinateLeft3, pointLeft[1], pointLeft[0], "blue"); SubFunction.LineShow(image, aperture[0] - 5, (int)meanOrdinateLeft3, aperture[0] + 5, (int)meanOrdinateLeft3, "blue"); SubFunction.LineShow(image, pointLeft[1] - 5, pointLeft[0], pointLeft[1] + 5, pointLeft[0], "blue"); SubFunction.TextShow(image, leftKongtong * proportion, aperture[0], (int)meanOrdinateLeft3+20); //右 SubFunction.LineShow(image, aperture[1], (int)meanOrdinateRight3, pointRight[1], pointRight[0], "blue"); SubFunction.LineShow(image, aperture[1] - 5, (int)meanOrdinateRight3, aperture[1] + 5, (int)meanOrdinateRight3, "blue"); SubFunction.LineShow(image, pointRight[1] - 5, pointRight[0], pointRight[1] + 5, pointRight[0], "blue"); SubFunction.TextShow(image, rightKongtong * proportion, aperture[1], (int)meanOrdinateRight3+20); //孔深标注(浅盲孔没有孔深) //SubFunction.LineShow(image, (int)middleAperture, curveVertex[0], (int)middleAperture, (int)middleApertureY, "blue"); //SubFunction.LineShow(image, (int)middleAperture - 5, curveVertex[0], (int)middleAperture + 5, curveVertex[0], "blue"); //SubFunction.LineShow(image, (int)middleAperture - 5, (int)middleApertureY, (int)middleAperture + 5, (int)middleApertureY, "blue"); //SubFunction.TextShow(image, kongshen * proportion, curveVertex[1], curveVertex[0]); //孔底标注 double middlep = (meanOrdinateL6+meanOrdinateLeft1)/2; SubFunction.LineShow(image, curveVertex[1], curveVertex[0], curveVertex[1], (int)meanOrdinateL6, "blue"); SubFunction.LineShow(image, curveVertex[1] - 5, curveVertex[0], curveVertex[1] + 5, curveVertex[0], "blue"); SubFunction.LineShow(image, curveVertex[1] - 5, (int)meanOrdinateL6, curveVertex[1] + 5, (int)meanOrdinateL6, "blue"); SubFunction.TextShow(image, kongdi * proportion, curveVertex[1], (int)middlep); //左孔底咬食量 SubFunction.LineShow(image, (int)middleLeft, (int)meanOrdinateLeft4, (int)middleLeft, (int)meanOrdinateL6, "blue"); SubFunction.LineShow(image, (int)middleLeft - 5, (int)meanOrdinateLeft4, (int)middleLeft + 5, (int)meanOrdinateLeft4, "blue"); SubFunction.LineShow(image, (int)middleLeft - 5, (int)meanOrdinateL6, (int)middleLeft + 5, (int)meanOrdinateL6, "blue"); SubFunction.TextShow(image, leftKongdiyaoshiliang * proportion, (int)middleLeft, (int)meanOrdinateL6); //右孔底咬食量 SubFunction.LineShow(image, (int)middleRight, (int)meanOrdinateRight4, (int)middleRight, (int)meanOrdinateL6, "blue"); SubFunction.LineShow(image, (int)middleRight - 5, (int)meanOrdinateRight4, (int)middleRight + 5, (int)meanOrdinateRight4, "blue"); SubFunction.LineShow(image, (int)middleRight - 5, (int)meanOrdinateL6, (int)middleRight + 5, (int)meanOrdinateL6, "blue"); SubFunction.TextShow(image, rightKongdiyaoshiliang * proportion, (int)middleRight, (int)meanOrdinateL6); //拟合 SubFunction.LineShow(image, apertureLow[0], (int)meanOrdinateL6, apertureLow[1], (int)meanOrdinateL6); SubFunction.LineShow(image, dataArea[0], (int)meanOrdinateLeft2, dataArea[1], (int)meanOrdinateLeft2); SubFunction.LineShow(image, dataArea[2], (int)meanOrdinateRight2, dataArea[3], (int)meanOrdinateRight2); // 保存 //Cv2.ImWrite(@"D:\eshi.jpg",image); // 显示 new Window("demo1", WindowMode.Normal, image); Cv2.WaitKey(0); } public static void ShuangcengShenmangkong(string fileName) { // 获取图片 Mat image = new Mat(fileName, ImreadModes.Color); // 转换为灰度图 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); // 二值化,获得目标区域 Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu); // 转换成数组 int[,] arrayContour = BasFunction.Mat2Array(imageContour); arrayContour = BasFunction.ConversionRange(arrayContour); // 寻找两层分界点 int[] sum = BasFunction.Sum(arrayContour, 2);// 每行求和 int y1 = 0;// 上区域开始 int y2 = 0;// 上区域结束 int y3 = 0;// 下区域结束 int y4 = 0;// 下区域开始 for (int i = 0; i < imageContour.Rows; i++) { if (sum[i] > 0) { y1 = i; break; } } for (int i = imageContour.Rows - 1; i > 0; i--) { if (sum[i] > 0) { y4 = i; break; } } int[] newSum = BasFunction.Intercept(sum, y1, y4); int min = BasFunction.Min(newSum); for (int i = y1; i < y4; i++) { if (sum[i] < min + 50) { y2 = i; break; } } for (int i = y4; i > y2; i--) { if (sum[i] < min + 50) { y3 = i; break; } } int middle = (y2 + y3) / 2;// 分界点 // 分成两份 // 分原图 Mat image1 = new Mat(); Mat image2 = new Mat(); BasFunction.InterceptMat(image, out image1, 0, middle, 0, image.Cols); BasFunction.InterceptMat(image, out image2, middle, image.Rows, 0, image.Cols); // 重新阈值分割 Mat imageContour1 = image1.Threshold(0, 255, ThresholdTypes.Otsu); Mat imageContour2 = image2.Threshold(0, 255, ThresholdTypes.Otsu); // 对分好的图进行边缘检测 Mat imageOutline1 = new Mat(); Mat imageOutline2 = new Mat(); SubFunction.Sobel(imageContour1, out imageOutline1); SubFunction.Sobel(imageContour2, out imageOutline2); // 对下方的图进行180度旋转 Cv2.Flip(imageContour2, imageContour2, FlipMode.X); Cv2.Flip(imageOutline2, imageOutline2, FlipMode.X); // 调用 Mat result1 = new Mat(); Mat result2 = new Mat(); DrawShenmangkong(image, out result1, imageContour1, imageOutline1); DrawShenmangkong2(result1, out result2, imageContour2, imageOutline2,middle); } public static void DancengShenmangkong(string fileName) { // 获取图片 Mat image = new Mat(fileName, ImreadModes.Color); // 转换为灰度图 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); // 二值化,获得目标区域 Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu); // 闭运算,填充孔洞 Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5)); Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se); // 边缘检测 Mat imageOutline = new Mat(); SubFunction.Sobel(imageContour, out imageOutline); // 调用计算程序 Mat result = new Mat(); DrawShenmangkong(image, out result, imageContour, imageOutline); } public static void DrawShenmangkong(Mat image, out Mat result,Mat imageContour,Mat imageOutline) { // 一、预处理部分 // 像素实际比例 double proportion = 0.2689; // 得到行列数 int rows = image.Rows; int cols = image.Cols; // 转换成灰度图 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); // 获得蓝色,绿色,红色通道图片 Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type()); SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed); // 将Mat类转换成数组 int[,] arrayOutline = BasFunction.Mat2Array(imageOutline); arrayOutline = BasFunction.ConversionRange(arrayOutline);//将数组转为0,1数组 int[,] arrayContour = BasFunction.Mat2Array(imageContour); arrayContour = BasFunction.ConversionRange(arrayContour); // 二、计算中部区域的边界,middleArea[0]中部左边界,middleArea[1]中部右边界 int[] middleArea = SubFunction.GetMiddleArea(imageContour); // 三、计算左右边界 //dataArea[0]左部分左边界,dataArea[1]左部分右边界,dataArea[2]右部分左边界,dataArea[3]右部分右边界 int[] dataArea = SubFunction.GetDataArea(imageContour, middleArea); // 四、提取L1,L3 double meanOrdinateLeft1 = 0;// L1左部分纵坐标 SubFunction.ExtractLines(arrayOutline, out meanOrdinateLeft1, dataArea[0], dataArea[1]); double meanOrdinateRight1 = 0;// L1右部分纵坐标 SubFunction.ExtractLines(arrayOutline, out meanOrdinateRight1, dataArea[2], dataArea[3]); double meanOrdinateLeft3 = 0;// L3左部分纵坐标 SubFunction.ExtractLines(arrayOutline, out meanOrdinateLeft3, dataArea[0], dataArea[1], meanOrdinateLeft1); double meanOrdinateRight3 = 0;// L3右部分纵坐标 SubFunction.ExtractLines(arrayOutline, out meanOrdinateRight3, dataArea[2], dataArea[3], meanOrdinateRight1); // 五、提取内部线L2 double meanOrdinateLeft2 = 0; double meanOrdinateRight2 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft1 + 10, (int)meanOrdinateLeft3 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft2); SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight1 + 10, (int)meanOrdinateRight3 - 10, dataArea[2], dataArea[3], out meanOrdinateRight2); // 六、提取L5,L6 // 对轮廓线腐蚀 Mat seErode = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 1));// 结构元素 Mat imageOutlineErode = new Mat();// 腐蚀后轮廓线 Cv2.Erode(imageOutline, imageOutlineErode, seErode);// 腐蚀 // 转换成数组 int[,] arrayOutlineErode = BasFunction.Mat2Array(imageOutlineErode);// 将Mat类转换成数组 arrayOutlineErode = BasFunction.ConversionRange(arrayOutlineErode);//将数组转为0,1数组 // 提取 double meanOrdinateLeft5 = 0;// L5左部分 SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateLeft5, dataArea[0], dataArea[1]-50,meanOrdinateLeft3); double meanOrdinateRight5 = 0;// L5右部分 SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateRight5, dataArea[2]+50, dataArea[3], meanOrdinateRight3); double meanOrdinateLeft6 = 0;// L6左部分 SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateLeft6, dataArea[0], dataArea[1], meanOrdinateLeft5); double meanOrdinateRight6 = 0;// L6右部分 SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateRight6, dataArea[2], dataArea[3], meanOrdinateRight5); // 七、提取胶体线 Mat glue = new Mat(); SubFunction.GlueArea(imageContour, imageRed, out glue, (int)meanOrdinateLeft3, (int)meanOrdinateLeft5,0,cols); // 转为数组 int[,] arrayGlue = BasFunction.Mat2Array(glue); arrayGlue = BasFunction.ConversionRange(arrayGlue); // 八、提取L4 double meanOrdinateLeft4 = 0;// L4左部分 SubFunction.ExtractLines2(arrayGlue, out meanOrdinateLeft4, dataArea[0], dataArea[1]-50, meanOrdinateLeft5); double meanOrdinateRight4 = 0;// L4左部分 SubFunction.ExtractLines2(arrayGlue, out meanOrdinateRight4, dataArea[2]+50, dataArea[3] , meanOrdinateRight5); // 九、计算孔径起止点 //aperture[0]孔径起始点(左);aperture[1]孔径起始点(右) int[] aperture = new int[2]; SubFunction.GetAperture(arrayContour, out aperture, (int)meanOrdinateLeft3, (int)meanOrdinateRight3, middleArea, dataArea); int[] apertureBegin = { (int)meanOrdinateLeft3, aperture[0] };// 孔径左边左边 int[] apertureEnd = { (int)meanOrdinateRight3, aperture[1] };// 孔径右边左边 double middleAperture = (aperture[0] + aperture[1]) / 2;//孔径中点 // 十、计算孔铜 // 得到曲面线条L1 int[,] line1 = new int[rows, cols]; double averageCoordinate1 = 0;//L1的纵坐标 SubFunction.ExtractLines(arrayOutline, out line1, out averageCoordinate1, dataArea[0], dataArea[3]); //求孔径起始点与曲面之间的最短距离,以及最短距离时的曲面坐标 double[] kongtong = new double[2]; int[] pointLeft = new int[2]; int[] pointRight = new int[2]; SubFunction.GetKongtong(line1, apertureBegin, apertureEnd, out kongtong, out pointLeft, out pointRight); // 十一、计算胶内缩 // 上胶边界 int[] upperWaist = new int[2]; SubFunction.GetWaist(imageContour, out upperWaist, (int)meanOrdinateLeft4 - 30, (int)meanOrdinateLeft4 + 30, (int)middleAperture); // 下胶边界 int[] lowerWaist = new int[2]; SubFunction.GetLowerWaist(imageContour, out lowerWaist, (int)meanOrdinateLeft4, (int)meanOrdinateLeft5, dataArea); // 十二 、提取L7 double meanOrdinateL7 = 0; double t1 = 0; BasFunction.ChooseSize(meanOrdinateLeft5, meanOrdinateRight5, "small",out t1); SubFunction.InsideLine(imageGreen, (int)t1 - 10, (int)meanOrdinateLeft6 - 10, (int)middleAperture - 90, (int)middleAperture + 90, out meanOrdinateL7); // 十三、下孔径(这里用的是和上孔径一样的行数,但是上下边界的问题可能会有,需要注意) int[] lowerAperture = new int[2]; SubFunction.GetAperture(arrayContour, out lowerAperture, (int)meanOrdinateLeft5, (int)meanOrdinateRight5, middleArea, dataArea); // 十四、曲面最凸点坐标 int[] curveVertex = new int[2]; double middleApertureY;//孔径平均高度 SubFunction.CurveVertex(line1, apertureBegin, apertureEnd, out curveVertex, out middleApertureY); // 十五、计算 double leftMiantong = meanOrdinateLeft2 - meanOrdinateLeft1; double rightMiantong = meanOrdinateRight2 - meanOrdinateRight1; double leftJicaitong = meanOrdinateLeft3 - meanOrdinateLeft2; double rightJicaitong = meanOrdinateRight3 - meanOrdinateRight2; double leftMian_Jicaitong = meanOrdinateLeft3 - meanOrdinateLeft1; double rightMian_Jicaitong = meanOrdinateRight3 - meanOrdinateRight1; double leftJiaohou = meanOrdinateLeft5 - meanOrdinateLeft4; double rightJiaohou = meanOrdinateRight5 - meanOrdinateRight4; double leftKongdiyaoshiliang = meanOrdinateL7 - meanOrdinateLeft5; double rightKongdiyaoshiliang = meanOrdinateL7 - meanOrdinateRight5; double leftJiaoneisuo = upperWaist[0] - lowerWaist[0]; double rightJiaoneisuo = lowerWaist[1] - upperWaist[1]; double leftKongtong = kongtong[0]; double rightKongtong = kongtong[1]; double upperKongjing = aperture[1] - aperture[0]; double lowerKongjing = lowerAperture[1] - lowerAperture[0]; double kongshen = curveVertex[0] - middleApertureY; double kongdi = meanOrdinateL7 - curveVertex[0]; // 十六、标记 double middleLeft = (dataArea[0] + dataArea[1]) / 2; double middleRight = (dataArea[2] + dataArea[3]) / 2; // 左面铜 SubFunction.LabelVertical(image, (int)middleLeft-20, (int)meanOrdinateLeft1, (int)middleLeft-20, (int)meanOrdinateLeft2, leftMiantong); // 右面铜 SubFunction.LabelVertical(image, (int)middleRight+20, (int)meanOrdinateRight1, (int)middleRight+20, (int)meanOrdinateRight2, rightMiantong); // 左基材铜 SubFunction.LabelVertical(image, (int)middleLeft - 40, (int)meanOrdinateLeft2, (int)middleLeft - 40, (int)meanOrdinateLeft3, leftJicaitong); // 右基材铜 SubFunction.LabelVertical(image, (int)middleRight + 40, (int)meanOrdinateRight2, (int)middleRight + 40, (int)meanOrdinateRight3, rightJicaitong); // 左面铜+基材铜 SubFunction.LabelVertical(image, (int)middleLeft, (int)meanOrdinateLeft1, (int)middleLeft, (int)meanOrdinateLeft3, leftMian_Jicaitong); // 右面铜+基材铜 SubFunction.LabelVertical(image, (int)middleRight, (int)meanOrdinateRight1, (int)middleRight, (int)meanOrdinateRight3, rightMian_Jicaitong); // 左胶厚 SubFunction.LabelVertical(image, (int)middleLeft, (int)meanOrdinateLeft4, (int)middleLeft, (int)meanOrdinateLeft5, leftJiaohou); // 右胶厚 SubFunction.LabelVertical(image, (int)middleRight, (int)meanOrdinateRight4, (int)middleRight, (int)meanOrdinateRight5, rightJiaohou); // 左孔底咬食量 SubFunction.LabelVertical(image, (int)middleLeft, (int)meanOrdinateLeft5, (int)middleLeft, (int)meanOrdinateL7, leftKongdiyaoshiliang); // 右孔底咬食量 SubFunction.LabelVertical(image, (int)middleRight, (int)meanOrdinateRight5, (int)middleRight, (int)meanOrdinateL7, rightKongdiyaoshiliang); // 左胶内缩 SubFunction.LableHorizontal(image, lowerWaist[0], (int)meanOrdinateLeft4, upperWaist[0], (int)meanOrdinateLeft4, leftJiaoneisuo); // 右胶内缩 SubFunction.LableHorizontal(image, upperWaist[1], (int)meanOrdinateRight4, lowerWaist[1], (int)meanOrdinateRight4, rightJiaoneisuo); // 左孔铜 SubFunction.LabelVertical(image, apertureBegin[1], apertureBegin[0], pointLeft[1], pointLeft[0], leftKongtong); // 右孔铜 SubFunction.LabelVertical(image, apertureEnd[1], apertureEnd[0], pointRight[1], pointRight[0], rightKongtong); // 上孔径 SubFunction.LableHorizontal(image, apertureBegin[1], (int)meanOrdinateLeft1 - 30, apertureEnd[1], (int)meanOrdinateLeft1 - 30, upperKongjing); // 下孔径 SubFunction.LableHorizontal(image, lowerAperture[0], (int)meanOrdinateL7 + 20, lowerAperture[1], (int)meanOrdinateL7 + 20, lowerKongjing); // 孔深 SubFunction.LabelVertical(image, curveVertex[1], curveVertex[0], curveVertex[1], (int)middleApertureY, kongshen); // 孔底 SubFunction.LabelVertical(image, curveVertex[1], curveVertex[0], curveVertex[1], (int)meanOrdinateL7, kongdi); result = image; } public static void DrawShenmangkong2(Mat image, out Mat result, Mat imageContour, Mat imageOutline,int middle) { // 一、预处理部分 // 像素实际比例 double proportion = 0.2689; // 得到行列数 int rows = image.Rows; int cols = image.Cols; // 转换成灰度图 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); // 获得蓝色,绿色,红色通道图片 Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type()); SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed); // 将Mat类转换成数组 int[,] arrayOutline = BasFunction.Mat2Array(imageOutline); arrayOutline = BasFunction.ConversionRange(arrayOutline);//将数组转为0,1数组 int[,] arrayContour = BasFunction.Mat2Array(imageContour); arrayContour = BasFunction.ConversionRange(arrayContour); // 二、计算中部区域的边界,middleArea[0]中部左边界,middleArea[1]中部右边界 int[] middleArea = SubFunction.GetMiddleArea(imageContour); // 三、计算左右边界 //dataArea[0]左部分左边界,dataArea[1]左部分右边界,dataArea[2]右部分左边界,dataArea[3]右部分右边界 int[] dataArea = SubFunction.GetDataArea(imageContour, middleArea); // 四、提取L1,L3 double meanOrdinateLeft1 = 0;// L1左部分纵坐标 SubFunction.ExtractLines(arrayOutline, out meanOrdinateLeft1, dataArea[0], dataArea[1]); double meanOrdinateRight1 = 0;// L1右部分纵坐标 SubFunction.ExtractLines(arrayOutline, out meanOrdinateRight1, dataArea[2], dataArea[3]); double meanOrdinateLeft3 = 0;// L3左部分纵坐标 SubFunction.ExtractLines(arrayOutline, out meanOrdinateLeft3, dataArea[0], dataArea[1], meanOrdinateLeft1); double meanOrdinateRight3 = 0;// L3右部分纵坐标 SubFunction.ExtractLines(arrayOutline, out meanOrdinateRight3, dataArea[2], dataArea[3], meanOrdinateRight1); // 五、提取内部线L2 double meanOrdinateLeft2 = 0; double meanOrdinateRight2 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft1 + 10, (int)meanOrdinateLeft3 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft2); SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight1 + 10, (int)meanOrdinateRight3 - 10, dataArea[2], dataArea[3], out meanOrdinateRight2); // 六、提取L5,L6 // 对轮廓线腐蚀 Mat seErode = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 1));// 结构元素 Mat imageOutlineErode = new Mat();// 腐蚀后轮廓线 Cv2.Erode(imageOutline, imageOutlineErode, seErode);// 腐蚀 // 转换成数组 int[,] arrayOutlineErode = BasFunction.Mat2Array(imageOutlineErode);// 将Mat类转换成数组 arrayOutlineErode = BasFunction.ConversionRange(arrayOutlineErode);//将数组转为0,1数组 // 提取 double meanOrdinateLeft5 = 0;// L5左部分 SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateLeft5, dataArea[0], dataArea[1] - 50, meanOrdinateLeft3); double meanOrdinateRight5 = 0;// L5右部分 SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateRight5, dataArea[2] + 50, dataArea[3], meanOrdinateRight3); double meanOrdinateLeft6 = 0;// L6左部分 SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateLeft6, dataArea[0], dataArea[1], meanOrdinateLeft5); double meanOrdinateRight6 = 0;// L6右部分 SubFunction.ExtractLines(arrayOutlineErode, out meanOrdinateRight6, dataArea[2], dataArea[3], meanOrdinateRight5); // 七、提取胶体线 Mat glue = new Mat(); SubFunction.GlueArea(imageContour, imageRed, out glue, (int)meanOrdinateLeft3, (int)meanOrdinateLeft5,0,cols); // 转为数组 int[,] arrayGlue = BasFunction.Mat2Array(glue); arrayGlue = BasFunction.ConversionRange(arrayGlue); // 八、提取L4 double meanOrdinateLeft4 = 0;// L4左部分 SubFunction.ExtractLines2(arrayGlue, out meanOrdinateLeft4, dataArea[0], dataArea[1] - 50, meanOrdinateLeft5); double meanOrdinateRight4 = 0;// L4左部分 SubFunction.ExtractLines2(arrayGlue, out meanOrdinateRight4, dataArea[2] + 50, dataArea[3], meanOrdinateRight5); // 九、计算孔径起止点 //aperture[0]孔径起始点(左);aperture[1]孔径起始点(右) int[] aperture = new int[2]; SubFunction.GetAperture(arrayContour, out aperture, (int)meanOrdinateLeft3, (int)meanOrdinateRight3, middleArea, dataArea); int[] apertureBegin = { (int)meanOrdinateLeft3, aperture[0] };// 孔径左边左边 int[] apertureEnd = { (int)meanOrdinateRight3, aperture[1] };// 孔径右边左边 double middleAperture = (aperture[0] + aperture[1]) / 2;//孔径中点 // 十、计算孔铜 // 得到曲面线条L1 int[,] line1 = new int[rows, cols]; double averageCoordinate1 = 0;//L1的纵坐标 SubFunction.ExtractLines(arrayOutline, out line1, out averageCoordinate1, dataArea[0], dataArea[3]); //求孔径起始点与曲面之间的最短距离,以及最短距离时的曲面坐标 double[] kongtong = new double[2]; int[] pointLeft = new int[2]; int[] pointRight = new int[2]; SubFunction.GetKongtong(line1, apertureBegin, apertureEnd, out kongtong, out pointLeft, out pointRight); // 十一、计算胶内缩 // 上胶边界 int[] upperWaist = new int[2]; SubFunction.GetWaist(imageContour, out upperWaist, (int)meanOrdinateLeft4 - 30, (int)meanOrdinateLeft4 + 30, (int)middleAperture); // 下胶边界 int[] lowerWaist = new int[2]; SubFunction.GetLowerWaist(imageContour, out lowerWaist, (int)meanOrdinateLeft4, (int)meanOrdinateLeft5, dataArea); // 十二 、提取L7 double meanOrdinateL7 = 0; double t1 = 0; BasFunction.ChooseSize(meanOrdinateLeft5, meanOrdinateRight5, "small", out t1); SubFunction.InsideLine(imageGreen, (int)t1 - 10, (int)meanOrdinateLeft6 - 10, (int)middleAperture - 90, (int)middleAperture + 90, out meanOrdinateL7); // 十三、下孔径(这里用的是和上孔径一样的行数,但是上下边界的问题可能会有,需要注意) int[] lowerAperture = new int[2]; SubFunction.GetAperture(arrayContour, out lowerAperture, (int)meanOrdinateLeft5, (int)meanOrdinateRight5, middleArea, dataArea); // 十四、曲面最凸点坐标 int[] curveVertex = new int[2]; double middleApertureY;//孔径平均高度 SubFunction.CurveVertex(line1, apertureBegin, apertureEnd, out curveVertex, out middleApertureY); // 十五、计算 double leftMiantong = meanOrdinateLeft2 - meanOrdinateLeft1; double rightMiantong = meanOrdinateRight2 - meanOrdinateRight1; double leftJicaitong = meanOrdinateLeft3 - meanOrdinateLeft2; double rightJicaitong = meanOrdinateRight3 - meanOrdinateRight2; double leftMian_Jicaitong = meanOrdinateLeft3 - meanOrdinateLeft1; double rightMian_Jicaitong = meanOrdinateRight3 - meanOrdinateRight1; double leftJiaohou = meanOrdinateLeft5 - meanOrdinateLeft4; double rightJiaohou = meanOrdinateRight5 - meanOrdinateRight4; double leftKongdiyaoshiliang = meanOrdinateL7 - meanOrdinateLeft5; double rightKongdiyaoshiliang = meanOrdinateL7 - meanOrdinateRight5; double leftJiaoneisuo = upperWaist[0] - lowerWaist[0]; double rightJiaoneisuo = lowerWaist[1] - upperWaist[1]; double leftKongtong = kongtong[0]; double rightKongtong = kongtong[1]; double upperKongjing = aperture[1] - aperture[0]; double lowerKongjing = lowerAperture[1] - lowerAperture[0]; double kongshen = curveVertex[0] - middleApertureY; double kongdi = meanOrdinateL7 - curveVertex[0]; // 十六、标记 double middleLeft = (dataArea[0] + dataArea[1]) / 2; double middleRight = (dataArea[2] + dataArea[3]) / 2; // 左面铜 SubFunction.LabelVertical(image, (int)middleLeft - 20, (int)(2*middle-meanOrdinateLeft1), (int)middleLeft - 20, (int)(2 * middle - meanOrdinateLeft2), leftMiantong); // 右面铜 SubFunction.LabelVertical(image, (int)middleRight + 20, (int)(2 * middle - meanOrdinateRight1), (int)middleRight + 20, (int)(2 * middle - meanOrdinateRight2), rightMiantong); // 左基材铜 SubFunction.LabelVertical(image, (int)middleLeft - 40, (int)(2 * middle - meanOrdinateLeft2), (int)middleLeft - 40, (int)(2 * middle - meanOrdinateLeft3), leftJicaitong); // 右基材铜 SubFunction.LabelVertical(image, (int)middleRight + 40, (int)(2 * middle - meanOrdinateRight2), (int)middleRight + 40, (int)(2 * middle - meanOrdinateRight3), rightJicaitong); // 左面铜+基材铜 SubFunction.LabelVertical(image, (int)middleLeft, (int)(2 * middle - meanOrdinateLeft1), (int)middleLeft, (int)(2 * middle - meanOrdinateLeft3), leftMian_Jicaitong); // 右面铜+基材铜 SubFunction.LabelVertical(image, (int)middleRight, (int)(2 * middle - meanOrdinateRight1), (int)middleRight, (int)(2 * middle - meanOrdinateRight3), rightMian_Jicaitong); // 左胶厚 SubFunction.LabelVertical(image, (int)middleLeft, (int)(2 * middle - meanOrdinateLeft4), (int)middleLeft, (int)(2 * middle - meanOrdinateLeft5), leftJiaohou); // 右胶厚 SubFunction.LabelVertical(image, (int)middleRight, (int)(2 * middle - meanOrdinateRight4), (int)middleRight, (int)(2 * middle - meanOrdinateRight5), rightJiaohou); // 左孔底咬食量 SubFunction.LabelVertical(image, (int)middleLeft, (int)(2 * middle - meanOrdinateLeft5), (int)middleLeft, (int)(2 * middle - meanOrdinateL7), leftKongdiyaoshiliang); // 右孔底咬食量 SubFunction.LabelVertical(image, (int)middleRight, (int)(2 * middle - meanOrdinateRight5), (int)middleRight, (int)(2 * middle - meanOrdinateL7), rightKongdiyaoshiliang); // 左胶内缩 SubFunction.LableHorizontal(image, lowerWaist[0], (int)(2 * middle - meanOrdinateLeft4), upperWaist[0], (int)(2 * middle - meanOrdinateLeft4), leftJiaoneisuo); // 右胶内缩 SubFunction.LableHorizontal(image, upperWaist[1], (int)(2 * middle - meanOrdinateRight4), lowerWaist[1], (int)(2 * middle - meanOrdinateRight4), rightJiaoneisuo); // 左孔铜 SubFunction.LabelVertical(image, apertureBegin[1], (2 * middle - apertureBegin[0]), pointLeft[1], (2 * middle - pointLeft[0]), leftKongtong); // 右孔铜 SubFunction.LabelVertical(image, apertureEnd[1], (2 * middle - apertureEnd[0]), pointRight[1], (2 * middle - pointRight[0]), rightKongtong); // 上孔径 SubFunction.LableHorizontal(image, apertureBegin[1], (int)(2 * middle - (meanOrdinateLeft1 - 30)), apertureEnd[1], (int)(2 * middle - (meanOrdinateLeft1 - 30)), upperKongjing); // 下孔径 SubFunction.LableHorizontal(image, lowerAperture[0], (int)(2 * middle - (meanOrdinateL7 + 20)), lowerAperture[1], (int)(2 * middle - (meanOrdinateL7 + 20)), lowerKongjing); // 孔深 SubFunction.LabelVertical(image, curveVertex[1], curveVertex[0], curveVertex[1], (int)(2 * middle - middleApertureY), kongshen); // 孔底 SubFunction.LabelVertical(image, curveVertex[1], curveVertex[0], curveVertex[1], (int)(2 * middle - meanOrdinateL7), kongdi); result = image; } public static void CaokongShuangcengYou(string fileName) { // 一、预处理 // 读取图片 Mat image = new Mat(fileName, ImreadModes.Color); //获取图片的长宽 int rows = image.Rows; int cols = image.Cols; // 转换为灰度图 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); //获得蓝色,绿色,红色通道图片 Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type()); SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed); // 二值化,获得目标区域 Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu); // 闭运算,消除小孔 Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素 Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se); // 转成数组 int[,] arrayContour = BasFunction.Mat2Array(imageContour); arrayContour = BasFunction.ConversionRange(arrayContour); // 去亮光 int b2, b3; SubFunction.SplitArea(arrayContour, out b2, out b3); if ((b3 - b2) > 100) { Mat result = new Mat(); BasFunction.SetNumber(imageContour, out result, 0, rows, 0, b3, 0);// 亮光区域置0 imageContour = result; } // 边缘检测 Mat imageOutlint = new Mat(); SubFunction.Sobel(imageContour, out imageOutlint); int[,] arrayOutline = BasFunction.Mat2Array(imageOutlint); arrayOutline = BasFunction.ConversionRange(arrayOutline); // 二、计算数据提取区域 // 对图片进行填充 Mat imageFill = new Mat(); SubFunction.Fill(imageContour, out imageFill); // 计算数据提取区域 int[] dataArea = new int[2]; SubFunction.DataArea2(imageFill, out dataArea); // 三、提取L1,L3,L4,L6 double meanOrdinateL1 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL1, dataArea[0], dataArea[1]); double meanOrdinateL3 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL3, dataArea[0], dataArea[1],meanOrdinateL1); double meanOrdinateL4 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL4, dataArea[0], dataArea[1], meanOrdinateL3); double meanOrdinateL6 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL6, dataArea[0], dataArea[1], meanOrdinateL4); // 四、提取L2 double meanOrdinateL2 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateL1 + 10, (int)meanOrdinateL3 - 10, dataArea[0], dataArea[1], out meanOrdinateL2); // 五、提取L5 double meanOrdinateL5 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateL4 + 10, (int)meanOrdinateL6 - 10, dataArea[0], dataArea[1], out meanOrdinateL5); // 六、提竖线V1,V2 double abscissaV1 = 0; SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV1, (int)meanOrdinateL3, (int)meanOrdinateL4); double abscissaV2 = 0; SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV2, (int)meanOrdinateL3, (int)meanOrdinateL4, abscissaV1); // 七、数据计算 double upperMiantong = meanOrdinateL2 - meanOrdinateL1; double upperJicaitong = meanOrdinateL3 - meanOrdinateL2; double upperMian_Jicaitong = meanOrdinateL3 - meanOrdinateL1; double lowerMiantong = meanOrdinateL6 - meanOrdinateL5; double lowerJicaitong = meanOrdinateL5 - meanOrdinateL4; double lowerMian_Jicaitong = meanOrdinateL6 - meanOrdinateL4; double kongtong = abscissaV2 - abscissaV1; // 八、标记 int middle = (dataArea[0] + dataArea[1]) / 2; int middle2 = (int)((meanOrdinateL3 + meanOrdinateL4) / 2); // 上面铜 SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL1, middle + 40, (int)meanOrdinateL2,upperMiantong); // 上基材铜 SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL2, middle - 40, (int)meanOrdinateL3, upperJicaitong); // 上面铜+基材铜 SubFunction.LabelVertical(image, middle, (int)meanOrdinateL1, middle, (int)meanOrdinateL3, upperMian_Jicaitong); // 下面铜 SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL5, middle + 40, (int)meanOrdinateL6, lowerMiantong); // 下基材铜 SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL4, middle - 40, (int)meanOrdinateL5, lowerJicaitong); // 下面铜+基材铜 SubFunction.LabelVertical(image, middle, (int)meanOrdinateL4, middle, (int)meanOrdinateL6, lowerMian_Jicaitong); // 孔铜 SubFunction.LableHorizontal(image, (int)abscissaV2, middle2, (int)abscissaV1, middle2, kongtong); } public static void CaokongShuangcengZuo(string fileName) { // 一、预处理 // 读取图片 Mat image = new Mat(fileName, ImreadModes.Color); //获取图片的长宽 int rows = image.Rows; int cols = image.Cols; // 转换为灰度图 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); //获得蓝色,绿色,红色通道图片 Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type()); SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed); // 二值化,获得目标区域 Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu); // 闭运算,消除小孔 Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素 Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se); // 转成数组 int[,] arrayContour = BasFunction.Mat2Array(imageContour); arrayContour = BasFunction.ConversionRange(arrayContour); // 去亮光 int b2, b3; SubFunction.SplitArea(arrayContour, out b2, out b3); if ((b3 - b2) > 100) { Mat result = new Mat(); BasFunction.SetNumber(imageContour, out result, 0, rows, b2, cols, 0);// 亮光区域置0 imageContour = result; } // 边缘检测 Mat imageOutlint = new Mat(); SubFunction.Sobel(imageContour, out imageOutlint); int[,] arrayOutline = BasFunction.Mat2Array(imageOutlint); arrayOutline = BasFunction.ConversionRange(arrayOutline); // 二、计算数据提取区域 // 对图片进行填充 Mat imageFill = new Mat(); SubFunction.Fill(imageContour, out imageFill); // 计算数据提取区域 int[] dataArea = new int[2]; SubFunction.DataArea2(imageFill, out dataArea); // 三、提取L1,L3,L4,L6 double meanOrdinateL1 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL1, dataArea[0], dataArea[1]); double meanOrdinateL3 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL3, dataArea[0], dataArea[1], meanOrdinateL1); double meanOrdinateL4 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL4, dataArea[0], dataArea[1], meanOrdinateL3); double meanOrdinateL6 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL6, dataArea[0], dataArea[1], meanOrdinateL4); // 四、提取L2 double meanOrdinateL2 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateL1 + 10, (int)meanOrdinateL3 - 10, dataArea[0], dataArea[1], out meanOrdinateL2); // 五、提取L5 double meanOrdinateL5 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateL4 + 10, (int)meanOrdinateL6 - 10, dataArea[0], dataArea[1], out meanOrdinateL5); // 六、提竖线V1,V2 double abscissaV1 = 0; SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV1, (int)meanOrdinateL3, (int)meanOrdinateL4); double abscissaV2 = 0; SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV2, (int)meanOrdinateL3, (int)meanOrdinateL4, abscissaV1); // 七、数据计算 double upperMiantong = meanOrdinateL2 - meanOrdinateL1; double upperJicaitong = meanOrdinateL3 - meanOrdinateL2; double upperMian_Jicaitong = meanOrdinateL3 - meanOrdinateL1; double lowerMiantong = meanOrdinateL6 - meanOrdinateL5; double lowerJicaitong = meanOrdinateL5 - meanOrdinateL4; double lowerMian_Jicaitong = meanOrdinateL6 - meanOrdinateL4; double kongtong = abscissaV1 - abscissaV2; // 八、标记 int middle = (dataArea[0] + dataArea[1]) / 2; int middle2 = (int)((meanOrdinateL3 + meanOrdinateL4) / 2); // 上面铜 SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL1, middle + 40, (int)meanOrdinateL2, upperMiantong); // 上基材铜 SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL2, middle - 40, (int)meanOrdinateL3, upperJicaitong); // 上面铜+基材铜 SubFunction.LabelVertical(image, middle, (int)meanOrdinateL1, middle, (int)meanOrdinateL3, upperMian_Jicaitong); // 下面铜 SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL5, middle + 40, (int)meanOrdinateL6, lowerMiantong); // 下基材铜 SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL4, middle - 40, (int)meanOrdinateL5, lowerJicaitong); // 下面铜+基材铜 SubFunction.LabelVertical(image, middle, (int)meanOrdinateL4, middle, (int)meanOrdinateL6, lowerMian_Jicaitong); // 孔铜 SubFunction.LableHorizontal(image, (int)abscissaV2, middle2, (int)abscissaV1, middle2, kongtong); } public static void CaokongSancengYou(string fileName) { // 一、预处理 // 读取图片 Mat image = new Mat(fileName, ImreadModes.Color); //获取图片的长宽 int rows = image.Rows; int cols = image.Cols; // 转换为灰度图 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); //获得蓝色,绿色,红色通道图片 Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type()); SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed); // 二值化,获得目标区域 Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu); // 闭运算,消除小孔 Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素 Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se); // 转成数组 int[,] arrayContour = BasFunction.Mat2Array(imageContour); arrayContour = BasFunction.ConversionRange(arrayContour); // 去亮光 int b2, b3; SubFunction.SplitArea(arrayContour, out b2, out b3); if ((b3 - b2) > 100) { Mat result = new Mat(); BasFunction.SetNumber(imageContour, out result, 0, rows, 0, b3, 0);// 亮光区域置0 imageContour = result; } // 边缘检测 Mat imageOutlint = new Mat(); SubFunction.Sobel(imageContour, out imageOutlint); int[,] arrayOutline = BasFunction.Mat2Array(imageOutlint); arrayOutline = BasFunction.ConversionRange(arrayOutline); // 二、计算数据提取区域 // 对图片进行填充 Mat imageFill = new Mat(); SubFunction.Fill(imageContour, out imageFill); // 计算数据提取区域 int[] dataArea = new int[2]; SubFunction.DataArea2(imageFill, out dataArea); // 三、提取L1,L3,L4,L5, L6, L8 double meanOrdinateL1 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL1, dataArea[0], dataArea[1]); double meanOrdinateL3 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL3, dataArea[0], dataArea[1], meanOrdinateL1); double meanOrdinateL4 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL4, dataArea[0], dataArea[1], meanOrdinateL3); double meanOrdinateL5 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL5, dataArea[0], dataArea[1], meanOrdinateL4); double meanOrdinateL6 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL6, dataArea[0], dataArea[1], meanOrdinateL5); double meanOrdinateL8 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL8, dataArea[0], dataArea[1], meanOrdinateL6); // 四、提取L2 double meanOrdinateL2 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateL1 + 10, (int)meanOrdinateL3 - 10, dataArea[0], dataArea[1], out meanOrdinateL2); // 五、提取L7 double meanOrdinateL7 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateL6 + 10, (int)meanOrdinateL8 - 10, dataArea[0], dataArea[1], out meanOrdinateL7); // 六、提取胶体线 Mat imageGlue = new Mat(); SubFunction.GlueArea(imageContour, imageRed, out imageGlue, (int)meanOrdinateL5 + 10, (int)meanOrdinateL6 - 10, dataArea[0], dataArea[1]); // 转数组 int[,] arrayGlue = BasFunction.Mat2Array(imageGlue); arrayGlue = BasFunction.ConversionRange(arrayGlue); // 提取胶体线 double meanOrdinateLG = 0; SubFunction.InsideLine(imageGlue, (int)meanOrdinateL5 + 15, (int)meanOrdinateL6 - 15, dataArea[0], dataArea[1], out meanOrdinateLG); // 七、提取竖线V1、V2、V3、V4 double abscissaV1 = 0; SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV1, (int)meanOrdinateL3, (int)meanOrdinateL4); double abscissaV2 = 0; SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV2, (int)meanOrdinateL3, (int)meanOrdinateL4, abscissaV1); double abscissaV3 = 0; SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV3, (int)meanOrdinateLG, (int)meanOrdinateL6); double abscissaV4 = 0; SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV4, (int)meanOrdinateLG, (int)meanOrdinateL6, abscissaV3); // 八、计算粗糙度 int cucaodu; int[] cucaoduZuobiao = new int[2]; SubFunction.Cucaodu(arrayOutline, (int)meanOrdinateL5 + 60, (int)meanOrdinateL6 - 30, (int)abscissaV4, out cucaodu, out cucaoduZuobiao); // 九、计算数据 double upperMiantong = meanOrdinateL2 - meanOrdinateL1; double upperJicaitong = meanOrdinateL3 - meanOrdinateL2; double upperMian_Jicaitong = meanOrdinateL3 - meanOrdinateL1; double lowerMiantong = meanOrdinateL8 - meanOrdinateL7; double lowerJicaitong = meanOrdinateL7 - meanOrdinateL6; double lowerMian_Jicaitong = meanOrdinateL8 - meanOrdinateL6; double upperKongtong = abscissaV2 - abscissaV1; double lowerKongtong = abscissaV4 - abscissaV3; // 十、标记 int middle = (dataArea[0] + dataArea[1]) / 2; int middle2 = (int)(meanOrdinateL3 + meanOrdinateL4) / 2; int middle3 = (int)(meanOrdinateLG + meanOrdinateL6) / 2; // 上面铜 SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL1, middle - 40, (int)meanOrdinateL2, upperMiantong); // 上基材铜 SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL2, middle + 40, (int)meanOrdinateL3, upperJicaitong); // 上面铜+基材铜 SubFunction.LabelVertical(image, middle, (int)meanOrdinateL1, middle, (int)meanOrdinateL3, upperMian_Jicaitong); // 下面铜 SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL8, middle - 40, (int)meanOrdinateL7, lowerMiantong); // 下基材铜 SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL7, middle + 40, (int)meanOrdinateL6, lowerJicaitong); // 下面铜+基材铜 SubFunction.LabelVertical(image, middle, (int)meanOrdinateL8, middle, (int)meanOrdinateL6, lowerMian_Jicaitong); // 上孔铜 SubFunction.LableHorizontal(image, (int)abscissaV1, middle2, (int)abscissaV2, middle2, upperKongtong); // 下孔铜 SubFunction.LableHorizontal(image, (int)abscissaV3, middle3, (int)abscissaV4, middle3, lowerKongtong); // 粗糙度 SubFunction.LableHorizontal(image, (int)abscissaV4, cucaoduZuobiao[0], cucaoduZuobiao[1], cucaoduZuobiao[0], cucaodu); } public static void CaokongSancengZuo(string fileName) { // 一、预处理 // 读取图片 Mat image = new Mat(fileName, ImreadModes.Color); //获取图片的长宽 int rows = image.Rows; int cols = image.Cols; // 转换为灰度图 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); //获得蓝色,绿色,红色通道图片 Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type()); SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed); // 二值化,获得目标区域 Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu); // 闭运算,消除小孔 Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素 Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se); // 转成数组 int[,] arrayContour = BasFunction.Mat2Array(imageContour); arrayContour = BasFunction.ConversionRange(arrayContour); // 去亮光 int b2, b3; SubFunction.SplitArea(arrayContour, out b2, out b3); if ((b3 - b2) > 100) { Mat result = new Mat(); BasFunction.SetNumber(imageContour, out result, 0, rows, b2, cols, 0);// 亮光区域置0 imageContour = result; } // 边缘检测 Mat imageOutlint = new Mat(); SubFunction.Sobel(imageContour, out imageOutlint); int[,] arrayOutline = BasFunction.Mat2Array(imageOutlint); arrayOutline = BasFunction.ConversionRange(arrayOutline); // 二、计算数据提取区域 // 对图片进行填充 Mat imageFill = new Mat(); SubFunction.Fill(imageContour, out imageFill); // 计算数据提取区域 int[] dataArea = new int[2]; SubFunction.DataArea2(imageFill, out dataArea); // 三、提取L1,L3,L4,L5, L6, L8 double meanOrdinateL1 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL1, dataArea[0], dataArea[1]); double meanOrdinateL3 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL3, dataArea[0], dataArea[1], meanOrdinateL1); double meanOrdinateL4 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL4, dataArea[0], dataArea[1], meanOrdinateL3); double meanOrdinateL5 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL5, dataArea[0], dataArea[1], meanOrdinateL4); double meanOrdinateL6 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL6, dataArea[0], dataArea[1], meanOrdinateL5); double meanOrdinateL8 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL6, dataArea[0], dataArea[1], meanOrdinateL8); // 四、提取L2 double meanOrdinateL2 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateL1 + 10, (int)meanOrdinateL3 - 10, dataArea[0], dataArea[1], out meanOrdinateL2); // 五、提取L7 double meanOrdinateL7 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateL6 + 10, (int)meanOrdinateL8 - 10, dataArea[0], dataArea[1], out meanOrdinateL7); // 六、提取胶体线 Mat imageGlue = new Mat(); SubFunction.GlueArea(imageContour, imageRed, out imageGlue, (int)meanOrdinateL5 + 10, (int)meanOrdinateL6 - 10, dataArea[0], dataArea[1]); // 转数组 int[,] arrayGlue = BasFunction.Mat2Array(imageGlue); arrayGlue = BasFunction.ConversionRange(arrayGlue); // 提取胶体线 double meanOrdinateLG = 0; SubFunction.InsideLine(imageGlue, (int)meanOrdinateL5 + 15, (int)meanOrdinateL6 - 15, dataArea[0], dataArea[1], out meanOrdinateLG); // 七、提取竖线V1、V2、V3、V4 double abscissaV1 = 0; SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV1, (int)meanOrdinateL3, (int)meanOrdinateL4); double abscissaV2 = 0; SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV2, (int)meanOrdinateL3, (int)meanOrdinateL4, abscissaV1); double abscissaV3 = 0; SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV3, (int)meanOrdinateLG, (int)meanOrdinateL6); double abscissaV4 = 0; SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV4, (int)meanOrdinateLG, (int)meanOrdinateL6, abscissaV3); // 八、计算粗糙度 int cucaodu; int[] cucaoduZuobiao = new int[2]; SubFunction.Cucaodu(arrayOutline, (int)meanOrdinateL5 + 60, (int)meanOrdinateL6 - 30, (int)abscissaV4, out cucaodu, out cucaoduZuobiao); // 九、计算数据 double upperMiantong = meanOrdinateL2 - meanOrdinateL1; double upperJicaitong = meanOrdinateL3 - meanOrdinateL2; double upperMian_Jicaitong = meanOrdinateL3 - meanOrdinateL1; double lowerMiantong = meanOrdinateL8 - meanOrdinateL7; double lowerJicaitong = meanOrdinateL7 - meanOrdinateL6; double lowerMian_Jicaitong = meanOrdinateL8 - meanOrdinateL6; double upperKongtong = abscissaV1 - abscissaV2; double lowerKongtong = abscissaV3 - abscissaV4; // 十、标记 int middle = (dataArea[0] + dataArea[1]) / 2; int middle2 = (int)(meanOrdinateL3 + meanOrdinateL4) / 2; int middle3 = (int)(meanOrdinateLG + meanOrdinateL6) / 2; // 上面铜 SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL1, middle - 40, (int)meanOrdinateL2, upperMiantong); // 上基材铜 SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL2, middle + 40, (int)meanOrdinateL3, upperJicaitong); // 上面铜+基材铜 SubFunction.LabelVertical(image, middle, (int)meanOrdinateL1, middle, (int)meanOrdinateL3, upperMian_Jicaitong); // 下面铜 SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL8, middle - 40, (int)meanOrdinateL7, lowerMiantong); // 下基材铜 SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL7, middle + 40, (int)meanOrdinateL6, lowerJicaitong); // 下面铜+基材铜 SubFunction.LabelVertical(image, middle, (int)meanOrdinateL8, middle, (int)meanOrdinateL6, lowerMian_Jicaitong); // 上孔铜 SubFunction.LableHorizontal(image, (int)abscissaV1, middle2, (int)abscissaV2, middle2, upperKongtong); // 下孔铜 SubFunction.LableHorizontal(image, (int)abscissaV3, middle3, (int)abscissaV4, middle3, lowerKongtong); // 粗糙度 SubFunction.LableHorizontal(image, (int)abscissaV4, cucaoduZuobiao[0], cucaoduZuobiao[1], cucaoduZuobiao[0], cucaodu); } public static void CaokongSicengYou(string fileName) { // 一、预处理 // 读取图片 Mat image = new Mat(fileName, ImreadModes.Color); //获取图片的长宽 int rows = image.Rows; int cols = image.Cols; // 转换为灰度图 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); //获得蓝色,绿色,红色通道图片 Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type()); SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed); // 二值化,获得目标区域 Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu); // 闭运算,消除小孔 Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素 Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se); // 去亮光 Mat result = new Mat(); SubFunction.RemoveLightSiceng(imageContour, imageRed, out result, "right"); imageContour = result; // 转成数组 int[,] arrayContour = BasFunction.Mat2Array(imageContour); arrayContour = BasFunction.ConversionRange(arrayContour); // 边缘检测 Mat imageOutlint = new Mat(); SubFunction.Sobel(imageContour, out imageOutlint); int[,] arrayOutline = BasFunction.Mat2Array(imageOutlint); arrayOutline = BasFunction.ConversionRange(arrayOutline); // 二、计算数据提取区域 // 对图片进行填充 Mat imageFill = new Mat(); SubFunction.Fill(imageContour, out imageFill); // 计算数据提取区域 int[] dataArea = new int[2]; SubFunction.DataArea2(imageFill, out dataArea); // 三、提取L1,L3,L4,L5, L6, L7, L8, L10 double meanOrdinateL1 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL1, dataArea[0], dataArea[1]); double meanOrdinateL3 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL3, dataArea[0], dataArea[1], meanOrdinateL1); double meanOrdinateL4 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL4, dataArea[0], dataArea[1], meanOrdinateL3); double meanOrdinateL5 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL5, dataArea[0], dataArea[1], meanOrdinateL4); double meanOrdinateL6 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL6, dataArea[0], dataArea[1], meanOrdinateL5); double meanOrdinateL7 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL7, dataArea[0], dataArea[1], meanOrdinateL6); double meanOrdinateL8 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL8, dataArea[0], dataArea[1], meanOrdinateL7); double meanOrdinateL10 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL10, dataArea[0], dataArea[1], meanOrdinateL8); // 四、提取L2 double meanOrdinateL2 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateL1 + 10, (int)meanOrdinateL3 - 10, dataArea[0], dataArea[1], out meanOrdinateL2); // 五、提取L7 double meanOrdinateL9 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateL8 + 10, (int)meanOrdinateL10 - 10, dataArea[0], dataArea[1], out meanOrdinateL10); // 六、提取胶体线 Mat imageGlue1 = new Mat(); SubFunction.GlueArea(imageContour, imageRed, out imageGlue1, (int)meanOrdinateL3 + 10, (int)meanOrdinateL4 - 10, dataArea[0], dataArea[1]); Mat imageGlue2 = new Mat(); SubFunction.GlueArea(imageContour, imageRed, out imageGlue2, (int)meanOrdinateL7 + 10, (int)meanOrdinateL8 - 10, dataArea[0], dataArea[1]); // 转数组 int[,] arrayGlue1 = BasFunction.Mat2Array(imageGlue1); arrayGlue1 = BasFunction.ConversionRange(arrayGlue1); int[,] arrayGlue2 = BasFunction.Mat2Array(imageGlue2); arrayGlue2 = BasFunction.ConversionRange(arrayGlue2); // 提取胶体线 double meanOrdinateLG1 = 0; SubFunction.InsideLine(imageGlue1, (int)meanOrdinateL3 + 15, (int)meanOrdinateL4 - 15, dataArea[0], dataArea[1], out meanOrdinateLG1); double meanOrdinateLG2 = 0; SubFunction.InsideLine(imageGlue1, (int)meanOrdinateL7 + 15, (int)meanOrdinateL8 - 15, dataArea[0], dataArea[1], out meanOrdinateLG2); // 七、提取竖线V1、V2、V3、V4、V5、V6 double abscissaV1 = 0; SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV1, (int)meanOrdinateL3, (int)meanOrdinateLG1); double abscissaV2 = 0; SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV2, (int)meanOrdinateL3, (int)meanOrdinateLG1, abscissaV1); double abscissaV3 = 0; SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV3, (int)meanOrdinateL5, (int)meanOrdinateL6); double abscissaV4 = 0; SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV4, (int)meanOrdinateL5, (int)meanOrdinateL6, abscissaV3); double abscissaV5 = 0; SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV5, (int)meanOrdinateLG2, (int)meanOrdinateL8); double abscissaV6 = 0; SubFunction.ExtractVerticalLines2(arrayOutline, out abscissaV6, (int)meanOrdinateLG2, (int)meanOrdinateL8, abscissaV5); // 八、计算粗糙度 int cucaodu1; int[] cucaoduZuobiao1 = new int[2]; SubFunction.Cucaodu(arrayOutline, (int)meanOrdinateL3 + 60, (int)meanOrdinateL4 - 30, (int)abscissaV2, out cucaodu1, out cucaoduZuobiao1); int cucaodu2; int[] cucaoduZuobiao2 = new int[2]; SubFunction.Cucaodu(arrayOutline, (int)meanOrdinateL7 + 60, (int)meanOrdinateL8 - 30, (int)abscissaV6, out cucaodu2, out cucaoduZuobiao2); // 九、计算数据 double upperMiantong = meanOrdinateL2 - meanOrdinateL1; double upperJicaitong = meanOrdinateL3 - meanOrdinateL2; double upperMian_Jicaitong = meanOrdinateL3 - meanOrdinateL1; double lowerMiantong = meanOrdinateL10 - meanOrdinateL8; double lowerJicaitong = meanOrdinateL9 - meanOrdinateL8; double lowerMian_Jicaitong = meanOrdinateL10 - meanOrdinateL8; double upperKongtong = abscissaV2 - abscissaV1; double middleKongtong = abscissaV4 - abscissaV3; double lowerKongtong = abscissaV6 - abscissaV5; // 十、标记 int middle = (dataArea[0] + dataArea[1]) / 2;// 面铜+基材铜横坐标 int middle2 = (int)(meanOrdinateL3 + meanOrdinateLG1) / 2;// 孔铜1纵坐标 int middle3 = (int)(meanOrdinateL5 + meanOrdinateL6) / 2;// 孔铜2纵坐标 int middle4 = (int)(meanOrdinateLG2 + meanOrdinateL8) / 2;// 孔铜3纵坐标 // 上面铜 SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL1, middle - 40, (int)meanOrdinateL2, upperMiantong); // 上基材铜 SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL2, middle + 40, (int)meanOrdinateL3, upperJicaitong); // 上面铜+基材铜 SubFunction.LabelVertical(image, middle, (int)meanOrdinateL1, middle, (int)meanOrdinateL3, upperMian_Jicaitong); // 下面铜 SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL8, middle - 40, (int)meanOrdinateL7, lowerMiantong); // 下基材铜 SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL7, middle + 40, (int)meanOrdinateL6, lowerJicaitong); // 下面铜+基材铜 SubFunction.LabelVertical(image, middle, (int)meanOrdinateL8, middle, (int)meanOrdinateL6, lowerMian_Jicaitong); // 上孔铜 SubFunction.LableHorizontal(image, (int)abscissaV1, middle2, (int)abscissaV2, middle2, upperKongtong); // 中孔铜 SubFunction.LableHorizontal(image, (int)abscissaV3, middle3, (int)abscissaV4, middle3, middleKongtong); // 下孔铜 SubFunction.LableHorizontal(image, (int)abscissaV5, middle4, (int)abscissaV6, middle4, lowerKongtong); // 粗糙度1 SubFunction.LableHorizontal(image, (int)abscissaV2, cucaoduZuobiao1[0], cucaoduZuobiao1[1], cucaoduZuobiao1[0], cucaodu1); // 粗糙度2 SubFunction.LableHorizontal(image, (int)abscissaV6, cucaoduZuobiao2[0], cucaoduZuobiao2[1], cucaoduZuobiao2[0], cucaodu2); } public static void CaokongSicengZuo(string fileName) { // 一、预处理 // 读取图片 Mat image = new Mat(fileName, ImreadModes.Color); //获取图片的长宽 int rows = image.Rows; int cols = image.Cols; // 转换为灰度图 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); //获得蓝色,绿色,红色通道图片 Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type()); SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed); // 二值化,获得目标区域 Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu); // 闭运算,消除小孔 Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素 Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se); // 去亮光 Mat result = new Mat(); SubFunction.RemoveLightSiceng(imageContour, imageRed, out result, "left"); imageContour = result; // 转成数组 int[,] arrayContour = BasFunction.Mat2Array(imageContour); arrayContour = BasFunction.ConversionRange(arrayContour); // 边缘检测 Mat imageOutlint = new Mat(); SubFunction.Sobel(imageContour, out imageOutlint); int[,] arrayOutline = BasFunction.Mat2Array(imageOutlint); arrayOutline = BasFunction.ConversionRange(arrayOutline); // 二、计算数据提取区域 // 对图片进行填充 Mat imageFill = new Mat(); SubFunction.Fill(imageContour, out imageFill); // 计算数据提取区域 int[] dataArea = new int[2]; SubFunction.DataArea2(imageFill, out dataArea); // 三、提取L1,L3,L4,L5, L6, L7, L8, L10 double meanOrdinateL1 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL1, dataArea[0], dataArea[1]); double meanOrdinateL3 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL3, dataArea[0], dataArea[1], meanOrdinateL1); double meanOrdinateL4 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL4, dataArea[0], dataArea[1], meanOrdinateL3); double meanOrdinateL5 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL5, dataArea[0], dataArea[1], meanOrdinateL4); double meanOrdinateL6 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL6, dataArea[0], dataArea[1], meanOrdinateL5); double meanOrdinateL7 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL7, dataArea[0], dataArea[1], meanOrdinateL6); double meanOrdinateL8 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL8, dataArea[0], dataArea[1], meanOrdinateL7); double meanOrdinateL10 = 0; SubFunction.ExtractLines(arrayOutline, out meanOrdinateL10, dataArea[0], dataArea[1], meanOrdinateL8); // 四、提取L2 double meanOrdinateL2 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateL1 + 10, (int)meanOrdinateL3 - 10, dataArea[0], dataArea[1], out meanOrdinateL2); // 五、提取L7 double meanOrdinateL9 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateL8 + 10, (int)meanOrdinateL10 - 10, dataArea[0], dataArea[1], out meanOrdinateL10); // 六、提取胶体线 Mat imageGlue1 = new Mat(); SubFunction.GlueArea(imageContour, imageRed, out imageGlue1, (int)meanOrdinateL3 + 10, (int)meanOrdinateL4 - 10, dataArea[0], dataArea[1]); Mat imageGlue2 = new Mat(); SubFunction.GlueArea(imageContour, imageRed, out imageGlue2, (int)meanOrdinateL7 + 10, (int)meanOrdinateL8 - 10, dataArea[0], dataArea[1]); // 转数组 int[,] arrayGlue1 = BasFunction.Mat2Array(imageGlue1); arrayGlue1 = BasFunction.ConversionRange(arrayGlue1); int[,] arrayGlue2 = BasFunction.Mat2Array(imageGlue2); arrayGlue2 = BasFunction.ConversionRange(arrayGlue2); // 提取胶体线 double meanOrdinateLG1 = 0; SubFunction.InsideLine(imageGlue1, (int)meanOrdinateL3 + 15, (int)meanOrdinateL4 - 15, dataArea[0], dataArea[1], out meanOrdinateLG1); double meanOrdinateLG2 = 0; SubFunction.InsideLine(imageGlue1, (int)meanOrdinateL7 + 15, (int)meanOrdinateL8 - 15, dataArea[0], dataArea[1], out meanOrdinateLG2); // 七、提取竖线V1、V2、V3、V4、V5、V6 double abscissaV1 = 0; SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV1, (int)meanOrdinateL3, (int)meanOrdinateLG1); double abscissaV2 = 0; SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV2, (int)meanOrdinateL3, (int)meanOrdinateLG1, abscissaV1); double abscissaV3 = 0; SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV3, (int)meanOrdinateL5, (int)meanOrdinateL6); double abscissaV4 = 0; SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV4, (int)meanOrdinateL5, (int)meanOrdinateL6, abscissaV3); double abscissaV5 = 0; SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV5, (int)meanOrdinateLG2, (int)meanOrdinateL8); double abscissaV6 = 0; SubFunction.ExtractVerticalLines(arrayOutline, out abscissaV6, (int)meanOrdinateLG2, (int)meanOrdinateL8, abscissaV5); // 八、计算粗糙度 int cucaodu1; int[] cucaoduZuobiao1 = new int[2]; SubFunction.Cucaodu(arrayOutline, (int)meanOrdinateL3 + 60, (int)meanOrdinateL4 - 30, (int)abscissaV2, out cucaodu1, out cucaoduZuobiao1); int cucaodu2; int[] cucaoduZuobiao2 = new int[2]; SubFunction.Cucaodu(arrayOutline, (int)meanOrdinateL7 + 60, (int)meanOrdinateL8 - 30, (int)abscissaV6, out cucaodu2, out cucaoduZuobiao2); // 九、计算数据 double upperMiantong = meanOrdinateL2 - meanOrdinateL1; double upperJicaitong = meanOrdinateL3 - meanOrdinateL2; double upperMian_Jicaitong = meanOrdinateL3 - meanOrdinateL1; double lowerMiantong = meanOrdinateL10 - meanOrdinateL8; double lowerJicaitong = meanOrdinateL9 - meanOrdinateL8; double lowerMian_Jicaitong = meanOrdinateL10 - meanOrdinateL8; double upperKongtong = abscissaV1 - abscissaV2; double middleKongtong = abscissaV3 - abscissaV4; double lowerKongtong = abscissaV5 - abscissaV6; // 十、标记 int middle = (dataArea[0] + dataArea[1]) / 2;// 面铜+基材铜横坐标 int middle2 = (int)(meanOrdinateL3 + meanOrdinateLG1) / 2;// 孔铜1纵坐标 int middle3 = (int)(meanOrdinateL5 + meanOrdinateL6) / 2;// 孔铜2纵坐标 int middle4 = (int)(meanOrdinateLG2 + meanOrdinateL8) / 2;// 孔铜3纵坐标 // 上面铜 SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL1, middle - 40, (int)meanOrdinateL2, upperMiantong); // 上基材铜 SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL2, middle + 40, (int)meanOrdinateL3, upperJicaitong); // 上面铜+基材铜 SubFunction.LabelVertical(image, middle, (int)meanOrdinateL1, middle, (int)meanOrdinateL3, upperMian_Jicaitong); // 下面铜 SubFunction.LabelVertical(image, middle - 40, (int)meanOrdinateL8, middle - 40, (int)meanOrdinateL7, lowerMiantong); // 下基材铜 SubFunction.LabelVertical(image, middle + 40, (int)meanOrdinateL7, middle + 40, (int)meanOrdinateL6, lowerJicaitong); // 下面铜+基材铜 SubFunction.LabelVertical(image, middle, (int)meanOrdinateL8, middle, (int)meanOrdinateL6, lowerMian_Jicaitong); // 上孔铜 SubFunction.LableHorizontal(image, (int)abscissaV1, middle2, (int)abscissaV2, middle2, upperKongtong); // 中孔铜 SubFunction.LableHorizontal(image, (int)abscissaV3, middle3, (int)abscissaV4, middle3, middleKongtong); // 下孔铜 SubFunction.LableHorizontal(image, (int)abscissaV5, middle4, (int)abscissaV6, middle4, lowerKongtong); // 粗糙度1 SubFunction.LableHorizontal(image, (int)abscissaV2, cucaoduZuobiao1[0], cucaoduZuobiao1[1], cucaoduZuobiao1[0], cucaodu1); // 粗糙度2 SubFunction.LableHorizontal(image, (int)abscissaV6, cucaoduZuobiao2[0], cucaoduZuobiao2[1], cucaoduZuobiao2[0], cucaodu2); } public static void CaokongSicengZhong(string fileName) { // 一、预处理 // 读取图片 Mat image = new Mat(fileName, ImreadModes.Color); //获取图片的长宽 int rows = image.Rows; int cols = image.Cols; // 转换为灰度图 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); //获得蓝色,绿色,红色通道图片 Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type()); SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed); // 重新修改比例调色 Mat imageNew = new Mat(imageRed.Size(), imageRed.Type()); imageNew = 0.9 * imageGreen + 0.1 * imageRed; // 均值滤波 Mat imageFilter = new Mat(); Cv2.Blur(imageNew, imageFilter, new Size(5, 5)); // 二值化,获得目标区域 Mat imageContourText = imageFilter.Threshold(0, 255, ThresholdTypes.Otsu);// 用来计算消除亮光的边界 Mat imageContour = imageRed.Threshold(0, 255, ThresholdTypes.Otsu); // 转成数组 int[,] arrayContourText = BasFunction.Mat2Array(imageContourText); arrayContourText = BasFunction.ConversionRange(arrayContourText); // 将中间亮光置0 int b2, b3; SubFunction.SplitArea(arrayContourText, out b2, out b3); Mat result = new Mat(); BasFunction.SetNumber(imageContour, out result, 0, rows, b2, b3, 0);// 亮光区域置0 imageContour = result; // 闭运算,消除小孔 Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素 Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se); // 将原图分为两部分 int dividingLine = (b2 + b3) / 2; Mat imageContour1 = imageContour; Mat imageContour2 = imageContour; for (int i = 0; i < rows; i++) { for (int j = 0; j < dividingLine; j++) { imageContour2.Set(i, j, 0); } for (int k = dividingLine; k < cols; k++) { imageContour1.Set(i, k, 0); } } // 边缘检测 Mat imageOutline1; Mat imageOutline2; SubFunction.Sobel(imageContour1, out imageOutline1); SubFunction.Sobel(imageContour2, out imageOutline2); // 转成数组 int[,] arrayOutline1 = BasFunction.Mat2Array(imageOutline1); arrayOutline1 = BasFunction.ConversionRange(arrayOutline1); int[,] arrayOutline2 = BasFunction.Mat2Array(imageOutline2); arrayOutline2 = BasFunction.ConversionRange(arrayOutline2); // 计算图像1(左) // 二、计算数据提取区域 // 对图片进行填充 Mat imageFill = new Mat(); SubFunction.Fill(imageContour1, out imageFill); // 计算数据提取区域 int[] dataArea = new int[2]; SubFunction.DataArea2(imageFill, out dataArea); // 三、提取L1,L3,L4,L5, L6, L7, L8, L10 double meanOrdinateLeft1 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft1, dataArea[0], dataArea[1]); double meanOrdinateLeft3 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft3, dataArea[0], dataArea[1], meanOrdinateLeft1); double meanOrdinateLeft4 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft4, dataArea[0], dataArea[1], meanOrdinateLeft3); double meanOrdinateLeft5 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft5, dataArea[0], dataArea[1], meanOrdinateLeft4); double meanOrdinateLeft6 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft6, dataArea[0], dataArea[1], meanOrdinateLeft5); double meanOrdinateLeft7 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft7, dataArea[0], dataArea[1], meanOrdinateLeft6); double meanOrdinateLeft8 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft8, dataArea[0], dataArea[1], meanOrdinateLeft7); double meanOrdinateLeft10 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft10, dataArea[0], dataArea[1], meanOrdinateLeft8); // 四、提取L2 double meanOrdinateLeft2 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft1 + 10, (int)meanOrdinateLeft3 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft2); // 五、提取L7 double meanOrdinateLeft9 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft8 + 10, (int)meanOrdinateLeft10 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft9); // 六、提取胶体线 Mat imageGlueLeft1 = new Mat(); SubFunction.GlueArea(imageContour1, imageRed, out imageGlueLeft1, (int)meanOrdinateLeft3 + 10, (int)meanOrdinateLeft4 - 10, dataArea[0], dataArea[1]); Mat imageGlueLeft2 = new Mat(); SubFunction.GlueArea(imageContour1, imageRed, out imageGlueLeft2, (int)meanOrdinateLeft7 + 10, (int)meanOrdinateLeft8 - 10, dataArea[0], dataArea[1]); // 转数组 int[,] arrayGlueLeft1 = BasFunction.Mat2Array(imageGlueLeft1); arrayGlueLeft1 = BasFunction.ConversionRange(arrayGlueLeft1); int[,] arrayGlueLeft2 = BasFunction.Mat2Array(imageGlueLeft2); arrayGlueLeft2 = BasFunction.ConversionRange(arrayGlueLeft2); // 提取胶体线 double meanOrdinateLG1 = 0; SubFunction.InsideLine(imageGlueLeft1, (int)meanOrdinateLeft3 + 15, (int)meanOrdinateLeft4 - 15, dataArea[0], dataArea[1], out meanOrdinateLG1); double meanOrdinateLG2 = 0; SubFunction.InsideLine(imageGlueLeft2, (int)meanOrdinateLeft7 + 15, (int)meanOrdinateLeft8 - 15, dataArea[0], dataArea[1], out meanOrdinateLG2); // 七、提竖线V1,V2, V3, V4, V5, V6 double abscissaVLeft1 = 0; SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft1, (int)meanOrdinateLeft3, (int)meanOrdinateLG1); double abscissaVLeft2 = 0; SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft2, (int)meanOrdinateLeft3, (int)meanOrdinateLG1, abscissaVLeft1); double abscissaVLeft3 = 0; SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft3, (int)meanOrdinateLeft5, (int)meanOrdinateLeft6); double abscissaVLeft4 = 0; SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft4, (int)meanOrdinateLeft5, (int)meanOrdinateLeft6, abscissaVLeft3); double abscissaVLeft5 = 0; SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft5, (int)meanOrdinateLG2, (int)meanOrdinateLeft8); double abscissaVLeft6 = 0; SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft6, (int)meanOrdinateLG2, (int)meanOrdinateLeft8, abscissaVLeft5); // 八、计算粗糙度 int cucaoduLeft1 = 0; int[] cucaoduZuobiaoLeft1 = new int[2]; SubFunction.Cucaodu(arrayOutline1, (int)meanOrdinateLeft3 + 60, (int)meanOrdinateLeft4 - 30, (int)abscissaVLeft2, out cucaoduLeft1, out cucaoduZuobiaoLeft1); int cucaoduLeft2 = 0; int[] cucaoduZuobiaoLeft2 = new int[2]; SubFunction.Cucaodu(arrayOutline1, (int)meanOrdinateLeft7 + 60, (int)meanOrdinateLeft8 - 30, (int)abscissaVLeft6, out cucaoduLeft2, out cucaoduZuobiaoLeft2); // 计算图像2(右) // 二、计算数据提取区域 // 对图片进行填充 Mat imageFill2 = new Mat(); SubFunction.Fill(imageContour2, out imageFill); // 计算数据提取区域 int[] dataArea2 = new int[2]; SubFunction.DataArea2(imageFill2, out dataArea2); // 三、提取L1,L3,L4,L5, L6, L7, L8, L10 double meanOrdinateRight1 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight1, dataArea2[0], dataArea2[1]); double meanOrdinateRight3 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight3, dataArea2[0], dataArea2[1], meanOrdinateRight1); double meanOrdinateRight4 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight4, dataArea2[0], dataArea2[1], meanOrdinateRight3); double meanOrdinateRight5 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight5, dataArea2[0], dataArea2[1], meanOrdinateRight4); double meanOrdinateRight6 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight6, dataArea2[0], dataArea2[1], meanOrdinateRight5); double meanOrdinateRight7 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight7, dataArea2[0], dataArea2[1], meanOrdinateRight6); double meanOrdinateRight8 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight8, dataArea2[0], dataArea2[1], meanOrdinateRight7); double meanOrdinateRight10 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight10, dataArea2[0], dataArea2[1], meanOrdinateRight8); // 四、提取L2 double meanOrdinateRight2 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight1 + 10, (int)meanOrdinateRight3 - 10, dataArea2[0], dataArea2[1], out meanOrdinateRight2); // 五、提取L9 double meanOrdinateRight9 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight8 + 10, (int)meanOrdinateRight10 - 10, dataArea2[0], dataArea2[1], out meanOrdinateRight9); // 六、提取胶体线 Mat imageGlueRight1 = new Mat(); SubFunction.GlueArea(imageContour2, imageRed, out imageGlueRight1, (int)meanOrdinateRight3 + 10, (int)meanOrdinateRight4 - 10, dataArea2[0], dataArea2[1]); Mat imageGlueRight2 = new Mat(); SubFunction.GlueArea(imageContour2, imageRed, out imageGlueRight2, (int)meanOrdinateRight7 + 10, (int)meanOrdinateRight8 - 10, dataArea2[0], dataArea2[1]); // 转数组 int[,] arrayGlueRight1 = BasFunction.Mat2Array(imageGlueRight1); arrayGlueRight1 = BasFunction.ConversionRange(arrayGlueRight1); int[,] arrayGlueRight2 = BasFunction.Mat2Array(imageGlueRight2); arrayGlueRight2 = BasFunction.ConversionRange(arrayGlueRight2); // 提取胶体线 double meanOrdinateRG1 = 0; SubFunction.InsideLine(imageGlueRight1, (int)meanOrdinateRight3 + 15, (int)meanOrdinateRight4 - 15, dataArea2[0], dataArea2[1], out meanOrdinateRG1); double meanOrdinateRG2 = 0; SubFunction.InsideLine(imageGlueRight2, (int)meanOrdinateRight7 + 15, (int)meanOrdinateRight8 - 15, dataArea2[0], dataArea2[1], out meanOrdinateRG2); // 七 、提竖线V1,V2, V3, V4, V5, V6 double abscissaVRight1 = 0; SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight1, (int)meanOrdinateRight3, (int)meanOrdinateRG1); double abscissaVRight2 = 0; SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight2, (int)meanOrdinateRight3, (int)meanOrdinateRG1, abscissaVRight1); double abscissaVRight3 = 0; SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight3, (int)meanOrdinateRight5, (int)meanOrdinateRight6); double abscissaVRight4 = 0; SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight4, (int)meanOrdinateRight5, (int)meanOrdinateRight6, abscissaVRight3); double abscissaVRight5 = 0; SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight5, (int)meanOrdinateRG2, (int)meanOrdinateRight8); double abscissaVRight6 = 0; SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight6, (int)meanOrdinateRG2, (int)meanOrdinateRight8, abscissaVRight5); // 八、计算粗糙度 int cucaoduRight1 = 0; int[] cucaoduZuobiaoRight1 = new int[2]; SubFunction.Cucaodu(arrayOutline2, (int)meanOrdinateRight3 + 60, (int)meanOrdinateRight4 - 30, (int)abscissaVRight2, out cucaoduRight1, out cucaoduZuobiaoRight1); int cucaoduRight2 = 0; int[] cucaoduZuobiaoRight2 = new int[2]; SubFunction.Cucaodu(arrayOutline2, (int)meanOrdinateRight7 + 60, (int)meanOrdinateRight8 - 30, (int)abscissaVRight6, out cucaoduRight2, out cucaoduZuobiaoRight2); // 九、数据计算 // 左 double leftUpperMiantong = meanOrdinateLeft2 - meanOrdinateLeft1; double leftUpperJicaitong = meanOrdinateLeft3 - meanOrdinateLeft2; double leftUpperMian_Jicaitong = meanOrdinateLeft3 - meanOrdinateLeft1; double leftLowerMiantong = meanOrdinateLeft10 - meanOrdinateLeft9; double leftLowerJicaitong = meanOrdinateLeft9 - meanOrdinateLeft8; double leftLowerMian_Jicaitong = meanOrdinateLeft10 - meanOrdinateLeft8; double leftKongtong1 = abscissaVLeft1 - abscissaVLeft2; double leftKongtong2 = abscissaVLeft3 - abscissaVLeft4; double leftKongtong3 = abscissaVLeft5 - abscissaVLeft6; // 右 double rightUpperMiantong = meanOrdinateRight2 - meanOrdinateRight1; double rightUpperJicaitong = meanOrdinateRight3 - meanOrdinateRight2; double rightUpperMian_Jicaitong = meanOrdinateRight3 - meanOrdinateRight1; double rightLowerMiantong = meanOrdinateRight10 - meanOrdinateRight9; double rightLowerJicaitong = meanOrdinateRight9 - meanOrdinateRight8; double rightLowerMian_Jicaitong = meanOrdinateRight10 - meanOrdinateRight8; double rightKongtong1 = abscissaVRight2 - abscissaVRight1; double rightKongtong2 = abscissaVRight4 - abscissaVRight3; double rightKongtong3 = abscissaVRight6 - abscissaVRight5; double upperKongjing = abscissaVRight2 - abscissaVLeft2; ; double lowerKongjing = abscissaVRight6 - abscissaVLeft6; // 八、标记 int middleLeft = (dataArea[0] + dataArea[1]) / 2;// 左边面铜+基材铜横坐标 int middleLeft2 = (int)((meanOrdinateLeft3 + meanOrdinateLG1) / 2);// 左边孔铜1纵坐标 int middleLeft3 = (int)((meanOrdinateLeft5 + meanOrdinateLeft6) / 2);// 左边孔铜2纵坐标 int middleLeft4 = (int)((meanOrdinateLG2 + meanOrdinateLeft8) / 2);// 左边孔铜3纵坐标 int middleRight = (dataArea2[0] + dataArea2[1]) / 2;// 右边面铜+基材铜横坐标 int middleRight2 = (int)((meanOrdinateRight3 + meanOrdinateRG1) / 2);// 右边孔铜1纵坐标 int middleRight3 = (int)((meanOrdinateRight5 + meanOrdinateRight6) / 2);// 右边孔铜2纵坐标 int middleRight4 = (int)((meanOrdinateRG2 + meanOrdinateRight8) / 2);// 右边孔铜3纵坐标 // 图一标记(左) // 上面铜 SubFunction.LabelVertical(image, middleLeft + 40, (int)meanOrdinateLeft1, middleLeft + 40, (int)meanOrdinateLeft2, leftUpperMiantong); // 上基材铜 SubFunction.LabelVertical(image, middleLeft - 40, (int)meanOrdinateLeft2, middleLeft - 40, (int)meanOrdinateLeft3, leftUpperJicaitong); // 上面铜+基材铜 SubFunction.LabelVertical(image, middleLeft, (int)meanOrdinateLeft1, middleLeft, (int)meanOrdinateLeft3, leftUpperMian_Jicaitong); // 下面铜 SubFunction.LabelVertical(image, middleLeft + 40, (int)meanOrdinateLeft9, middleLeft + 40, (int)meanOrdinateLeft10, leftLowerMiantong); // 下基材铜 SubFunction.LabelVertical(image, middleLeft - 40, (int)meanOrdinateLeft8, middleLeft - 40, (int)meanOrdinateLeft9, leftLowerJicaitong); // 下面铜+基材铜 SubFunction.LabelVertical(image, middleLeft, (int)meanOrdinateLeft8, middleLeft, (int)meanOrdinateLeft10, leftLowerMian_Jicaitong); // 孔铜 SubFunction.LableHorizontal(image, (int)abscissaVLeft2, middleLeft2, (int)abscissaVLeft1, middleLeft2, leftKongtong1); SubFunction.LableHorizontal(image, (int)abscissaVLeft4, middleLeft3, (int)abscissaVLeft3, middleLeft3, leftKongtong2); SubFunction.LableHorizontal(image, (int)abscissaVLeft6, middleLeft4, (int)abscissaVLeft5, middleLeft4, leftKongtong3); // 图二标记(右) // 上面铜 SubFunction.LabelVertical(image, middleRight + 40, (int)meanOrdinateRight1, middleRight + 40, (int)meanOrdinateRight2, rightUpperMiantong); // 上基材铜 SubFunction.LabelVertical(image, middleRight - 40, (int)meanOrdinateRight2, middleRight - 40, (int)meanOrdinateRight3, rightUpperJicaitong); // 上面铜+基材铜 SubFunction.LabelVertical(image, middleRight, (int)meanOrdinateRight1, middleRight, (int)meanOrdinateRight3, rightUpperMian_Jicaitong); // 下面铜 SubFunction.LabelVertical(image, middleRight + 40, (int)meanOrdinateRight9, middleRight + 40, (int)meanOrdinateRight10, rightLowerMiantong); // 下基材铜 SubFunction.LabelVertical(image, middleRight - 40, (int)meanOrdinateRight8, middleRight - 40, (int)meanOrdinateRight9, rightLowerJicaitong); // 下面铜+基材铜 SubFunction.LabelVertical(image, middleRight, (int)meanOrdinateRight8, middleRight, (int)meanOrdinateRight10, rightLowerMian_Jicaitong); // 孔铜 SubFunction.LableHorizontal(image, (int)abscissaVRight2, middleRight2, (int)abscissaVRight1, middleRight2, rightKongtong1); SubFunction.LableHorizontal(image, (int)abscissaVRight4, middleRight3, (int)abscissaVRight3, middleRight3, rightKongtong2); SubFunction.LableHorizontal(image, (int)abscissaVRight6, middleRight4, (int)abscissaVRight5, middleRight4, rightKongtong3); // 上孔径 SubFunction.LableHorizontal(image, (int)abscissaVLeft2, (int)meanOrdinateLeft1, (int)abscissaVRight2, (int)meanOrdinateLeft1, upperKongjing); // 下孔径 SubFunction.LableHorizontal(image, (int)abscissaVLeft6, (int)meanOrdinateLeft10, (int)abscissaVRight6, (int)meanOrdinateLeft10, lowerKongjing); } public static void CaokongShuangcengZhong(string fileName) { // 一、预处理 // 读取图片 Mat image = new Mat(fileName, ImreadModes.Color); //获取图片的长宽 int rows = image.Rows; int cols = image.Cols; // 转换为灰度图 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); //获得蓝色,绿色,红色通道图片 Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type()); SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed); // 重新修改比例调色 Mat imageNew = new Mat(imageRed.Size(),imageRed.Type()); imageNew = 0.9 * imageGreen + 0.1 * imageRed; // 均值滤波 Mat imageFilter = new Mat(); Cv2.Blur(imageNew, imageFilter, new Size(5, 5)); // 二值化,获得目标区域 Mat imageContourText = imageFilter.Threshold(0, 255, ThresholdTypes.Otsu);// 用来计算消除亮光的边界 Mat imageContour = imageRed.Threshold(0, 255, ThresholdTypes.Otsu); // 转成数组 int[,] arrayContourText = BasFunction.Mat2Array(imageContourText); arrayContourText = BasFunction.ConversionRange(arrayContourText); // 将中间亮光置0 int b2, b3; SubFunction.SplitArea(arrayContourText, out b2, out b3); Mat result = new Mat(); BasFunction.SetNumber(imageContour, out result, 0, rows, b2, b3, 0);// 亮光区域置0 imageContour = result; // 闭运算,消除小孔 Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素 Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se); // 将原图分为两部分 int dividingLine = (b2 + b3) / 2; Mat imageContour1 = imageContour; Mat imageContour2 = imageContour; for (int i = 0; i < rows; i++) { for (int j = 0; j < dividingLine; j++) { imageContour2.Set(i, j, 0); } for (int k = dividingLine; k < cols; k++) { imageContour1.Set(i, k, 0); } } // 边缘检测 Mat imageOutline1; Mat imageOutline2; SubFunction.Sobel(imageContour1, out imageOutline1); SubFunction.Sobel(imageContour2, out imageOutline2); // 转成数组 int[,] arrayOutline1 = BasFunction.Mat2Array(imageOutline1); arrayOutline1 = BasFunction.ConversionRange(arrayOutline1); int[,] arrayOutline2 = BasFunction.Mat2Array(imageOutline2); arrayOutline2 = BasFunction.ConversionRange(arrayOutline2); // 计算图像1(左) // 二、计算数据提取区域 // 对图片进行填充 Mat imageFill = new Mat(); SubFunction.Fill(imageContour1, out imageFill); // 计算数据提取区域 int[] dataArea = new int[2]; SubFunction.DataArea2(imageFill, out dataArea); // 三、提取L1,L3,L4,L6 double meanOrdinateLeft1 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft1, dataArea[0], dataArea[1]); double meanOrdinateLeft3 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft3, dataArea[0], dataArea[1], meanOrdinateLeft1); double meanOrdinateLeft4 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft4, dataArea[0], dataArea[1], meanOrdinateLeft3); double meanOrdinateLeft6 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft6, dataArea[0], dataArea[1], meanOrdinateLeft4); // 四、提取L2 double meanOrdinateLeft2 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft1 + 10, (int)meanOrdinateLeft3 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft2); // 五、提取L5 double meanOrdinateLeft5 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft4 + 10, (int)meanOrdinateLeft6 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft5); // 六、提竖线V1,V2 double abscissaVLeft1 = 0; SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft1, (int)meanOrdinateLeft3, (int)meanOrdinateLeft4); double abscissaVLeft2 = 0; SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft2, (int)meanOrdinateLeft3, (int)meanOrdinateLeft4, abscissaVLeft1); // 计算图像2(右) // 二、计算数据提取区域 // 对图片进行填充 Mat imageFill2 = new Mat(); SubFunction.Fill(imageContour2, out imageFill); // 计算数据提取区域 int[] dataArea2 = new int[2]; SubFunction.DataArea2(imageFill2, out dataArea2); // 三、提取L1,L3,L4,L6 double meanOrdinateRight1 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight1, dataArea2[0], dataArea2[1]); double meanOrdinateRight3 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight3, dataArea2[0], dataArea2[1], meanOrdinateRight1); double meanOrdinateRight4 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight4, dataArea2[0], dataArea2[1], meanOrdinateRight3); double meanOrdinateRight6 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight6, dataArea2[0], dataArea2[1], meanOrdinateRight4); // 四、提取L2 double meanOrdinateRight2 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight1 + 10, (int)meanOrdinateRight3 - 10, dataArea2[0], dataArea2[1], out meanOrdinateRight2); // 五、提取L5 double meanOrdinateRight5 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight4 + 10, (int)meanOrdinateRight6 - 10, dataArea2[0], dataArea2[1], out meanOrdinateRight5); // 六、提竖线V1,V2 double abscissaVRight1 = 0; SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight1, (int)meanOrdinateRight3, (int)meanOrdinateRight4); double abscissaVRight2 = 0; SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight2, (int)meanOrdinateRight3, (int)meanOrdinateRight4, abscissaVRight1); // 七、提取上孔径 double kongjingLeft1 = 0; double kongjingLeft2 = 0; double kongjingRight1 = 0; double kongjingRight2 = 0; SubFunction.ExtractVerticalLines(arrayOutline1, out kongjingLeft1, (int)meanOrdinateLeft3, (int)meanOrdinateLeft3 + 20); SubFunction.ExtractVerticalLines(arrayOutline1, out kongjingLeft2, (int)meanOrdinateLeft3, (int)meanOrdinateLeft3 + 20, kongjingLeft1); SubFunction.ExtractVerticalLines2(arrayOutline2, out kongjingRight1, (int)meanOrdinateRight3, (int)meanOrdinateRight3 + 20); SubFunction.ExtractVerticalLines2(arrayOutline2, out kongjingRight2, (int)meanOrdinateRight3, (int)meanOrdinateRight3 + 20, kongjingRight1); // 八、提取下孔径 double kongjingLeft3 = 0; double kongjingLeft4 = 0; double kongjingRight3 = 0; double kongjingRight4 = 0; SubFunction.ExtractVerticalLines(arrayOutline1, out kongjingLeft3, (int)meanOrdinateLeft4 - 20, (int)meanOrdinateLeft4); SubFunction.ExtractVerticalLines(arrayOutline1, out kongjingLeft4, (int)meanOrdinateLeft4 - 20, (int)meanOrdinateLeft4, kongjingLeft3); SubFunction.ExtractVerticalLines2(arrayOutline2, out kongjingRight3, (int)meanOrdinateRight4 - 20, (int)meanOrdinateRight4); SubFunction.ExtractVerticalLines2(arrayOutline2, out kongjingRight4, (int)meanOrdinateRight4 - 20, (int)meanOrdinateRight4, kongjingRight3); // 七、数据计算 // 左 double leftUpperMiantong = meanOrdinateLeft2 - meanOrdinateLeft1; double leftUpperJicaitong = meanOrdinateLeft3 - meanOrdinateLeft2; double leftUpperMian_Jicaitong = meanOrdinateLeft3 - meanOrdinateLeft1; double leftLowerMiantong = meanOrdinateLeft6 - meanOrdinateLeft5; double leftLowerJicaitong = meanOrdinateLeft5 - meanOrdinateLeft4; double leftLowerMian_Jicaitong = meanOrdinateLeft6 - meanOrdinateLeft4; double leftKongtong = abscissaVLeft1 - abscissaVLeft2; // 右 double rightUpperMiantong = meanOrdinateRight2 - meanOrdinateRight1; double rightUpperJicaitong = meanOrdinateRight3 - meanOrdinateRight2; double rightUpperMian_Jicaitong = meanOrdinateRight3 - meanOrdinateRight1; double rightLowerMiantong = meanOrdinateRight6 - meanOrdinateRight5; double rightLowerJicaitong = meanOrdinateRight5 - meanOrdinateRight4; double rightLowerMian_Jicaitong = meanOrdinateRight6 - meanOrdinateRight4; double rightKongtong = abscissaVRight2 - abscissaVRight1; double upperKongjing = kongjingRight2 - kongjingLeft2; double lowerKongjing = kongjingRight4 - kongjingLeft4; // 八、标记 int middleLeft = (dataArea[0] + dataArea[1]) / 2; int middleLeft2 = (int)((meanOrdinateLeft3 + meanOrdinateLeft4) / 2); int middleRight = (dataArea2[0] + dataArea2[1]) / 2; int middleRight2 = (int)((meanOrdinateRight3 + meanOrdinateRight4) / 2); // 图一标记(左) // 上面铜 SubFunction.LabelVertical(image, middleLeft + 40, (int)meanOrdinateLeft1, middleLeft + 40, (int)meanOrdinateLeft2, leftUpperMiantong); // 上基材铜 SubFunction.LabelVertical(image, middleLeft - 40, (int)meanOrdinateLeft2, middleLeft - 40, (int)meanOrdinateLeft3, leftUpperJicaitong); // 上面铜+基材铜 SubFunction.LabelVertical(image, middleLeft, (int)meanOrdinateLeft1, middleLeft, (int)meanOrdinateLeft3, leftUpperMian_Jicaitong); // 下面铜 SubFunction.LabelVertical(image, middleLeft + 40, (int)meanOrdinateLeft5, middleLeft + 40, (int)meanOrdinateLeft6, leftLowerMiantong); // 下基材铜 SubFunction.LabelVertical(image, middleLeft - 40, (int)meanOrdinateLeft4, middleLeft - 40, (int)meanOrdinateLeft5, leftLowerJicaitong); // 下面铜+基材铜 SubFunction.LabelVertical(image, middleLeft, (int)meanOrdinateLeft4, middleLeft, (int)meanOrdinateLeft6, leftLowerMian_Jicaitong); // 孔铜 SubFunction.LableHorizontal(image, (int)abscissaVLeft2, middleLeft2, (int)abscissaVLeft1, middleLeft2, leftKongtong); // 图二标记(右) // 上面铜 SubFunction.LabelVertical(image, middleRight + 40, (int)meanOrdinateRight1, middleRight + 40, (int)meanOrdinateRight2, rightUpperMiantong); // 上基材铜 SubFunction.LabelVertical(image, middleRight - 40, (int)meanOrdinateRight2, middleRight - 40, (int)meanOrdinateRight3, rightUpperJicaitong); // 上面铜+基材铜 SubFunction.LabelVertical(image, middleRight, (int)meanOrdinateRight1, middleRight, (int)meanOrdinateRight3, rightUpperMian_Jicaitong); // 下面铜 SubFunction.LabelVertical(image, middleRight + 40, (int)meanOrdinateRight5, middleRight + 40, (int)meanOrdinateRight6, rightLowerMiantong); // 下基材铜 SubFunction.LabelVertical(image, middleRight - 40, (int)meanOrdinateRight4, middleRight - 40, (int)meanOrdinateRight5, rightLowerJicaitong); // 下面铜+基材铜 SubFunction.LabelVertical(image, middleRight, (int)meanOrdinateRight4, middleRight, (int)meanOrdinateRight6, rightLowerMian_Jicaitong); // 孔铜 SubFunction.LableHorizontal(image, (int)abscissaVRight2, middleRight2, (int)abscissaVRight1, middleRight2, rightKongtong); // 上孔径 SubFunction.LableHorizontal(image, (int)kongjingLeft2, (int)meanOrdinateLeft1, (int)kongjingRight2, (int)meanOrdinateLeft1, upperKongjing); // 下孔径 SubFunction.LableHorizontal(image, (int)kongjingLeft4, (int)meanOrdinateLeft6, (int)kongjingRight4, (int)meanOrdinateLeft6, lowerKongjing); } public static void CaokongSancengZhong(string fileName) { // 一、预处理 // 读取图片 Mat image = new Mat(fileName, ImreadModes.Color); //获取图片的长宽 int rows = image.Rows; int cols = image.Cols; // 转换为灰度图 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); //获得蓝色,绿色,红色通道图片 Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type()); SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed); // 重新修改比例调色 Mat imageNew = new Mat(imageRed.Size(), imageRed.Type()); imageNew = 0.9 * imageGreen + 0.1 * imageRed; // 均值滤波 Mat imageFilter = new Mat(); Cv2.Blur(imageNew, imageFilter, new Size(5, 5)); // 二值化,获得目标区域 Mat imageContourText = imageFilter.Threshold(0, 255, ThresholdTypes.Otsu);// 用来计算消除亮光的边界 Mat imageContour = imageRed.Threshold(0, 255, ThresholdTypes.Otsu); // 转成数组 int[,] arrayContourText = BasFunction.Mat2Array(imageContourText); arrayContourText = BasFunction.ConversionRange(arrayContourText); // 将中间亮光置0 int b2, b3; SubFunction.SplitArea(arrayContourText, out b2, out b3); Mat result = new Mat(); BasFunction.SetNumber(imageContour, out result, 0, rows, b2, b3, 0);// 亮光区域置0 imageContour = result; // 闭运算,消除小孔 Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素 Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se); // 将原图分为两部分 int dividingLine = (b2 + b3) / 2; Mat imageContour1 = imageContour; Mat imageContour2 = imageContour; for (int i = 0; i < rows; i++) { for (int j = 0; j < dividingLine; j++) { imageContour2.Set(i, j, 0); } for (int k = dividingLine; k < cols; k++) { imageContour1.Set(i, k, 0); } } // 边缘检测 Mat imageOutline1; Mat imageOutline2; SubFunction.Sobel(imageContour1, out imageOutline1); SubFunction.Sobel(imageContour2, out imageOutline2); // 转成数组 int[,] arrayOutline1 = BasFunction.Mat2Array(imageOutline1); arrayOutline1 = BasFunction.ConversionRange(arrayOutline1); int[,] arrayOutline2 = BasFunction.Mat2Array(imageOutline2); arrayOutline2 = BasFunction.ConversionRange(arrayOutline2); // 计算图像1(左) // 二、计算数据提取区域 // 对图片进行填充 Mat imageFill = new Mat(); SubFunction.Fill(imageContour1, out imageFill); // 计算数据提取区域 int[] dataArea = new int[2]; SubFunction.DataArea2(imageFill, out dataArea); // 三、提取L1,L3,L4,L5, L6, L8 double meanOrdinateLeft1 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft1, dataArea[0], dataArea[1]); double meanOrdinateLeft3 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft3, dataArea[0], dataArea[1], meanOrdinateLeft1); double meanOrdinateLeft4 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft4, dataArea[0], dataArea[1], meanOrdinateLeft3); double meanOrdinateLeft5 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft5, dataArea[0], dataArea[1], meanOrdinateLeft4); double meanOrdinateLeft6 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft6, dataArea[0], dataArea[1], meanOrdinateLeft5); double meanOrdinateLeft8 = 0; SubFunction.ExtractLines(arrayOutline1, out meanOrdinateLeft8, dataArea[0], dataArea[1], meanOrdinateLeft6); // 四、提取L2 double meanOrdinateLeft2 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft1 + 10, (int)meanOrdinateLeft3 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft2); // 五、提取L7 double meanOrdinateLeft7 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateLeft6 + 10, (int)meanOrdinateLeft8 - 10, dataArea[0], dataArea[1], out meanOrdinateLeft7); // 六、提取胶体线 Mat imageGlue = new Mat(); SubFunction.GlueArea(imageContour1, imageRed, out imageGlue, (int)meanOrdinateLeft5 + 10, (int)meanOrdinateLeft6 - 10, dataArea[0], dataArea[1]); // 转数组 int[,] arrayGlue = BasFunction.Mat2Array(imageGlue); arrayGlue = BasFunction.ConversionRange(arrayGlue); // 提取胶体线 double meanOrdinateLG = 0; SubFunction.InsideLine(imageGlue, (int)meanOrdinateLeft5 + 15, (int)meanOrdinateLeft6 - 15, dataArea[0], dataArea[1], out meanOrdinateLG); // 七、提竖线V1,V2, V3, V4 double abscissaVLeft1 = 0; SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft1, (int)meanOrdinateLeft3, (int)meanOrdinateLeft4); double abscissaVLeft2 = 0; SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft2, (int)meanOrdinateLeft3, (int)meanOrdinateLeft4, abscissaVLeft1); double abscissaVLeft3 = 0; SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft3, (int)meanOrdinateLG, (int)meanOrdinateLeft6); double abscissaVLeft4 = 0; SubFunction.ExtractVerticalLines(arrayOutline1, out abscissaVLeft4, (int)meanOrdinateLG, (int)meanOrdinateLeft6, abscissaVLeft3); // 八、计算粗糙度 int cucaoduLeft = 0; int[] cucaoduZuobiaoLeft = new int[2]; SubFunction.Cucaodu(arrayOutline1, (int)meanOrdinateLeft5 + 60, (int)meanOrdinateLeft6 - 30, (int)abscissaVLeft4, out cucaoduLeft, out cucaoduZuobiaoLeft); // 计算图像2(右) // 二、计算数据提取区域 // 对图片进行填充 Mat imageFill2 = new Mat(); SubFunction.Fill(imageContour2, out imageFill); // 计算数据提取区域 int[] dataArea2 = new int[2]; SubFunction.DataArea2(imageFill2, out dataArea2); // 三、提取L1,L3,L4,L5, L6, L8 double meanOrdinateRight1 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight1, dataArea2[0], dataArea2[1]); double meanOrdinateRight3 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight3, dataArea2[0], dataArea2[1], meanOrdinateRight1); double meanOrdinateRight4 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight4, dataArea2[0], dataArea2[1], meanOrdinateRight3); double meanOrdinateRight5 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight5, dataArea2[0], dataArea2[1], meanOrdinateRight4); double meanOrdinateRight6 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight6, dataArea2[0], dataArea2[1], meanOrdinateRight5); double meanOrdinateRight8 = 0; SubFunction.ExtractLines(arrayOutline2, out meanOrdinateRight8, dataArea2[0], dataArea2[1], meanOrdinateRight6); // 四、提取L2 double meanOrdinateRight2 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight1 + 10, (int)meanOrdinateRight3 - 10, dataArea2[0], dataArea2[1], out meanOrdinateRight2); // 五、提取L5 double meanOrdinateRight7 = 0; SubFunction.InsideLine(imageGreen, (int)meanOrdinateRight6 + 10, (int)meanOrdinateRight8 - 10, dataArea2[0], dataArea2[1], out meanOrdinateRight7); // 六、提取胶体线 Mat imageGlue2 = new Mat(); SubFunction.GlueArea(imageContour2, imageRed, out imageGlue2, (int)meanOrdinateRight5 + 10, (int)meanOrdinateRight6 - 10, dataArea2[0], dataArea2[1]); // 转数组 int[,] arrayGlue2 = BasFunction.Mat2Array(imageGlue2); arrayGlue2 = BasFunction.ConversionRange(arrayGlue2); // 提取胶体线 double meanOrdinateRG = 0; SubFunction.InsideLine(imageGlue, (int)meanOrdinateRight5 + 15, (int)meanOrdinateRight6 - 15, dataArea2[0], dataArea2[1], out meanOrdinateRG); // 七 、提竖线V1,V2, V3, V4 double abscissaVRight1 = 0; SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight1, (int)meanOrdinateRight3, (int)meanOrdinateRight4); double abscissaVRight2 = 0; SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight2, (int)meanOrdinateRight3, (int)meanOrdinateRight4, abscissaVRight1); double abscissaVRight3 = 0; SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight3, (int)meanOrdinateRG, (int)meanOrdinateRight6); double abscissaVRight4 = 0; SubFunction.ExtractVerticalLines2(arrayOutline2, out abscissaVRight4, (int)meanOrdinateRG, (int)meanOrdinateRight6, abscissaVRight3); // 八、计算粗糙度 int cucaoduRight = 0; int[] cucaoduZuobiaoRight = new int[2]; SubFunction.Cucaodu(arrayOutline2, (int)meanOrdinateRight5 + 60, (int)meanOrdinateRight6 - 30, (int)abscissaVRight4, out cucaoduRight, out cucaoduZuobiaoRight); // 九、数据计算 // 左 double leftUpperMiantong = meanOrdinateLeft2 - meanOrdinateLeft1; double leftUpperJicaitong = meanOrdinateLeft3 - meanOrdinateLeft2; double leftUpperMian_Jicaitong = meanOrdinateLeft3 - meanOrdinateLeft1; double leftLowerMiantong = meanOrdinateLeft6 - meanOrdinateLeft5; double leftLowerJicaitong = meanOrdinateLeft5 - meanOrdinateLeft4; double leftLowerMian_Jicaitong = meanOrdinateLeft6 - meanOrdinateLeft4; double leftKongtong1 = abscissaVLeft1 - abscissaVLeft2; double leftKongtong2 = abscissaVLeft3 - abscissaVLeft4; // 右 double rightUpperMiantong = meanOrdinateRight2 - meanOrdinateRight1; double rightUpperJicaitong = meanOrdinateRight3 - meanOrdinateRight2; double rightUpperMian_Jicaitong = meanOrdinateRight3 - meanOrdinateRight1; double rightLowerMiantong = meanOrdinateRight6 - meanOrdinateRight5; double rightLowerJicaitong = meanOrdinateRight5 - meanOrdinateRight4; double rightLowerMian_Jicaitong = meanOrdinateRight6 - meanOrdinateRight4; double rightKongtong1 = abscissaVRight2 - abscissaVRight1; double rightKongtong2 = abscissaVRight4 - abscissaVRight3; double upperKongjing = abscissaVRight2 - abscissaVLeft2; ; double lowerKongjing = abscissaVRight4 - abscissaVLeft4; // 八、标记 int middleLeft = (dataArea[0] + dataArea[1]) / 2;// 左面铜+基材铜横坐标 int middleLeft2 = (int)((meanOrdinateLeft3 + meanOrdinateLeft4) / 2);// 左孔铜1纵坐标 int middleLeft3 = (int)((meanOrdinateLG + meanOrdinateLeft6) / 2);// 左孔铜2纵坐标 int middleRight = (dataArea2[0] + dataArea2[1]) / 2;// 右面铜+基材铜横坐标 int middleRight2 = (int)((meanOrdinateRight3 + meanOrdinateRight4) / 2);// 右孔铜1纵坐标 int middleRight3 = (int)((meanOrdinateRG + meanOrdinateRight6) / 2);// 右孔铜2纵坐标 // 图一标记(左) // 上面铜 SubFunction.LabelVertical(image, middleLeft + 40, (int)meanOrdinateLeft1, middleLeft + 40, (int)meanOrdinateLeft2, leftUpperMiantong); // 上基材铜 SubFunction.LabelVertical(image, middleLeft - 40, (int)meanOrdinateLeft2, middleLeft - 40, (int)meanOrdinateLeft3, leftUpperJicaitong); // 上面铜+基材铜 SubFunction.LabelVertical(image, middleLeft, (int)meanOrdinateLeft1, middleLeft, (int)meanOrdinateLeft3, leftUpperMian_Jicaitong); // 下面铜 SubFunction.LabelVertical(image, middleLeft + 40, (int)meanOrdinateLeft5, middleLeft + 40, (int)meanOrdinateLeft6, leftLowerMiantong); // 下基材铜 SubFunction.LabelVertical(image, middleLeft - 40, (int)meanOrdinateLeft4, middleLeft - 40, (int)meanOrdinateLeft5, leftLowerJicaitong); // 下面铜+基材铜 SubFunction.LabelVertical(image, middleLeft, (int)meanOrdinateLeft4, middleLeft, (int)meanOrdinateLeft6, leftLowerMian_Jicaitong); // 孔铜 SubFunction.LableHorizontal(image, (int)abscissaVLeft2, middleLeft2, (int)abscissaVLeft1, middleLeft2, leftKongtong1); SubFunction.LableHorizontal(image, (int)abscissaVLeft4, middleLeft3, (int)abscissaVLeft3, middleLeft3, leftKongtong2); // 图二标记(右) // 上面铜 SubFunction.LabelVertical(image, middleRight + 40, (int)meanOrdinateRight1, middleRight + 40, (int)meanOrdinateRight2, rightUpperMiantong); // 上基材铜 SubFunction.LabelVertical(image, middleRight - 40, (int)meanOrdinateRight2, middleRight - 40, (int)meanOrdinateRight3, rightUpperJicaitong); // 上面铜+基材铜 SubFunction.LabelVertical(image, middleRight, (int)meanOrdinateRight1, middleRight, (int)meanOrdinateRight3, rightUpperMian_Jicaitong); // 下面铜 SubFunction.LabelVertical(image, middleRight + 40, (int)meanOrdinateRight5, middleRight + 40, (int)meanOrdinateRight6, rightLowerMiantong); // 下基材铜 SubFunction.LabelVertical(image, middleRight - 40, (int)meanOrdinateRight4, middleRight - 40, (int)meanOrdinateRight5, rightLowerJicaitong); // 下面铜+基材铜 SubFunction.LabelVertical(image, middleRight, (int)meanOrdinateRight4, middleRight, (int)meanOrdinateRight6, rightLowerMian_Jicaitong); // 孔铜 SubFunction.LableHorizontal(image, (int)abscissaVRight2, middleRight2, (int)abscissaVRight1, middleRight2, rightKongtong1); SubFunction.LableHorizontal(image, (int)abscissaVRight4, middleRight3, (int)abscissaVRight3, middleRight3, rightKongtong2); // 上孔径 SubFunction.LableHorizontal(image, (int)abscissaVLeft2, (int)meanOrdinateLeft1, (int)abscissaVRight2, (int)meanOrdinateLeft1, upperKongjing); // 下孔径 SubFunction.LableHorizontal(image, (int)abscissaVLeft4, (int)meanOrdinateLeft6, (int)abscissaVRight4, (int)meanOrdinateLeft6, lowerKongjing); } public static void ShikeyinziDanceng(string fileName) { // 一、预处理 // 读取图片 Mat image = new Mat(fileName, ImreadModes.Color); //获取图片的长宽 int rows = image.Rows; int cols = image.Cols; // 转换为灰度图 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); //获得蓝色,绿色,红色通道图片 Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type()); SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed); // 二值化,获得目标区域 Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu); // 闭运算,消除小孔 Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素 Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se); // 转成数组 int[,] arrayContour = BasFunction.Mat2Array(imageContour); arrayContour = BasFunction.ConversionRange(arrayContour); // 选定检测区域 int[] dataArea = new int[4]; SubFunction.SKYZDataArea(imageContour, out dataArea); // 截取检测区域 int[,] arrayData = BasFunction.InterceptArray(arrayContour, dataArea[0], dataArea[1], dataArea[2], dataArea[3]); // 计算上横线位置 int[] upperX = new int[2]; SubFunction.UpperLine(arrayData, dataArea, out upperX); // 计算上、下顶点坐标 int upperY; int lowerY; SubFunction.LowerLine(arrayData,(dataArea[3]-dataArea[2])/2, out upperY,out lowerY); // 计算数据 int shangfu = upperX[1] - upperX[0]; int xiafu = dataArea[3] - dataArea[2]; int tonghou = lowerY - upperY; // 标记 // 上幅 SubFunction.LableHorizontal(image, upperX[0]+dataArea[2], upperY+dataArea[0] - 10, upperX[1] + dataArea[2], upperY + dataArea[0] - 10, shangfu); // 下幅 SubFunction.LableHorizontal(image, dataArea[2], lowerY + dataArea[0] + 10, dataArea[3], lowerY + dataArea[0] + 10, xiafu); // 铜厚 int middle = (upperX[0] + upperX[1]) / 2; SubFunction.LabelVertical(image, middle + dataArea[2], upperY + dataArea[0], middle + dataArea[2], lowerY + dataArea[0], tonghou); // 保存 Cv2.ImWrite(@"D:\蚀刻因子单层.jpg",image); // 显示 new Window("demo1", WindowMode.Normal, image); Cv2.WaitKey(0); } public static void ShikeyinziShuangceng(string fileName) { // 一、预处理 // 读取图片 Mat image = new Mat(fileName, ImreadModes.Color); //获取图片的长宽 int rows = image.Rows; int cols = image.Cols; // 转换为灰度图 Mat imageGray = image.CvtColor(ColorConversionCodes.BGR2GRAY); //获得蓝色,绿色,红色通道图片 Mat imageBlue, imageGreen, imageRed = new Mat(imageGray.Size(), imageGray.Type()); SubFunction.SeparateRGB(image, out imageBlue, out imageGreen, out imageRed); // 二值化,获得目标区域 Mat imageContour = imageGray.Threshold(0, 255, ThresholdTypes.Otsu); // 闭运算,消除小孔 Mat se = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));// 结构元素 Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Close, se); // 开运算,去除小面积 Mat se2 = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3)); Cv2.MorphologyEx(imageContour, imageContour, MorphTypes.Open, se2); // 转成数组 int[,] arrayContour = BasFunction.Mat2Array(imageContour); arrayContour = BasFunction.ConversionRange(arrayContour); // 选定检测区域 int[] dataArea = new int[4]; SubFunction.SKYZDataArea(imageContour, out dataArea); // 截取检测区域 int[,] arrayData = BasFunction.InterceptArray(arrayContour, dataArea[0], dataArea[1], dataArea[2], dataArea[3]); // 计算上横线位置 int[] upperX = new int[2]; SubFunction.UpperLine(arrayData, dataArea, out upperX); // 计算上、下顶点坐标 int upperY; int lowerY; SubFunction.LowerLine(arrayData,100, out upperY, out lowerY); // 提取内部线 double insideY = 0; SubFunction.InsideLine(imageGreen, upperY + 30+dataArea[0], lowerY - 50+dataArea[0], dataArea[2]+20, dataArea[3]-20, out insideY); // 计算数据 int shangfu = upperX[1] - upperX[0]; int xiafu = dataArea[3] - dataArea[2]; int tonghou = lowerY+dataArea[0] - (int)insideY; int zonghou = lowerY - upperY; // 标记 // 上幅 SubFunction.LableHorizontal(image, upperX[0]+dataArea[2], upperY - 10+dataArea[0], upperX[1] + dataArea[2], upperY - 10 + dataArea[0], shangfu); // 下幅 SubFunction.LableHorizontal(image, dataArea[2], lowerY + 10 + dataArea[0], dataArea[3], lowerY + 10 + dataArea[0], xiafu); // 总厚 int middle = (upperX[0] + upperX[1]) / 2; SubFunction.LabelVertical(image, dataArea[2]+100, upperY + dataArea[0], dataArea[2]+100, lowerY + dataArea[0], zonghou); // 铜厚 SubFunction.LabelVertical(image, dataArea[3]-100, (int)insideY , dataArea[3]-100, lowerY + dataArea[0], tonghou); // 保存 Cv2.ImWrite(@"D:\蚀刻因子双层.jpg", image); // 显示 new Window("demo1", WindowMode.Normal, image); Cv2.WaitKey(0); } } }