List of usage examples for org.opencv.core Mat rows
public int rows()
From source file:com.shootoff.camera.autocalibration.AutoCalibrationManager.java
License:Open Source License
public Optional<Bounds> calibrateFrame(MatOfPoint2f boardCorners, Mat mat) { // For debugging Mat traceMat = null;/* w w w. ja v a 2 s. c o m*/ if (logger.isTraceEnabled()) { traceMat = mat.clone(); } initializeSize(mat.cols(), mat.rows()); // Step 2: Estimate the pattern corners MatOfPoint2f estimatedPatternRect = estimatePatternRect(traceMat, boardCorners); // Step 3: Use Hough Lines to find the actual corners final Optional<MatOfPoint2f> idealCorners = findIdealCorners(mat, estimatedPatternRect); if (!idealCorners.isPresent()) return Optional.empty(); if (logger.isTraceEnabled()) { String filename = String.format("calibrate-dist.png"); final File file = new File(filename); filename = file.toString(); Highgui.imwrite(filename, traceMat); } // Step 4: Initialize the warp matrix and bounding box initializeWarpPerspective(mat, idealCorners.get()); if (boundingBox.getMinX() < 0 || boundingBox.getMinY() < 0 || boundingBox.getWidth() > cameraManager.getFeedWidth() || boundingBox.getHeight() > cameraManager.getFeedHeight()) { return Optional.empty(); } if (logger.isDebugEnabled()) logger.debug("bounds {} {} {} {}", boundingBox.getMinX(), boundingBox.getMinY(), boundingBox.getWidth(), boundingBox.getHeight()); final Mat undistorted = warpPerspective(mat); if (logger.isTraceEnabled()) { String filename = String.format("calibrate-undist.png"); File file = new File(filename); filename = file.toString(); Highgui.imwrite(filename, undistorted); Mat undistortedCropped = undistorted.submat((int) boundingBox.getMinY(), (int) boundingBox.getMaxY(), (int) boundingBox.getMinX(), (int) boundingBox.getMaxX()); filename = String.format("calibrate-undist-cropped.png"); file = new File(filename); filename = file.toString(); Highgui.imwrite(filename, undistortedCropped); } Mat warpedBoardCorners = warpCorners(boardCorners); isCalibrated = true; if (calculateFrameDelay) { findColors(undistorted, warpedBoardCorners); final double squareHeight = boundingBox.getHeight() / (double) (PATTERN_HEIGHT + 1); final double squareWidth = boundingBox.getWidth() / (double) (PATTERN_WIDTH + 1); int secondSquareCenterX = (int) (boundingBox.getMinX() + (squareWidth * 1.5)); int secondSquareCenterY = (int) (boundingBox.getMinY() + (squareHeight * .5)); if (logger.isDebugEnabled()) logger.debug("pF getFrameDelayPixel x {} y {} p {}", secondSquareCenterX, secondSquareCenterY, undistorted.get(secondSquareCenterY, secondSquareCenterX)); } return Optional.of(boundingBox); }
From source file:com.shootoff.camera.autocalibration.AutoCalibrationManager.java
License:Open Source License
/** * Perspective pattern discovery// w ww . j a v a 2 s . com * * Works similar to arena calibration but does not try to identify the * outline of the projection area We are only concerned with size, not * alignment or angle * * This function blanks out the pattern that it discovers in the Mat it is * provided. This is so that the pattern is not discovered by future pattern * discovery, e.g. auto-calibration * * workingMat should be null for all external callers unless there is some * need to work off a different Mat than is having patterns blanked out by * this function */ public Optional<Dimension2D> findPaperPattern(MatOfPoint2f boardCorners, Mat mat, Mat workingMat) { if (workingMat == null) workingMat = mat.clone(); initializeSize(workingMat.cols(), workingMat.rows()); // Step 2: Estimate the pattern corners final BoundingBox box = getPaperPatternDimensions(workingMat, boardCorners); // OpenCV gives us the checkerboard corners, not the outside dimension // So this estimates where the outside corner would be, plus a fudge // factor for the edge of the paper // Printer margins are usually a quarter inch on each edge double width = ((double) box.getWidth() * ((double) (PATTERN_WIDTH + 1) / (double) (PATTERN_WIDTH - 1)) * 1.048); double height = ((double) box.getHeight() * ((double) (PATTERN_HEIGHT + 1) / (double) (PATTERN_HEIGHT - 1)) * 1.063); final double PAPER_PATTERN_SIZE_THRESHOLD = .25; if (width > PAPER_PATTERN_SIZE_THRESHOLD * workingMat.cols() || height > PAPER_PATTERN_SIZE_THRESHOLD * workingMat.rows()) { logger.trace("Pattern too big to be paper, must be projection, setting blank {} x {}", box.getWidth(), box.getHeight()); workingMat.submat((int) box.getMinY(), (int) box.getMaxY(), (int) box.getMinX(), (int) box.getMaxX()) .setTo(new Scalar(0, 0, 0)); if (logger.isTraceEnabled()) { String filename = String.format("blanked-box.png"); File file = new File(filename); filename = file.toString(); Highgui.imwrite(filename, workingMat); } final Optional<MatOfPoint2f> boardCornersNew = findChessboard(workingMat); if (!boardCornersNew.isPresent()) return Optional.empty(); logger.trace("Found new pattern, attempting findPaperPattern {}", boardCornersNew.get()); return findPaperPattern(boardCornersNew.get(), mat, workingMat); } if (logger.isTraceEnabled()) { logger.trace("pattern width {} height {}", box.getWidth(), box.getHeight()); logger.trace("paper width {} height {}", width, height); int widthOffset = ((int) width - (int) box.getWidth()) / 2; int heightOffset = ((int) height - (int) box.getHeight()) / 2; logger.trace("offset width {} height {}", widthOffset, heightOffset); Mat fullpattern = workingMat.clone(); // TODO: This doesn't work if the pattern is upside down, but this is for debugging anyway right now // Should fix in case it causes an out of bounds or something Point topLeft = new Point(boardCorners.get(0, 0)[0], boardCorners.get(0, 0)[1]); Point topRight = new Point(boardCorners.get(PATTERN_WIDTH - 1, 0)[0], boardCorners.get(PATTERN_WIDTH - 1, 0)[1]); Point bottomRight = new Point(boardCorners.get(PATTERN_WIDTH * PATTERN_HEIGHT - 1, 0)[0], boardCorners.get(PATTERN_WIDTH * PATTERN_HEIGHT - 1, 0)[1]); Point bottomLeft = new Point(boardCorners.get(PATTERN_WIDTH * (PATTERN_HEIGHT - 1), 0)[0], boardCorners.get(PATTERN_WIDTH * (PATTERN_HEIGHT - 1), 0)[1]); Core.circle(fullpattern, topLeft, 1, new Scalar(255, 0, 0), -1); Core.circle(fullpattern, topRight, 1, new Scalar(255, 0, 0), -1); Core.circle(fullpattern, bottomRight, 1, new Scalar(255, 0, 0), -1); Core.circle(fullpattern, bottomLeft, 1, new Scalar(255, 0, 0), -1); String filename = String.format("marked-box.png"); File file = new File(filename); filename = file.toString(); Highgui.imwrite(filename, fullpattern); fullpattern = fullpattern.submat((int) box.getMinY() - heightOffset, (int) box.getMinY() - heightOffset + (int) height, (int) box.getMinX() - widthOffset, (int) box.getMinX() - widthOffset + (int) width); filename = String.format("full-box.png"); file = new File(filename); filename = file.toString(); Highgui.imwrite(filename, fullpattern); Mat cropped = workingMat.submat((int) box.getMinY(), (int) box.getMaxY(), (int) box.getMinX(), (int) box.getMaxX()); filename = String.format("pattern-box.png"); file = new File(filename); filename = file.toString(); Highgui.imwrite(filename, cropped); } mat.submat((int) box.getMinY(), (int) box.getMaxY(), (int) box.getMinX(), (int) box.getMaxX()) .setTo(new Scalar(0, 0, 0)); return Optional.of(new Dimension2D(width, height)); }
From source file:com.shootoff.camera.shotdetection.JavaShotDetector.java
License:Open Source License
private Set<Pixel> findThresholdPixelsAndUpdateFilter(final Mat workingFrame, final boolean detectShots) { dynamicallyThresholded = 0;//from w w w . j a v a 2s . c o m final Set<Pixel> thresholdPixels = Collections.synchronizedSet(new HashSet<Pixel>()); if (!cameraManager.isDetecting()) return thresholdPixels; final int subWidth = workingFrame.cols() / SECTOR_COLUMNS; final int subHeight = workingFrame.rows() / SECTOR_ROWS; final int cols = workingFrame.cols(); final int channels = workingFrame.channels(); final int size = (int) (workingFrame.total() * channels); final byte[] workingFramePrimitive = new byte[size]; workingFrame.get(0, 0, workingFramePrimitive); // In this loop we accomplish both MovingAverage updates AND threshold // pixel detection Parallel.forIndex(0, (SECTOR_ROWS * SECTOR_COLUMNS), 1, new Operation<Integer>() { public void perform(Integer sector) { final int sectorX = sector.intValue() % SECTOR_COLUMNS; final int sectorY = sector.intValue() / SECTOR_ROWS; if (!cameraManager.isSectorOn(sectorX, sectorY)) return; final int startX = subWidth * sectorX; final int startY = subHeight * sectorY; for (int y = startY; y < startY + subHeight; y++) { final int yOffset = y * cols; for (int x = startX; x < startX + subWidth; x++) { final int currentH = workingFramePrimitive[(yOffset + x) * channels] & 0xFF; final int currentS = workingFramePrimitive[(yOffset + x) * channels + 1] & 0xFF; final int currentV = workingFramePrimitive[(yOffset + x) * channels + 2] & 0xFF; final Pixel pixel = updateFilter(currentH, currentS, currentV, x, y, detectShots); if (pixel != null) thresholdPixels.add(pixel); } } } }); return thresholdPixels; }
From source file:com.shootoff.camera.shotdetection.PixelCluster.java
License:Open Source License
public double getColorDifference(final Mat workingFrame, final int[][] colorDistanceFromRed) { final Map<Pixel, byte[]> visited = new HashMap<Pixel, byte[]>(); int avgSaturation = 0; for (final Pixel pixel : this) { if (pixel.getConnectedness() < MAXIMUM_CONNECTEDNESS) { for (int h = -1; h <= 1; h++) { for (int w = -1; w <= 1; w++) { if (h == 0 && w == 0) continue; final int rx = pixel.x + w; final int ry = pixel.y + h; if (rx < 0 || ry < 0 || rx >= workingFrame.cols() || ry >= workingFrame.rows()) continue; final Pixel nearPoint = new Pixel(rx, ry); if (!visited.containsKey(nearPoint) && !this.contains(nearPoint)) { byte[] np = { 0, 0, 0 }; workingFrame.get(ry, rx, np); final int npSaturation = np[1] & 0xFF; avgSaturation += npSaturation; visited.put(nearPoint, np); }/*from w ww . j av a 2 s. c om*/ } } } } final int pixelCount = visited.size(); if (pixelCount == 0) return 0; avgSaturation /= pixelCount; int colorDistance = 0; int avgColorDistance = 0; int tempColorDistance = 0; for (final Entry<Pixel, byte[]> pixelEntry : visited.entrySet()) { byte[] np = pixelEntry.getValue(); final int npSaturation = np[1] & 0xFF; if (npSaturation > avgSaturation) { final int npColor = np[0] & 0xFF; final int npLum = np[2] & 0xFF; final int thisDFromRed = Math.min(npColor, Math.abs(180 - npColor)) * npLum * npSaturation; final int thisDFromGreen = Math.abs(60 - npColor) * npLum * npSaturation; final int currentCol = thisDFromRed - thisDFromGreen; final Pixel pixel = pixelEntry.getKey(); colorDistance += currentCol - (int) (CURRENT_COLOR_BIAS_MULTIPLIER * colorDistanceFromRed[pixel.x][pixel.y]); if (logger.isTraceEnabled()) { tempColorDistance += currentCol; avgColorDistance += colorDistanceFromRed[pixel.x][pixel.y]; } } } if (logger.isTraceEnabled()) logger.trace("Pixels {} Color {} avg {} sum {}", pixelCount, colorDistance / pixelCount, avgColorDistance / pixelCount, tempColorDistance / pixelCount); return colorDistance; }
From source file:com.sikulix.core.Finder.java
License:Open Source License
private static void printMatI(Mat mat) { int[] data = new int[mat.channels()]; for (int r = 0; r < mat.rows(); r++) { for (int c = 0; c < mat.cols(); c++) { mat.get(r, c, data);// w w w . j a v a 2s . c o m log.trace("(%d, %d) %s", r, c, Arrays.toString(data)); } } }
From source file:com.trandi.opentld.tld.BoundingBox.java
License:Apache License
BoundingBox intersect(final Mat img) { final BoundingBox result = new BoundingBox(); result.x = Math.max(x, 0);//from www .j av a 2 s .c om result.y = Math.max(y, 0); result.width = (int) Math.min(Math.min(img.cols() - x, width), Math.min(width, br().x)); result.height = (int) Math.min(Math.min(img.rows() - y, height), Math.min(height, br().y)); return result; }
From source file:com.trandi.opentld.tld.Grid.java
License:Apache License
Grid(Mat img, Rect trackedBox, int minWinSide) { // TODO why do we generate so many BAD boxes, only to remove them later on !? // OR do we need them to re-asses which ones are bad later on ? for (int s = 0; s < SCALES.length; s++) { final int width = Math.round(trackedBox.width * SCALES[s]); final int height = Math.round(trackedBox.height * SCALES[s]); final int minBbSide = Math.min(height, width); // continue ONLY if the future box is "reasonable": bigger than the min window and smaller than the full image ! if (minBbSide >= minWinSide && width <= img.cols() && height <= img.rows()) { trackedBoxScales.add(new Size(width, height)); final int shift = Math.round(SHIFT * minBbSide); for (int row = 1; row < (img.rows() - height); row += shift) { for (int col = 1; col < (img.cols() - width); col += shift) { final BoundingBox bbox = new BoundingBox(); bbox.x = col;/*w w w . j ava 2 s . c o m*/ bbox.y = row; bbox.width = width; bbox.height = height; bbox.scaleIdx = trackedBoxScales.size() - 1; // currently last one in this list grid.add(bbox); } } } } }
From source file:com.trandi.opentld.tld.Tld.java
License:Apache License
public void init(Mat frame1, Rect trackedBox) { // get Bounding boxes if (Math.min(trackedBox.width, trackedBox.height) < _params.min_win) { throw new IllegalArgumentException( "Provided trackedBox: " + trackedBox + " is too small (min " + _params.min_win + ")"); }/* w ww . j a v a2 s . com*/ _grid = new Grid(frame1, trackedBox, _params.min_win); Log.i(Util.TAG, "Init Created " + _grid.getSize() + " bounding boxes."); _grid.updateGoodBadBoxes(trackedBox, _params.num_closest_init); _iiRows = frame1.rows(); _iiCols = frame1.cols(); _iisum.create(_iiRows, _iiCols, CvType.CV_32F); _iisqsum.create(_iiRows, _iiCols, CvType.CV_64F); // correct bounding box _lastbox = _grid.getBestBox(); _classifierFern.init(_grid.getTrackedBoxScales(), _rng); // generate DATA // generate POSITIVE DATA generatePositiveData(frame1, _params.num_warps_init, _grid); // Set variance threshold MatOfDouble stddev = new MatOfDouble(); Core.meanStdDev(frame1.submat(_grid.getBestBox()), new MatOfDouble(), stddev); updateIntegralImgs(frame1); // this is directly half of the variance of the initial box, which will be used the the 1st stage of the classifier _var = (float) Math.pow(stddev.toArray()[0], 2d) * 0.5f; // check variance final double checkVar = Util.getVar(_grid.getBestBox(), _iisumJava, _iisqsumJava, _iiCols) * 0.5; Log.i(Util.TAG, "Variance: " + _var + " / Check variance: " + checkVar); // generate NEGATIVE DATA final Pair<List<Pair<int[], Boolean>>, List<Mat>> negData = generateNegativeData(frame1); // Split Negative Ferns <features, labels=false> into Training and Testing sets (they are already shuffled) final int nFernsSize = negData.first.size(); final List<Pair<int[], Boolean>> nFernsTest = new ArrayList<Pair<int[], Boolean>>( negData.first.subList(0, nFernsSize / 2)); final List<Pair<int[], Boolean>> nFerns = new ArrayList<Pair<int[], Boolean>>( negData.first.subList(nFernsSize / 2, nFernsSize)); // Split Negative NN Examples into Training and Testing sets final int nExSize = negData.second.size(); final List<Mat> nExamplesTest = new ArrayList<Mat>(negData.second.subList(0, nExSize / 2)); _nExamples = new ArrayList<Mat>(negData.second.subList(nExSize / 2, nExSize)); //MERGE Negative Data with Positive Data and shuffle it final List<Pair<int[], Boolean>> fernsData = new ArrayList<Pair<int[], Boolean>>(_pFerns); fernsData.addAll(nFerns); Collections.shuffle(fernsData); // TRAINING Log.i(Util.TAG, "Init Start Training with " + fernsData.size() + " ferns, " + _nExamples.size() + " nExamples, " + nFernsTest.size() + " nFernsTest, " + nExamplesTest.size() + " nExamplesTest"); _classifierFern.trainF(fernsData, 10); _classifierNN.trainNN(_pExample, _nExamples); // Threshold evaluation on testing sets _classifierFern.evaluateThreshold(nFernsTest); _classifierNN.evaluateThreshold(nExamplesTest); }
From source file:com.trandi.opentld.tld.Tld.java
License:Apache License
private TrackingStruct track(final Mat lastImg, final Mat currentImg, final BoundingBox lastBox) { Log.i(Util.TAG, "[TRACK]"); // Generate points final Point[] lastPoints = lastBox.points(); if (lastPoints.length == 0) { Log.e(Util.TAG, "Points not generated from lastBox: " + lastBox); return null; }/* w ww . j a v a 2 s. c o m*/ // Frame-to-frame tracking with forward-backward error checking final Pair<Point[], Point[]> trackedPoints = _tracker.track(lastImg, currentImg, lastPoints); if (trackedPoints == null) { Log.e(Util.TAG, "No points could be tracked."); return null; } if (_tracker.getMedianErrFB() > _params.tracker_stability_FBerrMax) { Log.w(Util.TAG, "TRACKER too unstable. FB Median error: " + _tracker.getMedianErrFB() + " > " + _params.tracker_stability_FBerrMax); // return null; // we hope the detection will find the pattern again } // bounding box prediction final BoundingBox predictedBB = lastBox.predict(trackedPoints.first, trackedPoints.second); if (predictedBB.x > currentImg.cols() || predictedBB.y > currentImg.rows() || predictedBB.br().x < 1 || predictedBB.br().y < 1) { Log.e(Util.TAG, "TRACKER Predicted bounding box out of range !"); return null; } // estimate Confidence Mat pattern = new Mat(); try { resizeZeroMeanStdev(currentImg.submat(predictedBB.intersect(currentImg)), pattern, _params.patch_size); } catch (Throwable t) { Log.e(Util.TAG, "PredBB when failed: " + predictedBB); } //Log.i(Util.TAG, "Confidence " + pattern.dump()); //Conservative Similarity final NNConfStruct nnConf = _classifierNN.nnConf(pattern); Log.i(Util.TAG, "Tracking confidence: " + nnConf.conservativeSimilarity); Log.i(Util.TAG, "[TRACK END]"); return new TrackingStruct(nnConf.conservativeSimilarity, predictedBB, trackedPoints.first, trackedPoints.second); }
From source file:com.trandi.opentld.tld.Tld.java
License:Apache License
/** * Structure the classifier into 3 stages: * a) patch variance/* w w w . j ava2 s . c o m*/ * b) ensemble of ferns classifier * c) nearest neighbour */ private Pair<List<DetectionStruct>, List<DetectionStruct>> detect(final Mat frame) { Log.i(Util.TAG, "[DETECT]"); final List<DetectionStruct> fernClassDetected = new ArrayList<Tld.DetectionStruct>(); //dt final List<DetectionStruct> nnMatches = new ArrayList<Tld.DetectionStruct>(); //dbb // 0. Cleaning _boxClusterMap.clear(); // 1. DETECTION final Mat img = new Mat(frame.rows(), frame.cols(), CvType.CV_8U); updateIntegralImgs(frame); Imgproc.GaussianBlur(frame, img, new Size(9, 9), 1.5); // Apply the Variance filter TODO : Bottleneck int a = 0; for (BoundingBox box : _grid) { // a) speed up by doing the features/ferns check ONLY if the variance is high enough ! if (Util.getVar(box, _iisumJava, _iisqsumJava, _iiCols) >= _var) { a++; final Mat patch = img.submat(box); final int[] allFernsHashCodes = _classifierFern.getAllFernsHashCodes(patch, box.scaleIdx); final double averagePosterior = _classifierFern.averagePosterior(allFernsHashCodes); _fernDetectionNegDataForLearning.put(box, allFernsHashCodes);// store for later use in learning // b) if (averagePosterior > _classifierFern.getFernPosThreshold()) { fernClassDetected.add(new DetectionStruct(box, allFernsHashCodes, averagePosterior, patch)); } } } Log.i(Util.TAG, a + " Bounding boxes passed the variance filter (" + _var + ")"); Log.i(Util.TAG, fernClassDetected.size() + " Initial detected from Fern Classifier"); if (fernClassDetected.size() == 0) { Log.i(Util.TAG, "[DETECT END]"); return null; } // keep only the best Util.keepBestN(fernClassDetected, MAX_DETECTED, new Comparator<DetectionStruct>() { @Override public int compare(DetectionStruct detS1, DetectionStruct detS2) { return Double.compare(detS1.averagePosterior, detS2.averagePosterior); } }); // 2. MATCHING using the NN classifier c) for (DetectionStruct detStruct : fernClassDetected) { // update detStruct.patch to params.patch_size and normalise it Mat pattern = new Mat(); resizeZeroMeanStdev(detStruct.patch, pattern, _params.patch_size); detStruct.nnConf = _classifierNN.nnConf(pattern); Log.i(Util.TAG, "NNConf: " + detStruct.nnConf.relativeSimilarity + " / " + detStruct.nnConf.conservativeSimilarity + " Threshold: " + _classifierNN.getNNThreshold()); // only keep valid boxes if (detStruct.nnConf.relativeSimilarity > _classifierNN.getNNThreshold()) { nnMatches.add(detStruct); } } Log.i(Util.TAG, "[DETECT END]"); return new Pair<List<DetectionStruct>, List<DetectionStruct>>(fernClassDetected, nnMatches); }