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;
  }
Ejemplo n.º 2
0
  /**
   * 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;
  }