Ejemplo n.º 1
0
        public static void LineSpreadFunction(Image <Gray, byte> workImage, out WaferEdgeFit leftLineData, out WaferEdgeFit rightLineData, out WaferEdgeFit topLineData, out WaferEdgeFit bottomLineData)
        {
            int width  = workImage.Width;
            int height = workImage.Height;

            //Recipe? Waferareapercent?
            int darkLimit = 20;

            CvInvoke.Threshold(workImage, workImage, darkLimit, 0, ThresholdType.ToZero);


            FitEdge(workImage, height / 3, 2 * height / 3, 0, width / 8, false, out leftLineData);
            FitEdge(workImage, height / 3, 2 * height / 3, 7 * width / 8, width, false, out rightLineData);
            FitEdge(workImage, 0, height / 8, width / 3, 2 * width / 3, true, out topLineData);
            FitEdge(workImage, 7 * height / 8, height, width / 3, 2 * width / 3, true, out bottomLineData);
        }
Ejemplo n.º 2
0
        public static void FitEdge(Image <Gray, byte> inputImage, int startRow, int endRow, int startCol, int endCol, bool isTopBottom, out WaferEdgeFit edge)
        {
            edge = new WaferEdgeFit();

            Rectangle origRoi = inputImage.ROI;
            Rectangle sideRoi = new Rectangle(startCol, startRow, endCol - startCol, endRow - startRow);

            bool startFromRight = !isTopBottom && startCol > origRoi.Width / 2 || isTopBottom && startRow > origRoi.Height / 2;

            inputImage.ROI = sideRoi;

            int workingWidth  = isTopBottom ? sideRoi.Height : sideRoi.Width;
            int workingHeight = isTopBottom ? sideRoi.Width : sideRoi.Height;

            using (Image <Gray, float> workImage = new Image <Gray, float>(workingWidth, workingHeight))
            {
                double gradientLimit;

                using (Image <Gray, float> sobelImage =
                           isTopBottom ? inputImage.Sobel(0, 1, 3) : inputImage.Sobel(1, 0, 3))
                {
                    using (Image <Gray, float> nullImage = new Image <Gray, float>(sobelImage.Size))
                    {
                        CvInvoke.AbsDiff(sobelImage, nullImage, sobelImage);
                    }

                    using (Image <Gray, byte> mask = new Image <Gray, byte>(sideRoi.Width, sideRoi.Height))
                    {
                        CvInvoke.Threshold(inputImage, mask, 0, 1, ThresholdType.Binary);
                        MCvScalar gradientMean = new MCvScalar();
                        MCvScalar gradientStd  = new MCvScalar();
                        CvInvoke.MeanStdDev(sobelImage, ref gradientMean, ref gradientStd, mask);
                        double nSigma = 5;
                        gradientLimit = gradientMean.V0 + nSigma * gradientStd.V0;
                    }

                    if (isTopBottom)
                    {
                        CvInvoke.Transpose(sobelImage, workImage);
                    }
                    else
                    {
                        sobelImage.CopyTo(workImage);
                    }
                }

                inputImage.ROI = origRoi;

                List <PointF> edgePoints = new List <PointF>();
                List <float>  fullWidthHalfMaximumVals = new List <float>();
                var           sobelData = workImage.Data;
                int           stride    = 1;

                for (int r = 0; r < workingHeight; r += stride)
                {
                    int approxEdgeCol = 0;
                    if (!startFromRight)
                    {
                        for (int c = 0; c < workingWidth; c++)
                        {
                            var currentValue = sobelData[r, c, 0];
                            if (currentValue > gradientLimit)
                            {
                                approxEdgeCol = c;
                                break;
                            }
                        }
                    }
                    else
                    {
                        for (int c = workingWidth - 1; c > 0; c--)
                        {
                            var currentValue = sobelData[r, c, 0];
                            if (currentValue > gradientLimit)
                            {
                                approxEdgeCol = c;
                                break;
                            }
                        }
                    }

                    int   meanEdgeCol     = 0;
                    float maxValue        = 0;
                    var   currentStartCol = Math.Max(approxEdgeCol - 5, 1);
                    var   currentEndCol   = Math.Min(approxEdgeCol + 5 + 1, workingWidth - 1);
                    for (int c = currentStartCol; c < currentEndCol; c++)
                    {
                        if (sobelData[r, c, 0] > maxValue)
                        {
                            maxValue    = sobelData[r, c, 0];
                            meanEdgeCol = c;
                        }
                    }

                    if (!(maxValue > 0))
                    {
                        continue;
                    }

                    float halfMaxLeftValue  = maxValue;
                    float halfMaxRightValue = maxValue;
                    int   halfMaxLeftCol    = meanEdgeCol;
                    int   halfMaxRightCol   = meanEdgeCol;

                    while (halfMaxLeftValue > maxValue / 2 && halfMaxLeftCol >= 0)
                    {
                        halfMaxLeftCol--;
                        halfMaxLeftValue = sobelData[r, halfMaxLeftCol, 0];
                    }
                    while (halfMaxRightValue > maxValue / 2 && halfMaxRightCol < workingWidth)
                    {
                        halfMaxRightCol++;
                        halfMaxRightValue = sobelData[r, halfMaxRightCol, 0];
                    }

                    float fwhm = halfMaxRightCol - halfMaxLeftCol;

                    //Interpolation
                    float dPixel = (maxValue / 2 - halfMaxLeftValue) /
                                   (sobelData[r, halfMaxLeftCol + 1, 0] - halfMaxLeftValue);
                    fwhm  -= dPixel;
                    dPixel = (maxValue / 2 - halfMaxRightValue) /
                             (sobelData[r, halfMaxRightCol - 1, 0] - halfMaxRightValue);
                    fwhm -= dPixel;

                    fullWidthHalfMaximumVals.Add(fwhm);


                    edgePoints.Add(isTopBottom
                        ? new PointF(r + sideRoi.X, meanEdgeCol + sideRoi.Y)
                        : new PointF(r + sideRoi.Y, meanEdgeCol + sideRoi.X));
                }

                VectorOfPointF yvector    = new VectorOfPointF();
                VectorOfFloat  parameters = new VectorOfFloat();
                yvector.Push(edgePoints.ToArray());
                CvInvoke.FitLine(yvector, parameters, DistType.L12, 0, 0.01, 0.01);

                float vx = parameters[0];
                float vy = parameters[1];
                float x0 = parameters[2];
                float y0 = parameters[3];

                edge.FitParams = parameters;
                edge.Slope     = vy / vx;
                edge.Intercept = y0 - edge.Slope * x0;

                fullWidthHalfMaximumVals.Sort();
                int length = fullWidthHalfMaximumVals.Count;

                if (length % 2 == 0)
                {
                    edge.LineSpread = (fullWidthHalfMaximumVals[length / 2 - 1] + fullWidthHalfMaximumVals[length / 2]) / 2;
                }
                else
                {
                    edge.LineSpread = fullWidthHalfMaximumVals[length / 2];
                }

                if (!isTopBottom)
                {
                    edge.InvertedRepresentation = true;
                }
            }
        }