Программная стабилизация видео в iOS с использованием фреймворка OpenCV

С ростом популярности цифрового видеоконтента всё более актуальной становится задача улучшения качества видео. На видео, снятых с помощью переносной камеры, фотоаппарата или смартфона, обычно присутствуют нежелательные движения картинки, вызванные дрожанием руки в процессе съемки. На сегодняшний день существенного улучшения качества видео можно добиться при помощи программной стабилизации — генерирования новой последовательности кадров, в которой компенсирован эффект дрожания. В этой статье я опишу метод программной стабилизации видео, основанный на использовании библиотеки OpenCV.

Стабилизация видео в iOS

Использование дополнительной программной стабилизации видео в iOS может показаться излишним при наличии встроенного решения от Apple. Алгоритм, разработанный инженерами Apple, позволяет добиться заметного улучшения качества видео, но обладает некоторыми недостатками: доступен для ограниченного количества устройств и версий iOS 6 и выше, а также поддерживает только определенные форматы записи видео.

Использование OpenCV позволяет справиться с этими ограничениями и обеспечить при этом качественную стабилизацию видео.

Почему OpenCV?

OpenCV (Open Source Computer Vision Library) — библиотека алгоритмов компьютерного зрения, обработки изображений и численных алгоритмов общего назначения с открытым кодом. Она была разработана Intel, а сейчас поддерживается Willow Garage Inc. и Itseez Ltd. OpenCV распространяется под лицензией BSD, а значит, бесплатна как для учебных, так и для коммерческих целей. Реализована на C++, C, Python и Java, поддерживает Windows, Linux, Mac OS, iOS и Android.

OpenCV имеет модульную структуру, что упрощает ее использование. Модуль стабилизации видео предоставляет набор функций и классов для анализа движения и обработки видео.

enum
{
BORDER_REPLICATE=IPL_BORDER_REPLICATE, BORDER_CONSTANT=IPL_BORDER_CONSTANT,
BORDER_REFLECT=IPL_BORDER_REFLECT,
BORDER_WRAP=IPL_BORDER_WRAP,
BORDER_REFLECT_101=IPL_BORDER_REFLECT_101, BORDER_REFLECT101=BORDER_REFLECT_101,
BORDER_TRANSPARENT=IPL_BORDER_TRANSPARENT,
BORDER_DEFAULT=BORDER_REFLECT_101,
BORDER_ISOLATED=16
};

Алгоритм

Алгоритм стабилизации видео обычно включает в себя следующие этапы:

iOS-video-stabilization

Рассмотрим процесс подробнее.

  • На первом этапе стабилизации видео выполняется оценка смещения между соседними кадрами. В результате мы получаем массив матриц 3х3, описывающих смещение между двумя смежными кадрами. Так как оценка смещения является первым этапом стабилизации, её точность имеет решающее значение.
  • На следующем этапе генерируется новая последовательность кадров на основе рассчитанных смещений, после чего для повышения качества видео и устранения дефектов производится дополнительная обработка (сглаживание, устранение размытости, граничная экстраполяция, проч.). Существуют подходы устранения дефектов, учитывающие модель движения камеры, которые при правильном выборе модели позволяют получить более качественный результат. Заполнение недостающих участков, появляющихся на кадрах после трансформации, называется video completion.
  • На видео также может присутствовать эффект размытости, основной источник ухудшения качества изображения, который вызван движением объекта в кадре во время съемки. Поэтому методы стабилизации также содержат механизм устранения размытости (deblurring).

Ниже представлен список основных параметров для классов OpenCV (классы оценки движения, стабилизаторы), используемых при видеостабилизации:

enum MotionModel
{
 TRANSLATION = 0,
 TRANSLATION_AND_SCALE = 1,
 LINEAR_SIMILARITY = 2,
 AFFINE = 3
};

Значения инлаеров (inlier) и аутлаеров (outlier) для параметров RANSAC при оценке движения (значения по умолчанию для инлаеров — 0.5, для аутлаеров — 0.1).

Радиус сглаживания (smoothing radius) стабилизатора для устранения шумов (по умолчанию 15).

Режим экстраполяции границ кадров:

enum
{
BORDER_REPLICATE=IPL_BORDER_REPLICATE, BORDER_CONSTANT=IPL_BORDER_CONSTANT,
BORDER_REFLECT=IPL_BORDER_REFLECT,
BORDER_WRAP=IPL_BORDER_WRAP,
BORDER_REFLECT_101=IPL_BORDER_REFLECT_101, BORDER_REFLECT101=BORDER_REFLECT_101,
BORDER_TRANSPARENT=IPL_BORDER_TRANSPARENT,
BORDER_DEFAULT=BORDER_REFLECT_101,
BORDER_ISOLATED=16
};

Чувствительность алгоритма устранения размытости (deblurring sensitivity) от 0 до +∞ (по умолчанию 0.1)

Настройка

