boolean decodeJPEGAndAnalyze(Context context, CalibrationEntries calibrationEntries) { boolean result = false; BitmapFactory.Options opt = new BitmapFactory.Options(); opt.inPreferQualityOverSpeed = true; BitmapRegionDecoder brd; byte[] data = mData; try { brd = BitmapRegionDecoder.newInstance(data, 0, data.length, false); Rect rect; rect = new Rect(0, 0, brd.getWidth(), brd.getHeight()); Bitmap bitmap = brd.decodeRegion(rect, opt); MatBitmapHolder mRgbaMatHolder = new MatBitmapHolder(bitmap); Mat rgbaMat = mRgbaMatHolder.pin(); Mat grayData = new Mat(); Imgproc.cvtColor(rgbaMat, grayData, Imgproc.COLOR_RGB2GRAY, 1); Mat centersCalibCircles = new Mat(); Size patternSize = CalibrationEntries.Pattern_ASYMMETRIC_CIRCLES_GRID_SIZE; Size imageSize = new Size(grayData.cols(), grayData.rows()); boolean patternWasFound = Calib3d.findCirclesGridDefault( grayData, patternSize, centersCalibCircles, Calib3d.CALIB_CB_ASYMMETRIC_GRID); if (patternWasFound && this.orientation != null) { int addedIdx = calibrationEntries.addEntry(this.orientation, centersCalibCircles); if (addedIdx >= 0) { Log.d( "CALIB", String.format( "PictureCapture: Added calibration entry at %d tot: %d", addedIdx, calibrationEntries.getNumEntries())); if (calibrationEntries.getNewlyAdded() > 5) { List<Mat> imagePoints = calibrationEntries.getPoints(); List<Mat> objectPoints = calibrationEntries.getObjectPointsAsymmentricList(imagePoints.size()); if (CalibrationEntries.isEnoughCalibrationPoints(imagePoints.size())) { calibrationEntries.resetNewlyAdded(); CameraCalibrationData cameraCalibrationData = new CameraCalibrationData(); List<Mat> rvecs = new Vector<Mat>(imagePoints.size()); List<Mat> tvecs = new Vector<Mat>(imagePoints.size()); int flags = 0; flags |= Calib3d.CALIB_FIX_K4 | Calib3d.CALIB_FIX_K5; Log.d("CALIB", String.format("PictureCapture: Calling Calib3d.calibrateCamera")); Mat K = new Mat(); Mat kdist = new Mat(); double rms = Calib3d.calibrateCamera( objectPoints, imagePoints, imageSize, K, kdist, rvecs, tvecs, flags); double[] Karray = new double[9]; double[] distcoeffs_array = new double[5]; K.get(0, 0, Karray); kdist.get(0, 0, distcoeffs_array); cameraCalibrationData.setData( grayData.cols(), grayData.rows(), Karray, distcoeffs_array, rms); Log.d( "CALIB", String.format( "PictureCapture: Calibration data: %s", cameraCalibrationData.formatCalibrationDataString())); calibrationEntries.setCalibrationData(cameraCalibrationData); result = true; } } } } // mRightBitmap = brd.decodeRegion(rect, opt); rect = new Rect(brd.getWidth() - brd.getWidth() / 3, 0, brd.getWidth(), brd.getHeight()); // mLeftBitmap = brd.decodeRegion(rect, opt); mRgbaMatHolder.unpin(rgbaMat); } catch (IOException e) { XLog.e("Region decoder doesn't want to cooperate", e); } return result; }
/** * Analyze video frames using computer vision approach and generate a ArrayList<AttitudeRec> * * @param recs output ArrayList of AttitudeRec * @return total number of frame of the video */ private int analyzeVideo(ArrayList<AttitudeRec> recs) { VideoMetaInfo meta = new VideoMetaInfo(new File(mPath, "videometa.json")); int decimation = 1; if (meta.fps > DECIMATION_FPS_TARGET) { decimation = (int) (meta.fps / DECIMATION_FPS_TARGET); meta.fps /= decimation; } VideoDecoderForOpenCV videoDecoder = new VideoDecoderForOpenCV( new File(mPath, "video.mp4"), decimation); // every 3 frame process 1 frame Mat frame; Mat gray = new Mat(); int i = -1; Size frameSize = videoDecoder.getSize(); if (frameSize.width != meta.frameWidth || frameSize.height != meta.frameHeight) { // this is very unlikely return -1; } if (TRACE_VIDEO_ANALYSIS) { Debug.startMethodTracing("cvprocess"); } Size patternSize = new Size(4, 11); float fc = (float) (meta.frameWidth / 2.0 / Math.tan(meta.fovWidth / 2.0)); Mat camMat = cameraMatrix(fc, new Size(frameSize.width / 2, frameSize.height / 2)); MatOfDouble coeff = new MatOfDouble(); // dummy MatOfPoint2f centers = new MatOfPoint2f(); MatOfPoint3f grid = asymmetricalCircleGrid(patternSize); Mat rvec = new MatOfFloat(); Mat tvec = new MatOfFloat(); MatOfPoint2f reprojCenters = new MatOfPoint2f(); if (LOCAL_LOGV) { Log.v(TAG, "Camera Mat = \n" + camMat.dump()); } long startTime = System.nanoTime(); while ((frame = videoDecoder.getFrame()) != null) { if (LOCAL_LOGV) { Log.v(TAG, "got a frame " + i); } // has to be in front, as there are cases where execution // will skip the later part of this while i++; // convert to gray manually as by default findCirclesGridDefault uses COLOR_BGR2GRAY Imgproc.cvtColor(frame, gray, Imgproc.COLOR_RGB2GRAY); boolean foundPattern = Calib3d.findCirclesGridDefault( gray, patternSize, centers, Calib3d.CALIB_CB_ASYMMETRIC_GRID); if (!foundPattern) { // skip to next frame continue; } if (OUTPUT_DEBUG_IMAGE) { Calib3d.drawChessboardCorners(frame, patternSize, centers, true); } // figure out the extrinsic parameters using real ground truth 3D points and the pixel // position of blobs found in findCircleGrid, an estimated camera matrix and // no-distortion are assumed. boolean foundSolution = Calib3d.solvePnP(grid, centers, camMat, coeff, rvec, tvec, false, Calib3d.CV_ITERATIVE); if (!foundSolution) { // skip to next frame if (LOCAL_LOGV) { Log.v(TAG, "cannot find pnp solution in frame " + i + ", skipped."); } continue; } // reproject points to for evaluation of result accuracy of solvePnP Calib3d.projectPoints(grid, rvec, tvec, camMat, coeff, reprojCenters); // error is evaluated in norm2, which is real error in pixel distance / sqrt(2) double error = Core.norm(centers, reprojCenters, Core.NORM_L2); if (LOCAL_LOGV) { Log.v(TAG, "Found attitude, re-projection error = " + error); } // if error is reasonable, add it into the results if (error < REPROJECTION_THREASHOLD) { double[] rv = new double[3]; rvec.get(0, 0, rv); recs.add(new AttitudeRec((double) i / meta.fps, rodr2rpy(rv))); } if (OUTPUT_DEBUG_IMAGE) { Calib3d.drawChessboardCorners(frame, patternSize, reprojCenters, true); Highgui.imwrite( Environment.getExternalStorageDirectory().getPath() + "/RVCVRecData/DebugCV/img" + i + ".png", frame); } } if (LOCAL_LOGV) { Log.v(TAG, "Finished decoding"); } if (TRACE_VIDEO_ANALYSIS) { Debug.stopMethodTracing(); } if (LOCAL_LOGV) { // time analysis double totalTime = (System.nanoTime() - startTime) / 1e9; Log.i(TAG, "Total time: " + totalTime + "s, Per frame time: " + totalTime / i); } return i; }