Когда я начал работать над магистерской диссертацией на тему «Анализ пространственной структуры динамических изображений», то столкнулся с проблемой, что очень трудной найти какие-то готовые примеры алгоритмов распознавания образов и движущихся объектов. Везде, и в литературе, и в Интернете одна только голая теория. Цель написания данной статьи как раз восполнить данный пробел.
Итак, для проведения эксперимента я снял из окна квартиры короткий видеоролик, разбил его на кадры и сохранил парочку кадров в виде картинок:
Для определения факта движения я решил пока пойти простым путем: превратить изображения в матрицу, из второй матрицы вычесть первую (поэлементно). Вот код на C#, выполняющий данную обработку:
И вот что получилось в ходе выполнения данного алгоритма:
На полученной матрице мы видим пропечатанный контур автомобиля и еще какие то контуры на заднем плане, которые, скорее всего, возникли из-за дрожания руки и из за шедшего в момент съемки дождя. На фотографии дождь не виден, но на видео его хорошо заметно.
Для того, чтобы улучшить качество распознавания, можно ввести в программу некое пороговое значение:
if (light < 50) light = 0; else light = 255;
Результат тогда будет совсем другой:
Как видим, при помощи простого вычитания матриц и использования порогового значения мы смогли определить на динамической картинке движущийся объект. Что делать с полученными данным дальше? По сути, что мы имеем сейчас, это бинарная картинка. В ней есть некоторые пятна, которые определяют движущийся объект. Шумы, как видим, наш алгоритм отсек. В дальнейшем, можно определить координаты обнаруженных областей движения. Правда, у нас движущихся объектов получилось несколько — каждое пятно при попытке определить его координаты будет отдельным объектов. Но если мы таким образом обработаем несколько матриц, то мы можем заметить, что несколько объектов движутся синхронного, что позволяет нам отнести их к единому объекту.
Однако, приведенный здесь алгоритм не единственный способ определить движение. Если вам понравиться моя статья, то я продолжу тему и расскажу о других алгоритмах распознавания движения и распознавания образов.
Итак, для проведения эксперимента я снял из окна квартиры короткий видеоролик, разбил его на кадры и сохранил парочку кадров в виде картинок:
Для определения факта движения я решил пока пойти простым путем: превратить изображения в матрицу, из второй матрицы вычесть первую (поэлементно). Вот код на C#, выполняющий данную обработку:
/// <summary>
/// Создать матрицу
/// </summary>
/// <param name="file_name">Имя открываемого файла</param>
private ImageMatrix crate_matrix(string file_name)
{
Bitmap picture = new Bitmap(file_name);
ImageMatrix res = new ImageMatrix();
using (var wrapper = new ImageWrapper(picture,true))
{
res.matrix = new int[wrapper.Width, wrapper.Height];
for (int i = 0; i < wrapper.Width; i++)
{
for (int j = 0; j < wrapper.Height; j++)
{
Color color = wrapper[i, j];
res.matrix[i, j] = (color.R + color.G + color.B) /
3;
}
}
res.height = wrapper.Height;
res.width = wrapper.Width;
res.picture = picture;
}
return res;
}
private void tsmiDifference_Click(object sender, EventArgs e)
{
ImageMatrix matrix1 = crate_matrix("D:\\3\\1.png");
ImageMatrix matrix2 = crate_matrix("D:\\3\\2.png");
Bitmap picture = new Bitmap(matrix1.picture);
using (var wrapper = new ImageWrapper(picture, true))
{
for (int i = 0; i < wrapper.Width; i++)
{
for (int j = 1; j < wrapper.Height; j++)
{
int light1 = matrix1.matrix[i, j];
int light2 = matrix2.matrix[i, j];
int light = Math.Abs(light2-light1);
wrapper[i, j] = Color.FromArgb(light, light, light);
}
}
pbImage.Image = picture;
}
}
И вот что получилось в ходе выполнения данного алгоритма:
На полученной матрице мы видим пропечатанный контур автомобиля и еще какие то контуры на заднем плане, которые, скорее всего, возникли из-за дрожания руки и из за шедшего в момент съемки дождя. На фотографии дождь не виден, но на видео его хорошо заметно.
Для того, чтобы улучшить качество распознавания, можно ввести в программу некое пороговое значение:
if (light < 50) light = 0; else light = 255;
Результат тогда будет совсем другой:
Как видим, при помощи простого вычитания матриц и использования порогового значения мы смогли определить на динамической картинке движущийся объект. Что делать с полученными данным дальше? По сути, что мы имеем сейчас, это бинарная картинка. В ней есть некоторые пятна, которые определяют движущийся объект. Шумы, как видим, наш алгоритм отсек. В дальнейшем, можно определить координаты обнаруженных областей движения. Правда, у нас движущихся объектов получилось несколько — каждое пятно при попытке определить его координаты будет отдельным объектов. Но если мы таким образом обработаем несколько матриц, то мы можем заметить, что несколько объектов движутся синхронного, что позволяет нам отнести их к единому объекту.
Однако, приведенный здесь алгоритм не единственный способ определить движение. Если вам понравиться моя статья, то я продолжу тему и расскажу о других алгоритмах распознавания движения и распознавания образов.
barkalov
Не серьёзно.
PS: EmguCV (OpenCV for .NET) Optical Flow.
AlexandrSurkov
А мне кажется, что для тех, кто совсем не в теме анализа видео потоков, статья не самая плохая. Изложен самый базовый подход на реальном примере.
OpenCV с ходу сложно одолеть.
megabax
Вот с этим полностью согласен. Что бы одолеть OpenCV, для начала надо хотя бы на уровне этой статьи иметь представления по теме. Иначе получиться, как первоклассник, не зная алгебры, попытается понять интегралы.