Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Video stabilization with videostab module

Hi all,

Really hope that someone can assist with the following problem. I'm currently trying to video stabilization on iOS, but I'm getting an out of memory exception.

I have the following code that attempts to stabilize the video:

+ (int)videoStabFileAtURL:(NSURL *)inputURL writeToURL:(NSURL *)outputURL {
  Ptr<IFrameSource> stabilizedFrames;

  try {
    // 1 - Prepare input video and check it
    String inputPath = *new String(inputURL.path.UTF8String);
    String outputPath = *new String(outputURL.path.UTF8String);

    Ptr<VideoFileSource> source = makePtr<VideoFileSource>(inputPath);
    cout << "Frame count (rough): " << source->count() << endl;

    // 2 - Prepare the motion estimator
    double min_inlier_ratio = 0.1;

    Ptr<MotionEstimatorRansacL2> est = makePtr<MotionEstimatorRansacL2>(MM_TRANSLATION_AND_SCALE);
    RansacParams ransac = est->ransacParams();
    ransac.thresh = 5;
    ransac.eps = 0.5;

    est->setRansacParams(ransac);
    est->setMinInlierRatio(min_inlier_ratio);

    // 3 - Create a feature detector
    int nkps = 20;

    Ptr<GFTTDetector> feature_detector = GFTTDetector::create(nkps);

    // 4 - Create motion estimator
    Ptr<KeypointBasedMotionEstimator> motionEstBuilder = makePtr<KeypointBasedMotionEstimator>(est);
    motionEstBuilder->setDetector(feature_detector);

    Ptr<IOutlierRejector> outlierRejector = makePtr<NullOutlierRejector>();
    motionEstBuilder->setOutlierRejector(outlierRejector);

    // 5 - Prepare stabilizer
    StabilizerBase *stabilizer = 0;

    int radius_pass = 15;
    bool est_trim = true;

//    TwoPassStabilizer *twoPassStabilizer = new TwoPassStabilizer();
//    twoPassStabilizer->setEstimateTrimRatio(est_trim);
//    twoPassStabilizer->setMotionStabilizer(makePtr<GaussianMotionFilter>(radius_pass));

    OnePassStabilizer *onePassStabilizer = new OnePassStabilizer();
    onePassStabilizer->setMotionFilter(makePtr<GaussianMotionFilter>(radius_pass));

    stabilizer = onePassStabilizer;

    // Setup parameters
    int radius = 15;
    double trim_ratio = 0.1;
    bool incl_constr = false;

    stabilizer->setFrameSource(source);
    stabilizer->setMotionEstimator(motionEstBuilder);
    stabilizer->setRadius(radius);
    stabilizer->setTrimRatio(trim_ratio);
    stabilizer->setCorrectionForInclusion(incl_constr);
    stabilizer->setBorderMode(BORDER_REPLICATE);

    // Cast stabilizer to simple frame source interface to read stabilized frames
    stabilizedFrames.reset(dynamic_cast<IFrameSource*>(stabilizer));

    // 6 - Processing the stabilized frames. The results are saved
    processing(stabilizedFrames, outputPath);
  } catch (const exception &e) {
    cout << "Error: " << e.what() << endl;
    stabilizedFrames.release();
    return -1;
  }

  stabilizedFrames.release();
  return 0;
}

void processing(Ptr<IFrameSource> stabilizedFrames, String outputPath) {
  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
    @autoreleasepool {
      VideoWriter videoWriter;
      Mat stabilizedFrame;
      int nframes = 0;
      double outputFps = 30;

      // For each stabilized frame
      while (!(stabilizedFrame = stabilizedFrames->nextFrame()).empty()) {
        nframes++;

        // Init writer (once) and save stabilized frame
        if (!outputPath.empty()) {
          if (!videoWriter.isOpened()) {
            videoWriter.open(outputPath, VideoWriter::fourcc('H', '2', '6', '4'), outputFps, stabilizedFrame.size());
            videoWriter << stabilizedFrame;
          }
        }
      }
    }
  });
}

I can see it processing the frames, but it's using a lot of memory on an iPhone 6, which eventually leads to the app crashing. Does anyone know what I can do to reduce memory usage?