/// <summary> /// Calculate horizontal offset of the vertical line (center) in the binary image /// </summary> /// <param name="src"> binary image </param> /// <returns> horizontal offset of the vertical line </returns> private int CenterOfLine(Mat src) { // sobel in X-direction //Image<Gray, float> sobel = src.Clone().Erode(3).Sobel(1, 0, 3); Mat sobel = new Mat(src.Size(), src.Type()); Imgproc.Erode(src, sobel, Imgproc.GetStructuringElement(Imgproc.MorphRect, new Size(3, 3))); //Imgproc.Sobel(src, sobel, src.Type(), 0, 3); // min max loc double min = 0, max = 0; Core.Core.MinMaxLocResult result = Core.Core.MinMaxLoc(sobel);// MinMaxLoc(sobel, ref min, ref max, ref minLoc, ref maxLoc); // invalid state if (result.MinLoc.X <= result.MaxLoc.X) { return(src.Width() / 2); } return(((int)(result.MinLoc.X) - (int)(result.MaxLoc.X)) / 2 + (int)(result.MaxLoc.X)); }
private IList <MatOfPoint> ProcessImage() { Mat grayMat = new Mat(); Mat blurMat = new Mat(); Mat edgesMat = new Mat(); Mat final = new Mat(); Mat h = new Mat(); IList <MatOfPoint> contours = new JavaList <MatOfPoint>(); OpenCV.Android.Utils.BitmapToMat(originalImage, originalMat); originalImage.Dispose(); Imgproc.CvtColor(originalMat, grayMat, Imgproc.ColorBgr2gray); Imgproc.GaussianBlur(grayMat, blurMat, new OpenCV.Core.Size(3, 3), 0); Imgproc.Canny(blurMat, edgesMat, 10, 250); Mat kernel = Imgproc.GetStructuringElement(Imgproc.MorphRect, new Size(3, 3)); Imgproc.MorphologyEx(edgesMat, final, Imgproc.MorphClose, kernel); Imgproc.FindContours(final, contours, h, Imgproc.RetrExternal, Imgproc.ChainApproxSimple); return(contours); }
/// <summary> /// Run a sliding window algorithm on the bird eye view to find the 2 sides of the lane. /// </summary> /// <param name="birdEye">bird eye image</param> /// <param name="res"> result of windowing </param> /// <param name="windows"> number of stacked windows </param> public void FitLinesInSlidingWindows(Mat birdEye, out Mat res, int windows) { LeftPoints = new List <Point>(); RightPoints = new List <Point>(); // erode by 2x2 kernel Imgproc.Erode(birdEye, birdEye, Imgproc.GetStructuringElement(Imgproc.MorphRect, new Size(2, 2))); // alloc res have the same size and type as bird eye res = new Mat(birdEye.Size(), birdEye.Type()); // convert to BGR for result drawing Imgproc.CvtColor(birdEye, res, Imgproc.ColorGray2bgr); // crop half bottom of bird eye Mat cropped = new Mat(birdEye, new Rect(0, birdEye.Height() / 2, birdEye.Width(), birdEye.Height() / 2)); // find left and right starting point int left, right; SlidingWindowsStartLoc(cropped, out left, out right); // current window locations int currentWindowLeft = left; int currentWindowRight = right; // window settings & buffer int margin = 100; int minpix = 140; int winHeight = birdEye.Height() / windows; // calculate windows for (int i = 0; i < windows; i++) { // calculate window size and location int winYhigh = birdEye.Height() - i * winHeight; int winXleftLow = currentWindowLeft - margin; int winXrightLow = currentWindowRight - margin; Rect leftRect = new Rect(winXleftLow, winYhigh - winHeight, margin * 2, winHeight); Rect rightRect = new Rect(winXrightLow, winYhigh - winHeight, margin * 2, winHeight); Imgproc.Rectangle(res, new Point(leftRect.X, leftRect.Y), new Point(leftRect.X + leftRect.Width, leftRect.Y + leftRect.Height), new Scalar(20, 20, 255), 3); Imgproc.Rectangle(res, new Point(rightRect.X, rightRect.Y), new Point(rightRect.X + rightRect.Width, rightRect.Y + rightRect.Height), new Scalar(20, 20, 255), 3); int goodLeft; int goodRight; // save position LeftPoints.Add(new Point(winXleftLow + margin, winYhigh - (winHeight / 2))); RightPoints.Add(new Point(winXrightLow + margin, winYhigh - (winHeight / 2))); Mat birdEyeROI; birdEyeROI = birdEye.Submat(leftRect); goodLeft = Core.Core.CountNonZero(birdEyeROI); birdEyeROI = birdEye.Submat(rightRect); goodRight = Core.Core.CountNonZero(birdEyeROI); if (goodLeft > minpix) { // recenter birdEyeROI = birdEye.Submat(leftRect); currentWindowLeft = CenterOfLine(birdEyeROI) + leftRect.X; } if (goodRight > minpix) { // recenter birdEyeROI = birdEye.Submat(rightRect); currentWindowRight = CenterOfLine(birdEyeROI) + rightRect.X; } } // Draw midpoints foreach (Point p in LeftPoints) { //res.Draw(new Rectangle(new Point((int)p.X, (int)p.Y), new Size(20, 20)), new Bgr(50, 50, 230), 12); Imgproc.Rectangle(res, new Point((int)p.X, (int)p.Y), new Point(p.X + 20, p.Y + 20), new Scalar(50, 50, 230), 12); } foreach (Point p in RightPoints) { //res.Draw(new Rectangle(new Point((int)p.X, (int)p.Y), new Size(20, 20)), new Bgr(50, 50, 230), 12); Imgproc.Rectangle(res, new Point((int)p.X, (int)p.Y), new Point(p.X + 20, p.Y + 20), new Scalar(50, 50, 230), 12); } BirdEye = res; }
public static async Task <string> detectAndExtractText(Bitmap img) { //Matrix für die Bilder Mat large = new Mat(); Mat small = new Mat(); Mat rgb = new Mat(); //Bild zu Matrix umwandeln Utils.BitmapToMat(img, large); // downsample and use it for processing Imgproc.PyrDown(large, rgb); //Grey Imgproc.CvtColor(rgb, small, Imgproc.ColorBgr2gray); //Gradiant Mat grad = new Mat(); Size morphsize = new Size(3.0, 3.0); Mat morphKernel = Imgproc.GetStructuringElement(Imgproc.MorphEllipse, morphsize); Imgproc.MorphologyEx(small, grad, Imgproc.MorphGradient, morphKernel); //Binarize Mat bw = new Mat(); Imgproc.Threshold(grad, bw, 0.0, 255.0, Imgproc.ThreshBinary | Imgproc.ThreshOtsu); // connect horizontally oriented regions Mat connected = new Mat(); Size connectsize = new Size(9.0, 1.0); morphKernel = Imgproc.GetStructuringElement(Imgproc.MorphRect, connectsize); Imgproc.MorphologyEx(bw, connected, Imgproc.MorphClose, morphKernel); // find contours Mat mask = Mat.Zeros(bw.Size(), CvType.Cv8uc1); JavaList <MatOfPoint> contours = new JavaList <MatOfPoint>(); Mat hierarchy = new Mat(); OpenCV.Core.Point contourPoint = new OpenCV.Core.Point(0, 0); Imgproc.FindContours(connected, contours, hierarchy, Imgproc.RetrCcomp, Imgproc.ChainApproxSimple, contourPoint); Scalar zero = new Scalar(0, 0, 0); Scalar contourscal = new Scalar(255, 255, 255); Scalar rectScalar = new Scalar(0, 255, 0); OpenCV.Core.Rect rect; Mat maskROI; double r; double[] contourInfo; string resulttext = ""; string part; Bitmap bmpOcr; Mat croppedPart; for (int i = 0; i >= 0;) { rect = Imgproc.BoundingRect(contours[i]); maskROI = new Mat(mask, rect); maskROI.SetTo(zero); //fill the contour Imgproc.DrawContours(mask, contours, i, contourscal, Core.Filled); // ratio of non-zero pixels in the filled region r = (double)Core.CountNonZero(maskROI) / (rect.Width * rect.Height); /* assume at least 45% of the area is filled if it contains text */ /* constraints on region size */ /* these two conditions alone are not very robust. better to use something * like the number of significant peaks in a horizontal projection as a third condition */ if (r > .45 && (rect.Height > 8 && rect.Width > 8)) { //Imgproc.Rectangle(rgb, rect.Br(), rect.Tl(), rectScalar, 2); try { croppedPart = rgb.Submat(rect); bmpOcr = Bitmap.CreateBitmap(croppedPart.Width(), croppedPart.Height(), Bitmap.Config.Argb8888); Utils.MatToBitmap(croppedPart, bmpOcr); part = await OCR.getText(bmpOcr); resulttext = resulttext + part; Console.WriteLine("------------------Durchlauf-------------"); } catch (Exception e) { Android.Util.Log.Debug("Fehler", "cropped part data error " + e.Message); } } //Nächste Element bestimmen contourInfo = hierarchy.Get(0, i); i = (int)contourInfo[0]; } return(resulttext); }