List of usage examples for org.opencv.imgproc Imgproc findContours
public static void findContours(Mat image, List<MatOfPoint> contours, Mat hierarchy, int mode, int method)
From source file:ImageReade.java
public static void detectLetter(Mat img) { ArrayList<Rect> boundRect = new ArrayList<>(); Mat img_gray, img_sobel, img_threshold, element; img_gray = new Mat(); img_sobel = new Mat(); img_threshold = new Mat(); element = new Mat(); Imgproc.cvtColor(img, img_gray, Imgproc.COLOR_BGRA2GRAY); imshow("Rec img_gray", img_gray); Imgproc.Sobel(img_gray, img_sobel, CvType.CV_8U, 1, 0, 3, 1, 0, Imgproc.BORDER_DEFAULT); imshow("Rec img_sobel", img_sobel); Imgproc.threshold(img_sobel, img_threshold, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); imshow("Rec img_threshold", img_threshold); element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(16, 6)); Imgproc.morphologyEx(img_threshold, img_threshold, CV_MOP_CLOSE, element); imshow("Rec img_threshold second", img_threshold); List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); //Imgproc.findContours(img_threshold, contours, new Mat(), Imgproc.RETR_LIST,Imgproc.CHAIN_APPROX_SIMPLE); Imgproc.findContours(img_threshold, contours, new Mat(), 0, 1); for (int i = 0; i < contours.size(); i++) { System.out.println(Imgproc.contourArea(contours.get(i))); // if (Imgproc.contourArea(contours.get(i)) > 100) { // //Imgproc.approxPolyDP( contours.get(i), contours_poly[i], 3, true ); // Rect rect = Imgproc.boundingRect(contours.get(i)); // System.out.println(rect.height); // if (rect.width > rect.height) { // //System.out.println(rect.x +","+rect.y+","+rect.height+","+rect.width); // Core.rectangle(img, new Point(rect.x,rect.y), new Point(rect.x+rect.width,rect.y+rect.height),new Scalar(0,0,255)); // } // // // } if (Imgproc.contourArea(contours.get(i)) > 100) { MatOfPoint2f mMOP2f1 = new MatOfPoint2f(); MatOfPoint2f mMOP2f2 = new MatOfPoint2f(); contours.get(i).convertTo(mMOP2f1, CvType.CV_32FC2); Imgproc.approxPolyDP(mMOP2f1, mMOP2f2, 3, true); mMOP2f2.convertTo(contours.get(i), CvType.CV_32S); Rect rect = Imgproc.boundingRect(contours.get(i)); if (rect.width > rect.height) { Core.rectangle(img, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 0, 255)); }//w w w.j a v a2s . c o m } } imshow("Rec Detected", img); }
From source file:ThirdTry.java
public static void detectLetter(Mat img, Mat m2) { ArrayList<Rect> boundRect = new ArrayList<>(); Mat img_gray, img_sobel, img_threshold, element; img_gray = new Mat(); img_sobel = new Mat(); img_threshold = new Mat(); element = new Mat(); Imgproc.cvtColor(img, img_gray, Imgproc.COLOR_BGRA2GRAY); //imshow("Rec img_gray", img_gray); Imgproc.Sobel(img_gray, img_sobel, CvType.CV_8UC1, 1, 0, 3, 1, 0, Imgproc.BORDER_DEFAULT); //imshow("Rec img_sobel", img_sobel); Imgproc.threshold(m2, img_threshold, 0, 255, CV_THRESH_OTSU + CV_THRESH_BINARY); //imshow("Rec img_threshold", img_threshold); element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 2)); Imgproc.morphologyEx(m2, img_threshold, CV_MOP_CLOSE, element); imshow("Rec img_threshold second", img_threshold); element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(12, 12)); Imgproc.morphologyEx(img_threshold, img_threshold, CV_MOP_CLOSE, element); //imshow("Rec img_threshold second", img_threshold); List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); //Imgproc.findContours(img_threshold, contours, new Mat(), Imgproc.RETR_LIST,Imgproc.CHAIN_APPROX_SIMPLE); Imgproc.findContours(img_threshold, contours, new Mat(), 0, 1); for (int i = 0; i < contours.size(); i++) { System.out.println(Imgproc.contourArea(contours.get(i))); // if (Imgproc.contourArea(contours.get(i)) > 100) { // //Imgproc.approxPolyDP( contours.get(i), contours_poly[i], 3, true ); // Rect rect = Imgproc.boundingRect(contours.get(i)); // System.out.println(rect.height); // if (rect.width > rect.height) { // //System.out.println(rect.x +","+rect.y+","+rect.height+","+rect.width); // Core.rectangle(img, new Point(rect.x,rect.y), new Point(rect.x+rect.width,rect.y+rect.height),new Scalar(0,0,255)); // } // // // } if (Imgproc.contourArea(contours.get(i)) > 100) { MatOfPoint2f mMOP2f1 = new MatOfPoint2f(); MatOfPoint2f mMOP2f2 = new MatOfPoint2f(); contours.get(i).convertTo(mMOP2f1, CvType.CV_32FC2); Imgproc.approxPolyDP(mMOP2f1, mMOP2f2, 3, true); mMOP2f2.convertTo(contours.get(i), CvType.CV_32S); Rect rect = Imgproc.boundingRect(contours.get(i)); if (rect.width > rect.height) { Core.rectangle(img, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 0, 255)); }/*w w w . j a v a 2 s . co m*/ } } //imshow("Rec Detected", img); }
From source file:LicenseDetection.java
public void run() { // ------------------ set up tesseract for later use ------------------ ITesseract tessInstance = new Tesseract(); tessInstance.setDatapath("/Users/BradWilliams/Downloads/Tess4J"); tessInstance.setLanguage("eng"); // ------------------ Save image first ------------------ Mat img;/*ww w .ja v a 2 s . c o m*/ img = Imgcodecs.imread(getClass().getResource("/resources/car_2_shopped2.jpg").getPath()); Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/True_Image.png", img); // ------------------ Convert to grayscale ------------------ Mat imgGray = new Mat(); Imgproc.cvtColor(img, imgGray, Imgproc.COLOR_BGR2GRAY); Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/Gray.png", imgGray); // ------------------ Blur so edge detection wont pick up noise ------------------ Mat imgGaussianBlur = new Mat(); Imgproc.GaussianBlur(imgGray, imgGaussianBlur, new Size(3, 3), 0); Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/gaussian_blur.png", imgGaussianBlur); // ****************** Create image that will be cropped at end of program before OCR *************************** // ------------------ Binary theshold for OCR (used later)------------------ Mat imgThresholdOCR = new Mat(); Imgproc.adaptiveThreshold(imgGaussianBlur, imgThresholdOCR, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 7, 10); //Imgproc.threshold(imgSobel,imgThreshold,120,255,Imgproc.THRESH_TOZERO); Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/imgThresholdOCR.png", imgThresholdOCR); // ------------------ Erosion operation------------------ Mat kern = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_CROSS, new Size(3, 3)); Mat imgErodeOCR = new Mat(); Imgproc.morphologyEx(imgThresholdOCR, imgErodeOCR, Imgproc.MORPH_DILATE, kern); //Imgproc.MORPH_DILATE is performing erosion, wtf? Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/imgErodeOCR.png", imgErodeOCR); //------------------ Dilation operation ------------------ Mat kernall = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_RECT, new Size(3, 3)); Mat imgDilateOCR = new Mat(); Imgproc.morphologyEx(imgErodeOCR, imgDilateOCR, Imgproc.MORPH_ERODE, kernall); Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/imgDilateOCR.png", imgDilateOCR); // ************************************************************************************************************* // // ------------------ Close operation (dilation followed by erosion) to reduce noise ------------------ // Mat k = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_RECT, new Size(3, 3)); // Mat imgCloseOCR = new Mat(); // Imgproc.morphologyEx(imgThresholdOCR,imgCloseOCR,1,k); // Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/imgCloseOCR.png", imgCloseOCR); // ------------------ Sobel vertical edge detection ------------------ Mat imgSobel = new Mat(); Imgproc.Sobel(imgGaussianBlur, imgSobel, -1, 1, 0); Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/imgSobel.png", imgSobel); // ------------------ Binary theshold ------------------ Mat imgThreshold = new Mat(); Imgproc.adaptiveThreshold(imgSobel, imgThreshold, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 99, -60); //Imgproc.threshold(imgSobel,imgThreshold,120,255,Imgproc.THRESH_TOZERO); Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/imgThreshold.png", imgThreshold); // // ------------------ Open operation (erosion followed by dilation) ------------------ // Mat ker = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_CROSS, new Size(3, 2)); // Mat imgOpen = new Mat(); // Imgproc.morphologyEx(imgThreshold,imgOpen,0,ker); // Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/imgOpen.png", imgOpen); // ------------------ Close operation (dilation followed by erosion) to reduce noise ------------------ Mat kernel = Imgproc.getStructuringElement(Imgproc.CV_SHAPE_RECT, new Size(22, 8)); Mat imgClose = new Mat(); Imgproc.morphologyEx(imgThreshold, imgClose, 1, kernel); Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/imgClose.png", imgClose); // ------------------ Find contours ------------------ List<MatOfPoint> contours = new ArrayList<>(); Imgproc.findContours(imgClose, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); // **************************** DEBUG CODE ************************** Mat contourImg = new Mat(imgClose.size(), imgClose.type()); for (int i = 0; i < contours.size(); i++) { Imgproc.drawContours(contourImg, contours, i, new Scalar(255, 255, 255), -1); } Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/contours.png", contourImg); // ****************************************************************** // -------------- Convert contours -------------------- //Convert to MatOfPoint2f so that minAreaRect can be called List<MatOfPoint2f> newContours = new ArrayList<>(); for (MatOfPoint mat : contours) { MatOfPoint2f newPoint = new MatOfPoint2f(mat.toArray()); newContours.add(newPoint); } //Get minAreaRects List<RotatedRect> minAreaRects = new ArrayList<>(); for (MatOfPoint2f mat : newContours) { RotatedRect rect = Imgproc.minAreaRect(mat); /* --------------- BUG WORK AROUND ------------ Possible bug: When converting from MatOfPoint2f to RotatectRect the width height were reversed and the angle was -90 degrees from what it would be if the width and height were correct. When painting rectangle in image, the correct boxes were produced, but performing calculations on rect.angle rect.width, or rect.height yielded unwanted results. The following work around is buggy but works for my purpose */ if (rect.size.width < rect.size.height) { double temp; temp = rect.size.width; rect.size.width = rect.size.height; rect.size.height = temp; rect.angle = rect.angle + 90; } //check aspect ratio and area and angle if (rect.size.width / rect.size.height > 1 && rect.size.width / rect.size.height < 5 && rect.size.width * rect.size.height > 10000 && rect.size.width * rect.size.height < 50000 && Math.abs(rect.angle) < 20) { minAreaRects.add(rect); } //minAreaRects.add(rect); } // **************************** DEBUG CODE ************************** /* The following code is used to draw the rectangles on top of the original image for debugging purposes */ //Draw Rotated Rects Point[] vertices = new Point[4]; Mat imageWithBoxes = img; // Draw color rectangles on top of binary contours // Mat imageWithBoxes = new Mat(); // Mat temp = imgDilateOCR; // Imgproc.cvtColor(temp, imageWithBoxes, Imgproc.COLOR_GRAY2RGB); for (RotatedRect rect : minAreaRects) { rect.points(vertices); for (int i = 0; i < 4; i++) { Imgproc.line(imageWithBoxes, vertices[i], vertices[(i + 1) % 4], new Scalar(0, 0, 255), 2); } } Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/imgWithBoxes.png", imageWithBoxes); // ****************************************************************** // **************************** DEBUG CODE ************************** // for(RotatedRect rect : minAreaRects) { // System.out.println(rect.toString()); // } // ****************************************************************** /* In order to rotate image without cropping it: 1. Create new square image with dimension = diagonal of initial image. 2. Draw initial image into the center of new image. Insert initial image at ROI (Region of Interest) in new image 3. Rotate new image */ //Find diagonal/hypotenuse int hypotenuse = (int) Math.sqrt((img.rows() * img.rows()) + (img.cols() * img.cols())); //New Mat with hypotenuse as height and width Mat rotateSpace = new Mat(hypotenuse, hypotenuse, 0); int ROI_x = (rotateSpace.width() - imgClose.width()) / 2; //x start of ROI int ROI_y = (rotateSpace.height() - imgClose.height()) / 2; //x start of ROI //designate region of interest Rect r = new Rect(ROI_x, ROI_y, imgClose.width(), imgClose.height()); //Insert image into region of interest imgDilateOCR.copyTo(rotateSpace.submat(r)); Mat rotatedTemp = new Mat(); //Mat to hold temporarily rotated mat Mat rectMat = new Mat();//Mat to hold rect contents (needed for looping through pixels) Point[] rectVertices = new Point[4];//Used to build rect to make ROI Rect rec = new Rect(); List<RotatedRect> edgeDensityRects = new ArrayList<>(); //populate new arraylist with rects that satisfy edge density int count = 0; //Loop through Rotated Rects and find edge density for (RotatedRect rect : minAreaRects) { count++; rect.center = new Point((float) ROI_x + rect.center.x, (float) ROI_y + rect.center.y); //rotate image to math orientation of rotated rect rotate(rotateSpace, rotatedTemp, rect.center, rect.angle); //remove rect rotation rect.angle = 0; //get vertices from rotatedRect rect.points(rectVertices); // **************************** DEBUG CODE ************************** // // for (int k = 0; k < 4; k++) { // System.out.println(rectVertices[k]); // Imgproc.line(rotatedTemp, rectVertices[k], rectVertices[(k + 1) % 4], new Scalar(0, 0, 255), 2); // } // // Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/rotated" + count + ".png", rotatedTemp); // ***************************************************************** //build rect to use as ROI rec = new Rect(rectVertices[1], rectVertices[3]); rectMat = rotatedTemp.submat(rec); Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/extracted" + count + ".png", rectMat); //find edge density // // ------------------------ edge density check NOT IMPLEMENTED -------------------- // /* // Checking for edge density was not necessary for this image so it was not implemented due to lack of time // */ // for(int i = 0; i < rectMat.rows(); ++i){ // for(int j = 0; j < rectMat.cols(); ++j){ // // //add up white pixels // } // } // // //check number of white pixels against total pixels // //only add rects to new arraylist that satisfy threshold edgeDensityRects.add(rect); } // **************************** DEBUG CODE ************************** Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/rotatedSpace.png", rotateSpace); //Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/rotatedSpaceROTATED.png", rotatedTemp); //System.out.println(imgGray.type()); // ***************************************************************** // if there is only one rectangle left, its the license plate if (edgeDensityRects.size() == 1) { String result = ""; //Hold result from OCR BufferedImage bimg; Mat cropped; cropped = rectMat.submat(new Rect(20, 50, rectMat.width() - 40, rectMat.height() - 70)); Imgcodecs.imwrite("/Users/BradWilliams/ComputerVisionOut/rectMatCropped.png", cropped); bimg = matToBufferedImage(cropped); BufferedImage image = bimg; try { result = tessInstance.doOCR(image); } catch (TesseractException e) { System.err.println(e.getMessage()); } for (int i = 0; i < 10; ++i) { } result = result.replace("\n", ""); System.out.println(result); CarProfDBImpl db = new CarProfDBImpl(); db.connect("localhost:3306/computer_vision", "root", "*******"); CarProf c = db.getCarProf(result); System.out.print(c.toString()); db.close(); } }
From source file:ac.robinson.ticqr.TickBoxImageParserTask.java
License:Apache License
@Override protected ArrayList<PointF> doInBackground(Void... unused) { Log.d(TAG, "Searching for tick boxes of " + mBoxSize + " size"); // we look for *un-ticked* boxes, rather than ticked, as they are uniform in appearance (and hence easier to // detect) - they show up as a box within a box ArrayList<PointF> centrePoints = new ArrayList<>(); int minimumOuterBoxArea = (int) Math.round(Math.pow(mBoxSize, 2)); int maximumOuterBoxArea = (int) Math.round(Math.pow(mBoxSize * 1.35f, 2)); int minimumInnerBoxArea = (int) Math.round(Math.pow(mBoxSize * 0.5f, 2)); // image adjustment - blurSize, blurSTDev and adaptiveThresholdSize must not be even numbers int blurSize = 9; int blurSTDev = 3; int adaptiveThresholdSize = Math.round(mBoxSize * 3); // (oddness ensured below) int adaptiveThresholdC = 4; // value to add to the mean (can be negative or zero) adaptiveThresholdSize = adaptiveThresholdSize % 2 == 0 ? adaptiveThresholdSize + 1 : adaptiveThresholdSize; // how similar the recognised polygon must be to its actual contour - lower is more similar float outerPolygonSimilarity = 0.045f; float innerPolygonSimilarity = 0.075f; // don't require as much accuracy for the inner part of the tick box // how large the maximum internal angle can be (e.g., for checking square shape) float maxOuterAngleCos = 0.3f; float maxInnerAngleCos = 0.4f; // use OpenCV to recognise boxes that have a box inside them - i.e. an un-ticked tick box // see: http://stackoverflow.com/a/11427501 // Bitmap newBitmap = mBitmap.copy(Bitmap.Config.RGB_565, true); // not needed Mat bitMat = new Mat(); Utils.bitmapToMat(mBitmap, bitMat);// www . j a v a2 s. c o m // blur and convert to grey // alternative (less flexible): Imgproc.medianBlur(bitMat, bitMat, blurSize); Imgproc.GaussianBlur(bitMat, bitMat, new Size(blurSize, blurSize), blurSTDev, blurSTDev); Imgproc.cvtColor(bitMat, bitMat, Imgproc.COLOR_RGB2GRAY); // need 8uC1 (1 channel, unsigned char) image type // perform adaptive thresholding to detect edges // alternative (slower): Imgproc.Canny(bitMat, bitMat, 10, 20, 3, false); Imgproc.adaptiveThreshold(bitMat, bitMat, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY, adaptiveThresholdSize, adaptiveThresholdC); // get the contours in the image, and their hierarchy Mat hierarchyMat = new Mat(); List<MatOfPoint> contours = new ArrayList<>(); Imgproc.findContours(bitMat, contours, hierarchyMat, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE); if (DEBUG) { Imgproc.drawContours(bitMat, contours, -1, new Scalar(30, 255, 255), 1); } // parse the contours and look for a box containing another box, with similar enough sizes int numContours = contours.size(); ArrayList<Integer> searchedContours = new ArrayList<>(); Log.d(TAG, "Found " + numContours + " possible tick box areas"); if (numContours > 0 && !hierarchyMat.empty()) { for (int i = 0; i < numContours; i++) { // the original detected contour MatOfPoint boxPoints = contours.get(i); // hierarchy key: 0 = next sibling num, 1 = previous sibling num, 2 = first child num, 3 = parent num int childBox = (int) hierarchyMat.get(0, i)[2]; // usually the largest child (as we're doing RETR_TREE) if (childBox == -1) { // we only want elements that have children continue; } else { if (searchedContours.contains(childBox)) { if (DEBUG) { Log.d(TAG, "Ignoring duplicate box at first stage: " + childBox); } continue; } else { searchedContours.add(childBox); } } // discard smaller (i.e. noise) outer box areas as soon as possible for speed // used to do Imgproc.isContourConvex(outerPoints) later, but the angle check covers this, so no need double originalArea = Math.abs(Imgproc.contourArea(boxPoints)); if (originalArea < minimumOuterBoxArea) { // if (DEBUG) { // drawPoints(bitMat, boxPoints, new Scalar(255, 255, 255), 1); // Log.d(TAG, "Outer box too small"); // } continue; } if (originalArea > maximumOuterBoxArea) { // if (DEBUG) { // drawPoints(bitMat, boxPoints, new Scalar(255, 255, 255), 1); // Log.d(TAG, "Outer box too big"); // } continue; } // simplify the contours of the outer box - we want to detect four-sided shapes only MatOfPoint2f boxPoints2f = new MatOfPoint2f(boxPoints.toArray()); // Point2f for approxPolyDP Imgproc.approxPolyDP(boxPoints2f, boxPoints2f, outerPolygonSimilarity * Imgproc.arcLength(boxPoints2f, true), true); // simplify the contour if (boxPoints2f.height() != 4) { // height is number of points if (DEBUG) { // drawPoints(bitMat, new MatOfPoint(boxPoints2f.toArray()), new Scalar(255, 255, 255), 1); Log.d(TAG, "Outer box not 4 points"); } continue; } // check that the simplified outer box is approximately a square, angle-wise org.opencv.core.Point[] boxPointsArray = boxPoints2f.toArray(); double maxCosine = 0; for (int j = 0; j < 4; j++) { org.opencv.core.Point pL = boxPointsArray[j]; org.opencv.core.Point pIntersect = boxPointsArray[(j + 1) % 4]; org.opencv.core.Point pR = boxPointsArray[(j + 2) % 4]; getLineAngle(pL, pIntersect, pR); maxCosine = Math.max(maxCosine, getLineAngle(pL, pIntersect, pR)); } if (maxCosine > maxOuterAngleCos) { if (DEBUG) { // drawPoints(bitMat, new MatOfPoint(boxPoints2f.toArray()), new Scalar(255, 255, 255), 1); Log.d(TAG, "Outer angles not square enough"); } continue; } // check that the simplified outer box is approximately a square, line length-wise double minLine = Double.MAX_VALUE; double maxLine = 0; for (int p = 1; p < 4; p++) { org.opencv.core.Point p1 = boxPointsArray[p - 1]; org.opencv.core.Point p2 = boxPointsArray[p]; double xd = p1.x - p2.x; double yd = p1.y - p2.y; double lineLength = Math.sqrt((xd * xd) + (yd * yd)); minLine = Math.min(minLine, lineLength); maxLine = Math.max(maxLine, lineLength); } if (maxLine - minLine > minLine) { if (DEBUG) { // drawPoints(bitMat, new MatOfPoint(boxPoints2f.toArray()), new Scalar(255, 255, 255), 1); Log.d(TAG, "Outer lines not square enough"); } continue; } // draw the outer box if debugging if (DEBUG) { MatOfPoint debugBoxPoints = new MatOfPoint(boxPointsArray); Log.d(TAG, "Potential tick box: " + boxPoints2f.size() + ", " + "area: " + Math.abs(Imgproc.contourArea(debugBoxPoints)) + " (min:" + minimumOuterBoxArea + ", max:" + maximumOuterBoxArea + ")"); drawPoints(bitMat, debugBoxPoints, new Scalar(50, 255, 255), 2); } // loop through the children - they should be in descending size order, but sometimes this is wrong boolean wrongBox = false; while (true) { if (DEBUG) { Log.d(TAG, "Looping with box: " + childBox); } // we've previously tried a child - try the next one // key: 0 = next sibling num, 1 = previous sibling num, 2 = first child num, 3 = parent num if (wrongBox) { childBox = (int) hierarchyMat.get(0, childBox)[0]; if (childBox == -1) { break; } if (searchedContours.contains(childBox)) { if (DEBUG) { Log.d(TAG, "Ignoring duplicate box at loop stage: " + childBox); } break; } else { searchedContours.add(childBox); } //noinspection UnusedAssignment wrongBox = false; } // perhaps this is the outer box - check its child has no children itself // (removed so tiny children (i.e. noise) don't mean we mis-detect an un-ticked box as ticked) // if (hierarchyMat.get(0, childBox)[2] != -1) { // continue; // } // check the size of the child box is large enough boxPoints = contours.get(childBox); originalArea = Math.abs(Imgproc.contourArea(boxPoints)); if (originalArea < minimumInnerBoxArea) { if (DEBUG) { // drawPoints(bitMat, boxPoints, new Scalar(255, 255, 255), 1); Log.d(TAG, "Inner box too small"); } wrongBox = true; continue; } // simplify the contours of the inner box - again, we want four-sided shapes only boxPoints2f = new MatOfPoint2f(boxPoints.toArray()); Imgproc.approxPolyDP(boxPoints2f, boxPoints2f, innerPolygonSimilarity * Imgproc.arcLength(boxPoints2f, true), true); if (boxPoints2f.height() != 4) { // height is number of points // if (DEBUG) { // drawPoints(bitMat, boxPoints, new Scalar(255, 255, 255), 1); // } Log.d(TAG, "Inner box fewer than 4 points"); // TODO: allow > 4 for low quality images? wrongBox = true; continue; } // check that the simplified inner box is approximately a square, angle-wise // higher tolerance because noise means if we get several inners, the box may not be quite square boxPointsArray = boxPoints2f.toArray(); maxCosine = 0; for (int j = 0; j < 4; j++) { org.opencv.core.Point pL = boxPointsArray[j]; org.opencv.core.Point pIntersect = boxPointsArray[(j + 1) % 4]; org.opencv.core.Point pR = boxPointsArray[(j + 2) % 4]; getLineAngle(pL, pIntersect, pR); maxCosine = Math.max(maxCosine, getLineAngle(pL, pIntersect, pR)); } if (maxCosine > maxInnerAngleCos) { Log.d(TAG, "Inner angles not square enough"); wrongBox = true; continue; } // this is probably an inner box - log if debugging if (DEBUG) { Log.d(TAG, "Un-ticked inner box: " + boxPoints2f.size() + ", " + "area: " + Math.abs(Imgproc.contourArea(new MatOfPoint2f(boxPointsArray))) + " (min: " + minimumInnerBoxArea + ")"); } // find the inner box centre double centreX = (boxPointsArray[0].x + boxPointsArray[1].x + boxPointsArray[2].x + boxPointsArray[3].x) / 4f; double centreY = (boxPointsArray[0].y + boxPointsArray[1].y + boxPointsArray[2].y + boxPointsArray[3].y) / 4f; // draw the inner box if debugging if (DEBUG) { drawPoints(bitMat, new MatOfPoint(boxPointsArray), new Scalar(255, 255, 255), 1); Core.circle(bitMat, new org.opencv.core.Point(centreX, centreY), 3, new Scalar(255, 255, 255)); } // add to the list of boxes to check centrePoints.add(new PointF((float) centreX, (float) centreY)); break; } } } Log.d(TAG, "Found " + centrePoints.size() + " un-ticked boxes"); return centrePoints; }
From source file:angryhexclient.OurVision.java
License:Open Source License
/** * Detects the ground in the image.//from w ww. j av a2 s .c o m * @return A list of blocks representing the ground. */ public List<Block> detectGround() { Mat binaryImage = new Mat(new Size(_nWidth, _nHeight), CvType.CV_8U, new Scalar(1)); // We only detect right of this margin. The slingshot has some ground // colors and would partly be detected as ground. This is not what we // want. Trajectories originate at the slingshot, and if there is ground // detected at the slingshot, the agent will think, that none of its // trajectories are valid. Therefore we start with detecting due right // of the slingshot. int startAtX = findSlingshot().x + findSlingshot().width * 2; // Now we create a binary image of the ground areas. White where there // is ground, black otherwise. for (int y = 0; y < _nHeight; y++) { for (int x = 0; x < _nWidth; x++) { if (x > startAtX && isGround(x, y)) binaryImage.put(y, x, 255); else binaryImage.put(y, x, 0); } } Mat smoothedImage = new Mat(new Size(_nWidth, _nHeight), CvType.CV_8U, new Scalar(1)); // This median filter improves the detection tremendously. There are a // whole lot of single pixels that carry ground colors spread all over // the image. We remove them here. Imgproc.medianBlur(binaryImage, smoothedImage, 7); List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); // We use OpenCV to find the contours. Contours are lines, that // represent the boundaries of the objects in the binary image. Imgproc.findContours(smoothedImage, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); ArrayList<Block> result = new ArrayList<Block>(); //Now for every contour, we convert it to blocks for communicating them to DLV. for (MatOfPoint mp : contours) { org.opencv.core.Point[] pts = mp.toArray(); for (int i = 0; i < pts.length - 1; i++) { Block b = new Block((int) pts[i].x, (int) pts[i].y); b.add((int) pts[i + 1].x, (int) pts[i + 1].y); result.add(b); } //One block for the first vertex to the last vertex. Block b = new Block((int) pts[pts.length - 1].x, (int) pts[pts.length - 1].y); b.add((int) pts[0].x, (int) pts[0].y); result.add(b); } return result; }
From source file:br.cefetmg.lsi.opencv.multipleObjectTracking.processing.MultipleObjectTracking.java
License:Open Source License
private void trackFilteredObject(Ball theBall, Mat threshold, Mat cameraFeed) { List<Ball> balls = new ArrayList<Ball>(); Mat temp = new Mat(); threshold.copyTo(temp);//from w ww . ja v a2 s . c om // The two variables below are the return of "findContours" processing. List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); Mat hierarchy = new Mat(); // find contours of filtered image using openCV findContours function Imgproc.findContours(temp, contours, hierarchy, Imgproc.RETR_CCOMP, Imgproc.CHAIN_APPROX_SIMPLE); // use moments method to find our filtered object boolean objectFound = false; if (contours.size() > 0) { int numObjects = contours.size(); //if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter if (numObjects < MAX_NUM_OBJECTS) { for (int i = 0; i < contours.size(); i++) { Moments moment = Imgproc.moments(contours.get(i)); double area = moment.get_m00(); //if the area is less than 20 px by 20px then it is probably just noise //if the area is the same as the 3/2 of the image size, probably just a bad filter //we only want the object with the largest area so we safe a reference area each //iteration and compare it to the area in the next iteration. if (area > MIN_OBJECT_AREA) { Ball ball = new Ball(); ball.setXPos((int) (moment.get_m10() / area)); ball.setYPos((int) (moment.get_m01() / area)); if (theBall != null) { ball.setType(theBall.getType()); ball.setColour(theBall.getColour()); } balls.add(ball); objectFound = true; } else { objectFound = false; } } //let user know you found an object if (objectFound) { //draw object location on screen drawObject(balls, cameraFeed); } } else { Core.putText(cameraFeed, "TOO MUCH NOISE! ADJUST FILTER", new Point(0, 50), 1, 2, new Scalar(0, 0, 255), 2); } } }
From source file:classes.BlobsFinder.java
public void findBlobContours() { Mat grayImage = new Mat(); Imgproc.cvtColor(image, grayImage, Imgproc.COLOR_BGR2GRAY); ImageUtils.saveImage(grayImage, outImageName + "_grayImage.png", request); Mat gaussianImage = new Mat(); Imgproc.GaussianBlur(grayImage, gaussianImage, new Size(0, 0), 3); Core.addWeighted(grayImage, 1.5, gaussianImage, -1, 0, gaussianImage); ImageUtils.saveImage(gaussianImage, outImageName + "_gaussianGrayImage.png", request); Mat binaryImage = new Mat(); Imgproc.adaptiveThreshold(gaussianImage, binaryImage, 255, Imgproc.ADAPTIVE_THRESH_GAUSSIAN_C, Imgproc.THRESH_BINARY_INV, 15, 4); ImageUtils.saveImage(binaryImage, outImageName + "_binaryImage.png", request); Mat erodedImage = new Mat(); binaryImage.copyTo(erodedImage);//from ww w .j a v a 2 s . co m Mat structuringElement = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3)); Point anchor = new Point(-1, -1); Imgproc.morphologyEx(erodedImage, erodedImage, Imgproc.MORPH_CLOSE, structuringElement, anchor, 1); ImageUtils.saveImage(erodedImage, outImageName + "_erodedImage.png", request); List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); Imgproc.findContours(erodedImage, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); Mat originalContoursImage = new Mat(image.size(), CvType.CV_8UC1, new Scalar(0)); Scalar contourColor = new Scalar(255); int thickness = -1; // Thicknes should be lower than zero in order to drawn the filled contours Imgproc.drawContours(originalContoursImage, contours, -1, contourColor, thickness); // Drawing all the contours found ImageUtils.saveImage(originalContoursImage, outImageName + "_originalContoursImage.png", request); Mat erodedContoursImage = new Mat(); Imgproc.erode(originalContoursImage, erodedContoursImage, structuringElement, anchor, 1); ImageUtils.saveImage(erodedContoursImage, outImageName + "_erodedContoursImage.png", request); ArrayList<MatOfPoint> finalContours = new ArrayList<MatOfPoint>(); Mat finalContourImage = new Mat(image.size(), CvType.CV_8UC1, new Scalar(0)); Imgproc.findContours(erodedContoursImage, finalContours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE); for (int i = 0; i < finalContours.size(); i++) { MatOfPoint currentContour = finalContours.get(i); double area = Imgproc.contourArea(currentContour); if (area > MIN_AREA) { validContours.add(currentContour); String fabricPath = generateFabricPathString(currentContour); contourPaths.add(fabricPath); Rect boundingRect = Imgproc.boundingRect(currentContour); topLeftCorners.add(boundingRect.tl()); contoursAreas.add(area); } } // Drawing ALL the valid contours Imgproc.drawContours(finalContourImage, validContours, -1, contourColor, thickness); ImageUtils.saveImage(finalContourImage, outImageName + "_finalContourImage.png", request); }
From source file:classes.FloodFiller.java
private void fillFrom(Point seed, int lo, int up, Scalar backgroundColor, Scalar contourFillingColor) { Mat object = ObjectGenerator.extract(image, seed.x, seed.y, 10, 10); this.meanColor = Core.mean(object); Rect ccomp = new Rect(); Mat mask = Mat.zeros(image.rows() + 2, image.cols() + 2, CvType.CV_8UC1); int connectivity = 4; int newMaskVal = 255; int ffillMode = 1; int flags = connectivity + (newMaskVal << 8) + (ffillMode == 1 ? Imgproc.FLOODFILL_FIXED_RANGE : 0); Scalar newVal = new Scalar(0.299, 0.587, 0.114); Imgproc.threshold(mask, mask, 1, 128, Imgproc.THRESH_BINARY); filledArea = Imgproc.floodFill(image.clone(), mask, seed, newVal, ccomp, new Scalar(lo, lo, lo), new Scalar(up, up, up), flags); // Highgui.imwrite("mask.png", mask); ImageUtils.saveImage(mask, "mask.png", request); morphologicalImage = new Mat(image.size(), CvType.CV_8UC3); Mat element = new Mat(3, 3, CvType.CV_8U, new Scalar(1)); ArrayList<Mat> mask3 = new ArrayList<Mat>(); mask3.add(mask);/*from w w w . j a v a 2 s . c om*/ mask3.add(mask); mask3.add(mask); Core.merge(mask3, mask); // Applying morphological filters Imgproc.erode(mask, morphologicalImage, element); Imgproc.morphologyEx(morphologicalImage, morphologicalImage, Imgproc.MORPH_CLOSE, element, new Point(-1, -1), 9); Imgproc.morphologyEx(morphologicalImage, morphologicalImage, Imgproc.MORPH_OPEN, element, new Point(-1, -1), 2); Imgproc.resize(morphologicalImage, morphologicalImage, image.size()); // Highgui.imwrite("morphologicalImage.png", morphologicalImage); ImageUtils.saveImage(morphologicalImage, "morphologicalImage.png", request); List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); Core.split(mask, mask3); Mat binarymorphologicalImage = mask3.get(0); Imgproc.findContours(binarymorphologicalImage.clone(), contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_NONE); contoursImage = new Mat(image.size(), CvType.CV_8UC3, backgroundColor); int thickness = -1; // Thicknes should be lower than zero in order to drawn the filled contours Imgproc.drawContours(contoursImage, contours, -1, contourFillingColor, thickness); // Drawing all the contours found // Highgui.imwrite("allContoursImage.png", contoursImage); ImageUtils.saveImage(contoursImage, "allContoursImage.png", request); if (contours.size() > 1) { int minContourWith = 20; int minContourHeight = 20; int maxContourWith = 6400 / 2; int maxContourHeight = 4800 / 2; contours = filterContours(contours, minContourWith, minContourHeight, maxContourWith, maxContourHeight); } if (contours.size() > 0) { MatOfPoint biggestContour = contours.get(0); // getting the biggest contour contourArea = Imgproc.contourArea(biggestContour); if (contours.size() > 1) { biggestContour = Collections.max(contours, new ContourComparator()); // getting the biggest contour in case there are more than one } Point[] points = biggestContour.toArray(); path = "M " + (int) points[0].x + " " + (int) points[0].y + " "; for (int i = 1; i < points.length; ++i) { Point v = points[i]; path += "L " + (int) v.x + " " + (int) v.y + " "; } path += "Z"; biggestContourImage = new Mat(image.size(), CvType.CV_8UC3, backgroundColor); Imgproc.drawContours(biggestContourImage, contours, 0, contourFillingColor, thickness); // Highgui.imwrite("biggestContourImage.png", biggestContourImage); ImageUtils.saveImage(biggestContourImage, "biggestContourImage.png", request); Mat maskForColorExtraction = biggestContourImage.clone(); if (isWhite(backgroundColor)) { Imgproc.dilate(maskForColorExtraction, maskForColorExtraction, new Mat(), new Point(-1, -1), 3); } else { Imgproc.erode(maskForColorExtraction, maskForColorExtraction, new Mat(), new Point(-1, -1), 3); } // Highgui.imwrite("maskForColorExtraction.png", maskForColorExtraction); ImageUtils.saveImage(maskForColorExtraction, "maskForColorExtraction.png", request); Mat extractedColor = new Mat(); if (isBlack(backgroundColor) && isWhite(contourFillingColor)) { Core.bitwise_and(maskForColorExtraction, image, extractedColor); } else { Core.bitwise_or(maskForColorExtraction, image, extractedColor); } // Highgui.imwrite("extractedColor.png", extractedColor); ImageUtils.saveImage(extractedColor, "extractedColor.png", request); computedSearchWindow = Imgproc.boundingRect(biggestContour); topLeftCorner = computedSearchWindow.tl(); Rect croppingRect = new Rect(computedSearchWindow.x, computedSearchWindow.y, computedSearchWindow.width - 1, computedSearchWindow.height - 1); Mat imageForTextRecognition = new Mat(extractedColor.clone(), croppingRect); // Highgui.imwrite(outImageName, imageForTextRecognition); ImageUtils.saveImage(imageForTextRecognition, outImageName, request); // // // Mat data = new Mat(imageForTextRecognition.size(), CvType.CV_8UC3, backgroundColor); // imageForTextRecognition.copyTo(data); // data.convertTo(data, CvType.CV_8UC3); // // // The meanColor variable represents the color in the GBR space, the following line transforms this to the RGB color space, which // // is assumed in the prepareImage method of the TextRecognitionPreparer class // Scalar userColor = new Scalar(meanColor.val[2], meanColor.val[1], meanColor.val[0]); // // ArrayList<String> recognizableImageNames = TextRecognitionPreparer.generateRecognizableImagesNames(data, backgroundColor, userColor); // for (String imageName : recognizableImageNames) { // // try { // // First recognition step // String recognizedText = TextRecognizer.recognize(imageName, true).trim(); // if (recognizedText != null && !recognizedText.isEmpty()) { // recognizedStrings.add(recognizedText); // } // // Second recognition step // recognizedText = TextRecognizer.recognize(imageName, false).trim(); // if (recognizedText != null && !recognizedText.isEmpty()) { // recognizedStrings.add(recognizedText); // } // // } catch (Exception e) { // } // } // //// ArrayList<BufferedImage> recognizableBufferedImages = TextRecognitionPreparer.generateRecognizableBufferedImages(data, backgroundColor, userColor); //// for (BufferedImage bufferedImage : recognizableBufferedImages) { //// try { //// // First recognition step //// String recognizedText = TextRecognizer.recognize(bufferedImage, true).trim(); //// if (recognizedText != null && !recognizedText.isEmpty()) { //// recognizedStrings.add(recognizedText); //// } //// // Second recognition step //// recognizedText = TextRecognizer.recognize(bufferedImage, false).trim(); //// if (recognizedText != null && !recognizedText.isEmpty()) { //// recognizedStrings.add(recognizedText); //// } //// //// } catch (Exception e) { //// } //// } // // // // compute all moments Moments mom = Imgproc.moments(biggestContour); massCenter = new Point(mom.get_m10() / mom.get_m00(), mom.get_m01() / mom.get_m00()); // draw black dot Core.circle(contoursImage, massCenter, 4, contourFillingColor, 8); } }
From source file:classes.ObjectFinder.java
private void computeSearchWindow() { List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); // a vector of contours // retrieve the external contours // all pixels of each contours Imgproc.findContours(this.morphologicalImage.clone(), contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_NONE);//ww w .j av a2 s.co m // Draw black contours on a white image this.contoursImage = new Mat(morphologicalImage.size(), CvType.CV_8U, new Scalar(255)); if (contours.size() > 1) { int minContourWith = 20; int minContourHeight = 20; int maxContourWith = 6400 / 2; int maxContourHeight = 4800 / 2; contours = filterContours(contours, minContourWith, minContourHeight, maxContourWith, maxContourHeight); } if (contours.size() > 1) { Collections.sort(contours, new ContourComparator()); // Sorttig the contours to take ONLY the bigger one } computedSearchWindow = new Rect(); massCenter = new Point(-1, -1); if (contours.size() > 0) { this.firstContour = contours.get(0); Mat contournedImage = this.firstContour; // draw all contours in black with a thickness of 2 Scalar color = new Scalar(0); int thickness = 2; Imgproc.drawContours(contoursImage, contours, 0, color, thickness); // // testing the bounding box computedSearchWindow = Imgproc.boundingRect(this.firstContour); topLeftCorner = computedSearchWindow.tl(); // compute all moments Moments mom = Imgproc.moments(contournedImage); massCenter = new Point(mom.get_m10() / mom.get_m00(), mom.get_m01() / mom.get_m00()); // draw black dot Core.circle(contoursImage, massCenter, 4, color, 8); } }
From source file:cmib_4_4.Countour.java
public static void main(String args[]) { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); Mat image = Highgui.imread("input1.jpg", Highgui.CV_LOAD_IMAGE_GRAYSCALE); Mat image1 = Highgui.imread("input1.jpg", Highgui.CV_LOAD_IMAGE_GRAYSCALE); Mat image4 = Highgui.imread("input1.jpg"); Imgproc.threshold(image1, image1, 0, 255, THRESH_OTSU); Imgproc.Canny(image1, image1, Imgproc.THRESH_BINARY_INV + Imgproc.THRESH_OTSU, Imgproc.THRESH_BINARY_INV + Imgproc.THRESH_OTSU); Mat image2 = Mat.zeros(image.rows() + 2, image.cols() + 2, CV_8U); List<MatOfPoint> contours = new ArrayList<MatOfPoint>(); Imgproc.findContours(image1, contours, new Mat(), Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE); for (int i = 0; i < contours.size(); i++) { if (Imgproc.contourArea(contours.get(i)) > 100) { Rect rect = Imgproc.boundingRect(contours.get(i)); Imgproc.floodFill(image1, image2, new Point(150, 150), new Scalar(255)); Rect rectCrop = new Rect(rect.x, rect.y, rect.width, rect.height); Mat image_roi_rgb = new Mat(image4, rectCrop); Highgui.imwrite("crop2.jpg", image_roi_rgb); if (rect.height > 28) { Core.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 0, 255)); }/* www. jav a 2 s. c o m*/ } } Highgui.imwrite("falciparum2.jpg", image); }