Когда я начал работать над магистерской диссертацией на тему «Анализ пространственной структуры динамических изображений», то столкнулся с проблемой, что очень трудной найти какие-то готовые примеры алгоритмов распознавания образов и движущихся объектов. Везде, и в литературе, и в Интернете одна только голая теория. Цель написания данной статьи как раз восполнить данный пробел.
Итак, для проведения эксперимента я снял из окна квартиры короткий видеоролик, разбил его на кадры и сохранил парочку кадров в виде картинок:


Для определения факта движения я решил пока пойти простым путем: превратить изображения в матрицу, из второй матрицы вычесть первую (поэлементно). Вот код на 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;
Результат тогда будет совсем другой:

Как видим, при помощи простого вычитания матриц и использования порогового значения мы смогли определить на динамической картинке движущийся объект. Что делать с полученными данным дальше? По сути, что мы имеем сейчас, это бинарная картинка. В ней есть некоторые пятна, которые определяют движущийся объект. Шумы, как видим, наш алгоритм отсек. В дальнейшем, можно определить координаты обнаруженных областей движения. Правда, у нас движущихся объектов получилось несколько — каждое пятно при попытке определить его координаты б��дет отдельным объектов. Но если мы таким образом обработаем несколько матриц, то мы можем заметить, что несколько объектов движутся синхронного, что позволяет нам отнести их к единому объекту.
Однако, приведенный здесь алгоритм не единственный способ определить движение. Если вам понравиться моя статья, то я продолжу тему и расскажу о других алгоритмах распознавания движения и распознавания образов.