[алгоритм] Сравнение видео
как дополнительную информацию - относительную яркостьСразу уж дополнительно вейвлетизировать!
Смену сцен, вообще говоря, кодек уже нашел в процессе кодирования. Ключевые кадры будут часто попадать именно на смену сцен. Из этого получается:
1) у дубликатов будет довольно большое количество совпадающих (по времени) ключевых кадров
2) эти кадры можно легко декодировать не декодируя другие
3) их должно быть возможно достать с помощью libavcodec/libavformat (mplayer это как-то делает для перематывания)
Далее задача сводится к сравнению картинок на похожесть. Это должна быть более известная задача.
Тут, конечно, будет куча всяких интересных моментов. Кроме тривиального: "один кодек поставил ключевой кадр на это смене сцен, а другой нет" есть крайне реальная проблема, что одно видео может быть ускорено относительно другого. Преобразование 23.976fps (фильмы снимают в таком) в 25 fps (PAL DVD) чаще всего делают ускорением.
Ну обезразмерить надо относительно времени. Плохо, если при таком проеб... тьфу, преобразовании сместятся КК и сожмется их решетка.
1)
(по времени)у нас НЕТ времени. У нас есть отступы от начала. Пример - камрип, где пират начал снимать в самом конце титров и DVDRip, где титры полностью. В одном случае переход "сцена 0"(титры)-"сцена 1"(первые кадры фильма") придётся, например, на 0:0:7, а во втором случае - на 0:1:30. Зато длина "сцены 1" (т.е. дельта до перехода к "сцене 2") будет практически одинакова для обоих "источников"
2) Ты уже написал - в зависимости от кодека выбор I-фреймов может существенно отличаться. Вероято, что при "сильных" сменах сцен кодеки ведут себя одинаково и пишут I. Тогда, наверное, можно сравнивать текущий I с предыдущими и если он не сильно поменялся ПО НАШИМ меркам - считать, что сцена продолжается.
3) сравнивать картинки - тоже ресурсоёмко. Этого хотелось бы по-максимуму избежать.
При сравнении "цепочки длительности сцен" проблемы с разным фреймрейтом отпадают, потому что мы находимся во "времени зрителя", т.е. у нас время реальное.
http://lists.mplayerhq.hu/pipermail/mplayer-users/2006-May/0...
"mplayer -vf framestep=I some_video.ogg -vo jpeg:outdir=/tmp'"
но "плохие" имена файлов - просто сквозная нумерация. Вот если бы это было ВРЕМЯ...
похоже есть аналогичное решение и для ffmpeg
http://planetcakephp.org/aggregator/items/3401-ffmpeg-multip...
но, похоже проблема с именованием файлов остаётся.
3) сравнивать картинки - тоже ресурсоёмко. Этого хотелось бы по-максимуму избежать.Смотря сколько сравнений придется делать. В твоем первоначальном варианте алгоритма нужно декодировать все кадры и потом еще считать яркость. В двухчасовом фильме их порядка 172 тысяч.
2) Ты уже написал - в зависимости от кодека выбор I-фреймов может существенно отличаться. Вероято, что при "сильных" сменах сцен кодеки ведут себя одинаково и пишут I. Тогда, наверное, можно сравнивать текущий I с предыдущими и если он не сильно поменялся ПО НАШИМ меркам - считать, что сцена продолжается.Если таким образом удастся найти несколько очень "сильных" смен сцен, то по ним можно искать возможное начальное смещение и/или ускорение, а дальше найти несколько совпадающих КК и сравнить в них картинки.
Но все это эвристики. Эвристики в теории всегда хорошо работают, а вот на практике... Вобщем, без экспериментов это все умозрительные рассуждения, не более.
При сравнении "цепочки длительности сцен" проблемы с разным фреймрейтом отпадают, потому что мы находимся во "времени зрителя", т.е. у нас время реальное.Не, фильм реально ускоряют. То есть двухчасовой фильм при записи на PAL DVD станет на пять минут "короче", зато кадров в нем останется столько же.
PS: придумал тут два интересных юзкейза:
1) одна и та же серия какого-нибудь сериала записанная с разных телеканалов; в одной из записей есть реклама посередине (не вырезали по какой-то причине);
2) есть обычная версия фильма и "Directors cut".
1) Вот тут-то на помощь придёт "расстояние Хемминга"
2) Тут уже хуже - ошибка будет существено больше, хотя по идее, если учитывать вставку любого числа сцен как один "токен", то вставка пары-тройки сцен в фильм всё равно оставит цепочки "неделёкими".
С разным фреймрейтом - да, понятно - надо учитывать время начала сцен с некоторой возможной погрешностью.
В целом - да, надо писать и смотреть, что получится.
Спасибо.
На что я замахнулся - сравнение видео по контенту. Так, чтобы даже видео разных пропорций, разного качества (CAMRip vs DVDRip) более-менее нормально сопоставлялось.а зачем тебе сравнивать по видео ? сравнивай по аудио треку, он то наверняка всегда есть и тоже уникален.
берешь кусками аудио, переводишь в общий формат (частота да битность пониже - например 10 кгц 8 бит) и вычисляешь корреляцию между эталонным куском и текущим.
Авторское кино без звука?
Ролики со всяких тьюбов без звука?
Насколько я знаю, чем-то очень похожим занимались на ВМК, в лабе графики и мультимедиа. Попробуй с ними связться.
Полный "рендеринг" видео. Ищем явные смены "сцены" - например, смену яркости картинки на 75%(от балды) от предыдущеей, которая длится 10 секунд (от балды) от предыдущей "сцены". Запоминаем время между сценами и как дополнительную информацию - относительную яркость(относительно "средней яркости видео") и/или тон сцены ("усреднённый тон по кадру").В принципе, всё это реализовано в AviSynth (фреймсервер).
В том числе, эта система поддерживает фильтры, которые и просто высчитывают яркости/тона кадров (в YUV, не уверен насчёт HSV, надо смотреть и даже поддерживают подобные фильтры для смен кадров, то есть разницу между кадрами можно анализировать.
В общем, советую глянуть, или саму систему, или идеи, как это реализовано (и система, и обычно плагины доступны в исходниках). Я думаю, можно именно самой системой обойтись.
Система очень мощная, хотя глюкодром тот ещё.
С ключевыми кадрами идея интересная, но может оказаться, что ряд кодеков на длинных сценах просто ставят ключевики каждые N кадров, может возникнуть ложное впечатление, что там сцены совпадают.
Кодек1: I1(0:0:0)-I1(0:0:7)-I2(0:0:9)-I2(0:0:20)-I2(0:0:27)-I3(0:0:40)
Кодек2: I1(0:0:0)-I1(0:0:2)-I1(0:0:4)-I1(0:0:6)-I1(0:0:8)-I2(0:0:9)-I2(0:0:11)-I2(0:0:13)-I2(0:0:15)-I2(0:0:17)-...-I2(0:0:27)-...-I3(0:0:40)
Сцена2 как начиналась в 0:0:9 так и начинается.
Если анализировать картинку на предмет смены сцен, то связываться с ключевыми кадрами нет смысла.
Абсолютные временаСм.самый первый пост. Я об этом изначально писал, да, мы живём в "пространстве дельт между сценами". Тут я время привёл абсолютное, чтобы было нагляднее.
алгоритмы нечеткого сравнения строк
Блин! Уже не смешно. Смотри отсылку к расстоянию Хемминга.
связываться с ключевыми кадрами
См. выше - выдрать ключевые кадры существенно быстрее, чем отрендерить ВСЁ видео. И это должен быть очень странный алгоритм кодека, чтобы при кодировании КК не попал на нужную нам "сильную смену кадра". Значит можно попробовать пользоваться именно КК.
Блин! Уже не смешно. Смотри отсылку к расстоянию Хемминга.А можешь подробнее пояснить применение расстояния Хемминга в данном случае?
Пусть у нас есть две последовательности дельт (в секундах)
7,4000,56237,731948203
73,4000,56237,731948203
расстояние = 1
Смотреть надо. Если на практике дельты будут сильно прыгать (пока я надеюсь, что округление длительности сцены до секунд даст нужный результат) — найти алгоритм ещё более нечёткого сравнения, чтобы
7,4000,56237,731948203
73,4010,56137,731948000
он считал "похожими на 555 условных единиц".
Пусть ты получил две последовательности времен ключевых кадров (разности t_{KK} - t_{начало}) одинаковой длины, потом обнаружил, что между ними расстояние Хемминга 5. Что хорошего дает такой результат?
1) Из (0) следует, что два видео отличаются в длительности 5 сцен, что при общем числе сцен (условно) 250 составляет 2%,что "достаточно мало" (написано от балды - реально надо будет смотреть результаты, которые алгоритм будет давать на практике) и поэтому мы считаем видео одинаковыми.
1. Для каждого файла:
1.1. В видеопоследовательности находим абсолютные времена "смены сцен";
1.2. Получаем последовательность длительностей сцен;
2. Сравниваем две последовательности расстоянием Хемминга или чем-то похожим. Если расстояние мало — видеопоследовательности считаем "одинаковыми"
?
Если это так, то вставка сцены с рекламой сдвигает одну последовательность относительно другой и в итоге можно легко получить максимальное расстояние Хемминга. В связи с этим, похоже, полезнее считать наибольшую общую подпоследовательность, чем расстояние Хемминга.
См.самый первый пост. Я об этом изначально писал, да, мы живём в "пространстве дельт между сценами". Тут я время привёл абсолютное, чтобы было нагляднее.
Тогда что значит твое ЗНАЕМ ВРЕМЯ! ?
Смотри отсылку к расстоянию Хемминга.
Да видел я. Это очень плохая метрика, для строк (и данной задачи) гораздо лучше есть алгоритмы. Или ты имел в виду расстояние Левенштейна все же?
См. выше - выдрать ключевые кадры существенно быстрее, чем отрендерить ВСЁ видео. И это должен быть очень странный алгоритм кодека, чтобы при кодировании КК не попал на нужную нам "сильную смену кадра". Значит можно попробовать пользоваться именно КК.
Т.е. брать КК, сравнивать их UV и так отсеивать лишние? Ок, годится.
Я спорю, что ли? Хорошо, Хемминг в чистом виде не подходит, значит какой-нибудь Левенштейн или, как ты говоришь, искать наибольшую совпадающую цепочку.
С Хеммингом уже разобрались. Спасибо. Буду думать. Тут и без алгоритма сравнения уже можно укодиться.
С отсеиванием КК - да, так.
Если брать общую, наиболее сложную задачу, вместе с обработкой экранок, то тут такие проблемы встают:
1) возможные небольшие вставки фрагментов
2) разные ролики могут быть сняты с разной яркостью, разная гамма может быть, особенно сильно могут цвета гулять (причём это актуально не только для экранок, но в экранках тут вообще полная попа)
наилучший инвариант, как мне кажется — это смена яркости, как абсолютные яркости, так и дельты между кадрами. Такое пройдёт даже через экранку.
Поэтому, я бы задачу разбил на следующие:
1) Обработать видео файлы и получить текстовые файлы вида "время:абсолютная яркость:разница между соседними кадрами". Такое, по идее, можно сделать с помощью AviSynth
2) полученные данные интерпретировать как просто некие функции от t, функции вещественные. После этого выбирать определённым образом фрагмент функции из первого фильма (по какому-нибудь критерию, начиная с явной смены кадра, например определённым образом нормировать, и сравнивать с фрагментами нормированных кусков из второго фильма (по метрикам из L2, скажем). После чего делать выводы.
В общем, нужно научиться решать задачу 1, после чего поиграться с 2. С 2 уже начинаются нетривиальные вещи, поэтому загадывать дальше смысла нет, сначала нужно поиграться, и посмотреть, как это на практике работает.
Ну, по крайней мере, я бы, наверное, по такому пути пошёл.
Из-за этого KK может быть и без смены сцен
Это чуть выше обсуждалось — после получения всех КК мы по ним пробегаем и ищем смены сцен
возможные небольшие вставки фрагментов
обсуждалось - будем искать наибольшие повторяющиеся цепочки дельт
сняты с разной яркостью
первый пост - "относительную яркость(относительно "средней яркости видео""
это смена яркости
первый пост - "например, смену яркости картинки на 75%(от балды) от предыдущеей"
В общем, нужно научиться решать задачу 1, после чего поиграться с 2. С 2 уже начинаются нетривиальные вещи, поэтому загадывать дальше смысла нет, сначала нужно поиграться, и посмотреть, как это на практике работает.
чуть выше - "Тут и без алгоритма сравнения уже можно укодиться."
Спасибо!
Какая идея приходит в голову.
Создаём функцию, которая показывает, насколько меняется яркость кадра. Далее, рассматриваем особые точки, где яркость или начинает расти быстрее, чем на 10% в секунду, или, наоборот, падать (цифра от балды, но небольшая должна быть). Смотрим на расстояния между этими точками, и составляем таблицу с распределением таких расстояний, то есть, что-то вроде спектра строим. Потом сравниваем 2 распределения (для одного фильма, и для другого на основе чего и делаем выводы о похожести фильмов.
Плюсы: сравнение должно довольно быстро работать, алгоритм устойчив к помехам вроде коротких вставок (спектр поменяется незначительно можно строить много разных функций, увеличив качество поиска, можно делать адаптивное вычисление спектра (если в одном ролике найдено сильно больше особых точек, чем во втором, то можно изменить порог реагирования для одного из фильмов, тем самым ряд проблем с экранками решается).
Минусы, впрочем, тоже есть.
Распознавай текст, который встречается в кадрах и сравнивай его!
Саш, тебя из гестапо за жестокость выгнали, по-моему....
Сравнивать поведение таких вот рамочек
Или то ж гестапо?
ЗЫ..я не в теме
Но травой поделись!
система будет рендерить только ККЧтозанах? Поясни для тех кто в танке.
КК - ключевые кадры.
КК - ключевые кадры.А, тьфу. Я чего-то подумал, что у тебя будет видео только какое-то определённое. В смысле не сразу понял, что "система", которая будет рендерить — это та, что дубликаты ищет.
motion detection будет чертовски плохо работать, если согласно практически утверждённому плану система будет рендерить только КККороче, фигнёй ты страдаешь, если не сказать матернее, со своими КК. Ты какую вообще задачу в первую очередь хочешь решить? Всё и сразу? Забей, и научись сначала решать задачу сравнения видео, когда все кадры доступны. Анализ проще всего делать с помощью Avisynth. Вот такая программа (упрощённый вариант):
#v=AviSource("video_xvid.avi").KillAudio
v=DirectShowSource("video_x264.avi").KillAudio
function fff(frame_num, t_dy, t_du, t_dv)
{
tt = "[Frame:" + String(frame_num) + "][Y_diff:"+ String(t_dy) + "]"+\
"[U_diff:"+ String(t_du) + "][V_diff:"+ String(t_dv) + "]"
return String(tt)
}
v = FrameEvaluate(v, "tdy = YDifferenceFromPrevious")
v = FrameEvaluate(v, "tdu = UDifferenceFromPrevious")
v = FrameEvaluate(v, "tdv = VDifferenceFromPrevious")
v = FrameEvaluate(v, "ta = fff(current_frame, tdy, tdu, tdv)")
WriteFile(v, "video_info.log", "ta")
создаст тебе лог-файл для видео, со строками вида:
[Frame:1832][Y_diff:2.680630][U_diff:0.465540][V_diff:0.533312]
[Frame:1833][Y_diff:2.057590][U_diff:0.357804][V_diff:0.391417]
[Frame:1834][Y_diff:1.624959][U_diff:0.333042][V_diff:0.422066]
[Frame:1835][Y_diff:0.814241][U_diff:0.310328][V_diff:0.367870]
[Frame:1836][Y_diff:38.886059][U_diff:5.146197][V_diff:5.838218]
[Frame:1837][Y_diff:7.528607][U_diff:0.734853][V_diff:1.120834]
[Frame:1838][Y_diff:7.237834][U_diff:0.532971][V_diff:0.874563]
[Frame:1839][Y_diff:7.053646][U_diff:0.558129][V_diff:0.929810]
Это файл читается программой на любом удобном тебе языке программирования, и анализируется. Ключевые кадры видны довольно хорошо, плюс куча других интересных моментов появляется. Можно и более навороченные фильтры делать. Разумно сначала научиться сравнивать видео, а уже потом, когда поймёшь, что для этого нужно, пытаться обрабатывать avi напрямую.
Avisynth мощная, но глючная система, причём под Винды. Не факт, что под wine пойдёт. Но и тут есть альтернативные варианты, например перекодировать фильм так, чтобы все кадры были ключевыми, а проще вообще в отдельные jpeg'и. Потом, правда, придётся функции анализа картинок подключать, но куча либ есть для этого, да и не такие сложные эти функции, при желании можно и самому написать.
Ты же пытаешься начать с того, чтобы научиться парсить avi, причём неполноценно. Полноценная задача парсинга видео сложна, надо кучу форматов учитывать, системо-зависимые кодеки использовать и т.п. Даже программы вроде mplayer или функции из AviSynth криво работают. КК — заведомый тупик, уже обсудили, будет убогое решение, которое окончательно обломается на первом же DVD.
Кстати, с КК могу другое решение предложить. Берёшь несколько КК из одного видео, случайным образом. И сравниваешь его со всеми КК из второго. Если будет много совпадений, значит это похожее видео
2. *DifferenceFromPrevious сравнивают среднее значение, это тоже плохо, нужны гистограммы.
Распознавай текст, который встречается в кадрах и сравнивай его!Сабы просто надо найти в инете и их сравнить.
О! Спасибо!
Оставить комментарий
viktor954
Пишу поиск дубликатов файлов для QNAP. Если с text/binary всё более или менее просто (размер посмотрел, хэш посчитал и всё то чуточку сложнее с музыкой. Хотя тоже в некотором приближении решаемое - существует куча классов, которые могут вытягивать информацию из заголовков и тегов всевозможных форматов. Тоже есть, что сравнивать.А вот с видео...
На что я замахнулся - сравнение видео по контенту. Так, чтобы даже видео разных пропорций, разного качества (CAMRip vs DVDRip) более-менее нормально сопоставлялось.
Пока придумал только вот так:
Полный "рендеринг" видео. Ищем явные смены "сцены" - например, смену яркости картинки на 75%(от балды) от предыдущеей, которая длится 10 секунд (от балды) от предыдущей "сцены". Запоминаем время между сценами и как дополнительную информацию - относительную яркость(относительно "средней яркости видео") и/или тон сцены ("усреднённый тон по кадру").
Что сравниваем - первично сравниваем "цепочки длин сцен". По идее тут должен быть алгоритм, похожий на "расстояние Хемминга". Чем меньше "ошибка" тем больше похоже "последовательности сцен", тем больше похожи ролики. Потом при необходимости сравниваем для совпадающих по длительности сцен "тон" сцены. Даже если у роликов разная длительность и разное качество, то такой алгоритм должен дать достаточно хорошие результаты.
Явный минус алгоритма - ресурсоёмкость. С одной стороны - не страшно - оно будет потихоньку шуршать с низким приоритетом и особой нагрузки не создаст, с другой - на больших коллекциях это всё равно будут недели, месяцы и годы (если считать, что чтобы не нагружать проц хранилки надео рендерить самое быстрое 1:1, а в случае HD - 0,1:1, то даже без учёта остальной части алгоритма чисто на рендеринг уйдёт в среднем полтора часа, т.е. всего 16 фильмов в сутки)
Гугл с ходу алгоритмов, "замахивающихся" на такое соотнесение не дал.
Можете что-нибудь подсказать или посоветовать?