Библиотека OpenCV поставляется в виде фреймворка. Необходимо добавить в проект его iOS версию, а также дополнительные зависимости OpenCV. В итоге в нашем проекте должны быть, как минимум, следующие фреймворки:

  • OpenCV2
  • Accelerate
  • AssetsLibrary
  • AVFoundation
  • CoreGraphics
  • CoreImage
  • CoreMedia
  • CoreVideo
  • QuartzCore
  • UIKit
  • Foundation

Далее добавляем камеру CvVideoCamera во ViewController:

using namespace cv;
@interface ViewController ()
{
CvVideoCamera *_videoCamera;
}

И инициализируем ее следующим образом:

_videoCamera = [[CvVideoCamera alloc] initWithParentView:<imageView>];
_videoCamera.delegate = self;
_videoCamera.defaultAVCaptureDevicePosition = AVCaptureDevicePositionBack;
_videoCamera.defaultAVCaptureSessionPreset = AVCaptureSessionPresetMedium;
_videoCamera.defaultAVCaptureVideoOrientation = AVCaptureVideoOrientationLandscapeRight;
_videoCamera.defaultFPS = 25;
_videoCamera.grayscaleMode = NO;

При инициализации камере передается imageView как target для рендеринга каждого кадра. Свойство defaultFPS устанавливает скорость съёмки в кадрах в секунду (FPS). Если обработка протекает медленнее выбранного значения FPS, то лишние кадры автоматически отбрасываются.

Стабилизатор и оценочную функцию (estimator) инициализируем следующим образом:

StabilizerBase *stabilizer;
GaussianMotionFilter *motionFilter = new GaussianMotionFilter();
motionFilter->setStdev(4); // Set smoothing weights standard deviation
TwoPassStabilizer *twoPassStabilizer = new TwoPassStabilizer();
twoPassStabilizer->setMotionStabilizer(motionFilter);
stabilizer = twoPassStabilizer;
// we can use one pass stabilizer for better speed and low stabilizing
// OnePassStabilizer *onePassStabilizer= new OnePassStabilizer();
// onePassStabilizer->setMotionFilter(motionFilter);
// stabilizer = onePassStabilizer;
VideoFileSource *frameSource = new VideoFileSource(<inputPath>); // This is the path to original
video file
outputFps = FPS; outputFps = 25; // FPS for result video
stabilizer->setFrameSource(frameSource);
PyrLkRobustMotionEstimator *motionEstimator = new PyrLkRobustMotionEstimator();
motionEstimator->setMotionModel(MotionModel::AFFINE);
RansacParams ransacParams = motionEstimator->ransacParams();
ransacParams.eps = 0.5; // See point 2 from the previous paragraph
motionEstimator->setRansacParams(ransacParams);
motionEstimator->setMinInlierRatio(0.1); // See point 2 from the previous paragraph
stabilizer->setMotionEstimator(motionEstimator);
stabilizer->setRadius(15); // See point 3 from the previous paragraph
stabilizer->setBorderMode(BORDER_REPLICATE);
WeightingDeblurer *deblurer = new WeightingDeblurer();
deblurer->setSensitivity(0.1); // See point 5 from the previous paragraph
stabilizer->setDeblurer(deblurer);
Ptr<IFrameSource> stabilizedFrames = dynamic_cast<IFrameSource*>(stabilizer);

Обработка кадров

Для доступа к каждому кадру камеры используем делегирование. Устанавливаем ViewController в качестве делегата _videoСamera и реализуем метод -(void)processImage:(Mat&)image протокола CvVideoCameraDelegate, в котором вызываем:

[_videoCamera start];

Для стабилизации последовательности кадров используем следующий код:

Mat stabilizedFrame;
while (!(stabilizedFrame = stabilizedFrames->nextFrame()).empty())
{
 // write stabilizedFrame to the output, e.g. using AVAssetWriterInput and AVAssetWriterInputPixelBufferAdaptor
}

Не забудьте освободить использованную память!

Результаты

Для оценки производительности использованных методов, я провела много экспериментов на коротких видео. Применялся двухпроходный OpenCV стабилизатор, аффинная модель движения, режим BORDER_REPLICATE восстановления кадров и значения по умолчанию для других параметров (без применения графического ускорителя). Скорость вычислений составила 2 FPS для видеоролика с разрешением 640×480, 30 FPS, снятого на iPhone 4s. Таких результатов явно недостаточно для стабилизации видео в реальном времени. К тому же скорость обработки заметно падает с увеличением разрешения видео.

Скорость стабилизации видео также зависит от характеристик сцены: количества деталей, освещённости. Узким местом здесь является первый этап – оценка движения. К примеру, можно увеличить скорость обработки до 40 FPS при тех же настройках, используя уже вычисленные матрицы перемещений. Ускорения этапа оценки движения для стабилизации видео в реальном времени можно добиться с использованием GPU и OpenCL.

Ссылки:

http://opencv.org/

http://www.cc.gatech.edu/~irfan/p/2011-Grundmann-AVSWROCP.pdf

http://en.wikipedia.org/wiki/RANSAC