# MaskTools

## Общая информация

Авторы: kurosu и Manao
Версия: 1.5.8
Где взять: http://manao4.free.fr/
Категория: Разное
Требования: Цветовое пространство YV12

## Содержание

- I) О MaskTools
  - 1) Общее описание
  - 2) Детальное описание
- II) Описания функций
- III) Практическое использование
  - 1) MSharpen
  - 2) MSoften
  - 3) Устранение "радуги"
  - 4) Передискретизация в fxtoon
  - 5) Warpsharp для темных клипов
  - 6) псевдо - деинтерлейс (проблемы с цветностью все равно останутся)
  - 7) Непрямоугольные наложения
  - 8) Замена фона
  - 9) Kmf-Toon ;-)
- IV) Планы на будущее
- V) Предупреждение (не пропустите эту часть, но я не заставляю Вас изучать ее)
- VI) Версии
- VII) Обзор для разработчиков

## I) О MaskTools

### 1) Общее описание

После обработки клипа обычно нужна только часть результата. Например, у вас есть клип, который назван smooth и является результатом сглаживания (размытия, например фильтром blur() ) клипа, который назовем source.
Большую часть шума удалось убрать, но также исчезли и детали. Таким образом хорошо было бы сохранить часть пикселей из исходного клипа там, где есть большая разница в цвете или яркости. Так работает фильтр MSmooth, от D. Graft. Теперь предположим, что мы заменим все те пикселы из сглаженного варианта клипа, которые хотелось бы оставить, на белые, а остальные - на черные. Это и есть так называемая маска. Набор фильтров MaskTools предназначен для создания, преобразования и использования таких масок в цветовом пространстве YV12

### 2) Описание

В этом плагине имеются следующие функции :

- Binarize Превращает клип в маску на основании порогового преобразования
- CombMask Производит маску, содержащую информацию о тех местах исходного клипа, где наблюдается "гребенка"
- DEdgeMask / DEdgeMask2 Строит маску, содержащую только те места исходного клипа, где есть резкие перепады контраста (края деталей изображения), с использованием порогов для сравнения. Пороги можно отменить, задавая соответствующие значения параметров.
- EdgeMask Строит маску, содержащую только те места исходного клипа, где есть резкие перепады контраста, используя указанную величину порогов для сравнения. Пороги можно отменить, задавая соответствующие значения параметров. То же, что и DEdgeMask, но с предопределенным ядром преобразования.
- Expand "расширяет" области с максимальными значениями пикселов, распространяя значение максимума из области 3х3 пиксела на всю эту область. Обратная функция называется Inpand.
- FitY2UV/FitY2U/FitY2V Изменяет размер плоскости Y и заменяет какую-то из плоскостей UV/U/V тем, что получилось в результате изменения размера. Можно задавать любую функцию масштабирования, втч. и не встроенную в АвиСинт. Обратные функции называются FitU2Y и FitV2Y.
- Inflate будет 'раздувать' пикселы с наибольшими значениями, заменяя каждый пиксел на среднее арифметическое 8ми соседних пикселов если оно окажется больше исходного значения этого пиксела. Обратное действие производит функция Deflate (посвящается Phil Katz) (Фил Кац - изобретатель программы PKZip - прим. перев)
- Invert производит инверсию пиксела (т.е. out = 255 - in); может также служить для производства эффекта "соляризации" картинки.
- Logic производит основные логические операции (на самом деле те, которые есть в наборе команд MMX, хотя функции C тоже имеются, в основном из-за ограничений, связанных с размерами картинки).
- RGBLUT/YV12LUT/YV12LUTxy представляют собой просто табличные преобразования и позволяют быстро применить функцию к каждому пикселу изображения.
- MaskedMerge берет 3 клипа и производит объединение первого и второго, взвешенное по маске, которую представляет третий клип.
- MotionMask создает маску по движению в кадре.
- OverlayMask сравнивает 2 клипа по их яркости и цветности и создает маску на основании схожести этих значений с использованием порогов сравнения (почти то же самое что делает ColorKeyMask).
- YV12Convolution позволяет производить свертку картинку по произвольной матрице.
- YV12Layer - эквивалент OverLay.
- YV12Substract- то же, что и Subtract, работает в YV12, но *должна* быть немного побыстрее (т.к. использует MMX).

В дополнение к вышесказанному, все функции кроме группы FitPlane, допускают еще 3 параметра: Y, U и V. В зависимости от значений этих параметров к соответствующим цветовым плоскостям применяются следующие операции :

- значение = 3 означает что к указанной плоскости будет применено соответствующее преобразование,
- значение = 2 означает что в указанную плоскость будет помещена копия 2й цветовой плоскости (если это возможно)
- значение = 1 означает что указанная плоскость вообще не будет никак обрабатываться.
- значение = [-255...0] приведет к заполнению плоскости указанным значением, взятым с обратным знаком (например, чтобы получить яркость без цветовой информации, поставьте U=128,V=128)

И наконец, некоторые функции могут обрабатывать только часть кадра:

- эта возможность определяется параметрами (offX, offY) (положение начальной точки) и (w,h) (ширина и высота обрабатывамой области); фильтры должны модифицировать эти параметры так, чтобы обрабатываемая область находилась внутри обеих картинок.
- если фильтр использует 2 клипа (исключение - YV12Layer), то оба клипа должны иметь одинаковые размеры
- во всех случаях, размеры картинки должны быть как минимум кратны 8 (а иногда 16) чтобы фильтры могли использовать MMX и работать на полной скорости.

Первоначально все это задумывалось имея в виду модульность и атомарность операций (или полезность), а вовсе не скорость. В результате получилось все раздутым и медленным. Сами решайте, действительно это так, или не совсем... Примеры из III) со встроенными фильтрами должны работать быстрее.

## II) Описания функций.

### Binarize

`Binarize` (clip, int "threshold", bool "upper")
The `Binarize` производит пороговое преобразование. Если upper=true, то пиксел, значение которого строго больше порога, будет установлен в 0, в противном случае - в 255. Напротив, при upper=false, то пиксел, значение которого строго больше чем параметр threshold, будет установлен в 255, в противном случае - в 0.
Значения по умолчанию такие : threshold = 20, upper = true.

### CombMask

`CombMask` (clip, int "thY1", int "thY2")

Этот фильтр строит маску, содержащую те места исходного клипа, где наблюдается "гребенка". Значения порогов работают так же, как и в других фильтрах : после вычисления оценки "гребенчатости", если это значение меньше thY1, то пикселу присваивается 0, если больше thY2, пикселу присваивается 255, если посередине, то значение оценки делится на 256 и присваивается пикселу.

Оценка гребенки это (upper_pixel - pixel)*(lower_pixel - pixel). Как можно видеть, результат не приводится к диапазону 0..255, (не нормализуется), поскольку если бы это делалось, обычное значение было бы 1 или 2, не более. Таким образом можно устанавливать пороги выше чем 255, хотя это вряд ли полезно.

Значения по умолчанию : thY1 = 10 и thY2 = 10 ( таким образом по умолчанию получается маска с двумя возможными значениями пикселей ).

### DEdgeMask / DEdgeMask2

`DEdgeMask` (clip, int "thY1", int "thY2", int "thC1", int "thC2", string "matrix", float "divisor", bool "setdivisor", bool "vmode")
`DEdgeMask2` (clip source, clip low_thres, clip high_thres, string"matrix", float "divisor", bool "setdivisor", bool "vmode")
Этот фильтр делает маску краев деталей изображения (или просто краев) - областей с максимальными перепадами контраста. Алгоритм использует свертку, результат которой сравнивается с порогами thY1 и thY2 ( яркость ); thC1 и thC2 ( цветность ). Сравнение по порогам производится следующим образом ( r - результат свертки ) :

- r <= th1 дает 0.
- th1 < r <= th2 дает r.
- th2 < r дает 255.

Чтобы получилась маска с двумя уровнями, нужно установить th1=th2.

Выбор ядра свертки осуществляется при помощи параметра matrix. Ее значение должно быть матрицей 3 на 3 с целочисленными коэффициентами, разделенными одиночными пробелами. Так, строки "-1 -1 -1 -1 8 -1 -1 -1 -1" и "0 -1 0 -1 0 1 0 1 0" дадут операторы Лапласа и Собеля соответственно (см. "laplace" и "sobel" в описании к EdgeMask.

Так как коэффициенты должны быть целыми, параметр divisor служит для уточнения результата свертки. Этот результат будет поделен на значение параметра divisor. Если divisor не определен, то по умолчанию он берется равным сумме положительных коэффициентов матрицы, то есть производит нормализацию результата. Этот параметр может быть как целым числом, так и числом с плавающей точкой, хотя с целым числом фильтр будет работать быстрее.
Параметр setdivisor нужен только для совместимости с предыдущими версиями. Не надо его использовать.
Наконец, vmode позволяет сделать маску с центральным значением 128, а не 0. Значения по умолчанию : thY1 = 0, thY2 = 20, thC1 = 0, thC2 = 20, matrix = "-1 -1 -1 -1 8 -1 -1 -1 -1" и vmode=false.

DEdgemask2 работает в целом так же как и DEdgeMask, за исключением того, что вместо двух числовых значений порогов он требует задания двух клипов. Каждый из этих клипов содержит локальные пороги для каждого пикселя. Например, нужно сделать адаптивные пороги в зависимости от контраста каждого кадра. Локальные минимумы и максимумы можно сделать посредством inpand() and expand(). Разность делается с помощью YV12LUTxy или YV12Subtract. И вот пожалуйста, получаем клип с пороговыми значениями, зависящими от локального контраста.

### EdgeMask

`EdgeMask` (clip, int "thY1", int "thY2", int "thC1", int "thC2", string "type")
Этот фильтр создает маску краев изображения. Алгоритм поиска краев использует свертку, результат которой сравнивается с порогами thY1 и thY2 ( яркость ); thC1 и thC2 ( цветность ). Сравнение по порогам производится следующим образом ( r - результат свертки ) :

- r <= th1 дает 0.
- th1 < r <= th2 дает r.
- th2 < r дает 255.

Чтобы получилась маска с двумя уровнями, нужно установить th1=th2.

Выбор ядра свертки производится заданием параметра type :

- type = "roberts" :

  2 | -1
  -1 | 0

- type = "sobel" :

  0 | -1 | 0
  -1 | 0 | 1
  0 | 1 | 0

- type = "laplace" :

  -1/8 | -1/8 | -1/8
  -1/8 | 1 | -1/8
  -1/8 | -1/8 | -1/8

- type = "special" :

  -1/4 | 0 | -1/4
  0 | 1 | 0
  -1/4 | 0 | -1/4

Возможны еще два значения параметра type ("cartoon" и "line" ), которые не документированы.

Значения по умолчанию : thY1 = 0, thY2 = 20, thC1 = 0, thC2 = 20 and type = "sobel".

### FitY2U / FitY2V / FitY2UV FitU2Y / FitV2Y / FitU2V / FitV2U

Фильтры `FitPlane` (clip, string resizer)

Семейство фильтров `FitPlane` включает следующие фильтры :
- яркость в цветность: `FitY2U`, `FitY2V`, `FitY2UV`
- цветность в яркость: `FitU2Y`, `FitV2Y`
- цветность в цветность: `FitU2V`, `FitV2U`

При помощи этих фильтров маску, созданную для одной цветовой плоскости можно распространить на другую цветовую плоскость.

### Inpand / Expand / Deflate / Inflate

`Inpand` (clip)
`Expand` (clip)
`Deflate` (clip)
`Inflate` (clip)

Эти фильтры позволяют увеличить или уменьшить маску. `Expand` заменяет значение пиксела максимумом из значений всех окружающих пикселов. `Inpand` наоборот, выбирает минимальное значение. `Inflate` вычисляет среднее значение окружающих пикселов, и заменяет данный пиксел вычисленным средним только если это среднее больше исходного значения пиксела. `Deflate` делает то же самое, но заменяет пиксел если среднее значение окружающих пикселов меньше исходного значения пиксела.

Изображения, полученные в результате действия фильтров `Expand` и `Inflate` будут иметь более высокие значения пикселов, чем исходные. Напротив, в результате действия `Inpand` и `Deflate` получатся изображения с более низкими значениями пикселов.

Увеличение (уменьшение) маски, произведенное `Deflate` (`Inflate`) выглядит более мягким, чем произведенное `Expand` (`Inpand`).

### HysteresyMask

`HysteresyMask` (mask_clip1, mask_clip2)

Этот фильтр делает одну маску из двух. Теоретически первая должна лежать внутри второй, хотя все будет работать и если это не так. Однако результаты будут менее интересными. Идея этого фильтра состоит в том, чтобы усилить те части маски, которые принадлежат обеим маскам.

Этот алгоритм интересен тем, что позволяет, например, взять одну маску, содержащую все края всех деталей изображения, плюс, естественно, шум, и вторую, с минимумом деталей и минимумом шума, и получить результат, содержащий наиболее интересные края деталей изображения, но без шума (которого не было во второй маске).

### Invert

`Invert` (clip, int offX, int offX, int w, int h)

Этот фильтр заменяет значение пиксела на 255 - (значение пиксела).

Binarize(upper=false) можно рассматривать как

Invert().Binarize(upper=true)

(хотя оно в действительности обрабатывается совсем не так).

### Logic

`Logic` (mask_clip1, mask_clip2, string "mode")

Этот фильтр создает маску, являющуюся результатом операции с двумя масками. Тип операции задается параметром mode.

- mode="and" : работает только с двухуровневыми масками (пикселы которых имеют значения только 0 или 255 ). На выходе получается пересечение двух масок, т.е. если оба исходных пиксела имеют значение 255, то результат будет 255, в противном случае 0.
- mode="or" : работает только с двухуровневыми масками На выходе получается объединение двух масок, т.е. если хотя бы один исходный пиксел имеет значение 255, то результат будет 255, в противном случае 0.
- mode="xor" : работает только с двухуровневыми масками На выходе получается разность двух масок, т.е. если один исходный пиксел имеет значение 255 а второй 0, то результат будет 255, в противном случае 0.
- mode="andn" : работает только с двухуровневыми масками На выходе получается разность между первой и второй масками, т.е. если исходный пиксел первой маски имеет значение 255 а второй маски - 0, то результат будет 255, во всех остальных случаях 0.
- mode="min" : возвращает минимум значений соответствующих пикселов первой и второй масок. Для двухуровневых масок это то же самое что mode="and".
- mode="max" : возвращает максимум значений соответствующих пикселов первой и второй масок. Для двухуровневых масок это то же самое что mode="or".

Результат логической операции, произведенной над пикселами, значения которых отличаются от 0 и 255 непредсказуем.

Значение по умолчанию : mode = "and".

### RGBLUT / YV12LUT / YV12LUTxy / YUY2LUT

`YV12LUT` (clip, string "yexpr", string "uexpr", string "vexpr")
`YUY2LUT` (clip, string "yexpr", string"uexpr", string "vexpr")
`RGBLUT` (clip, string "Rexpr", string "Gexpr", string "Bexpr", string "AMPFile")
`YV12LUTxy` (clipx, clipy, string "yexpr", string "uexpr", string "vexpr")

Эти фильтры вычисляют заданную функцию для каждого пиксела изображения. Для того чтобы повысить скорость фильтра, все возможные результаты функции вычисляются заранее и хранятся в таблице. `RGBLUT` работает так же как и `YV12LUT`, за исключением дополнительного параметра AMPFile. Он позволяет подгрузить цветовой профиль фотошопа (color profile в англоязычной версии).

Функция задается в в виде строки с выражением в так называемой обратной польской записи. Идея состоит в том чтобы писать сначала аргументы а потом оператор, действующий на эти аргументы. Так, вместо "3 + 7" надо писать "3 7 +", а "sin(3)" становится "3 sin". Далее, "3 * 7 + 5" переходит в "3 7 * 5 +", а "(3 + 7) * 5" в "3 7 + 5 *". Это похоже на советские программируемые калькуляторы Б3-34 и подобные (прим. перев.) Главное достоинство такой записи - полное отсутствие скобок.

Вычисления производятся над вещественными числами. Положительные значения в логических выражениях означают "истина", отрицательные - "ложь". Символ "x" означает исходное значение пиксела. В функции `YV12LUTxy` используется также обозначение "y" для соответствующего пиксела из второго клипа. Элементы выражения (числа, символы и знаки операций) должны быть разделены одиночными пробелами.

Вот некоторые функции и операторы :

- +, -, /, *, ^, % - соответственно сложение, вычитание, деление, умножение, возведение в степень и остаток от деления.
- &, |, °, !& - логические операции "и", "или", "исключающее или", "не". В качестве логического значения "истина" они возвращают 1.0, "ложь" представляется как -1.0.
- <, <=, >, >=, =, != - операции сравнения "меньше", "меньше или равно", "больше", "больше или равно", "равно", "не равно". В случае если условие истинно, они возвращают 1.0, иначе как -1.0.
- cos, sin, tan, acos, asin, atan, exp, log, abs - это функции косинус,синус, тангенс, арккосинус, арксинус, арктангенс, еx логарифм и модуль.
- ? означает условное выражение. Это тернарный оператор ( с тремя аргументами) Первый из них - условие, второй - значение если условие истинно, третий - если ложно.

Примеры :

* Постеризация картинки по порогу в 128 : "x 128 < 0 255 ?". Это переводится на язык С как : "(x < 128) ? 0 : 255".
* Levels(il, gamma, ih, ol, oh) ( см. фильтр Levels ) : "x il - ih il - / 1 gamma / ^ oh ol - *". На С это будет "(((x - il) / (ih - il)) ^ (1 / gamma)) * (oh - ol)".

Значение по умолчанию : Yexpr = Uexpr = Vexpr = "x" ( то есть попросту ничего не делать ).

### MaskedMerge

`MaskedMerge` (base_clip, overlay_clip, mask_clip)

Этот фильтр накладывает клип, заданный как overlay_clip на клип base_clip по маске mask_clip. А именно, пусть bc, oc и mc представляют значения трех соответствующих пикселов в base_clip, overlay_clip и mask_clip, тогда результат будет такой :

    v = ((256 - mc) * bc + mc * oc + 128) / 256

128 присутствует здесь чтобы уменьшить ошибку, возникающую из-за целочисленного деления.

Таким образом, там где маска равна 255, результат будет взят из overlay_clip, где маска равна 0, результат будет взят из base_clip, а при промежуточных значениях маски будет одним из переходных от overlay_clip к base_clip значений.

### MotionMask

`MotionMask` (clip, int "thY1", int "thY2", int "thC1", int "thC2", int "thSD")

Этот фильтр создает маску движения картинки. Как и в других фильтрах, после создания маска подвергается пороговому преобразованию. Этот фильтр также проверяет наличие смены сцены и не выдает маску если такая смена имеет место.

Определение смены сцены осуществляется посредством вычисления суммы отличий данного кадра и предыдущего. Эта сумма нормируется (averaged ?) и сравнивается с порогом thSD. Если она оказывается больше этого порога, то фиксируется факт смены сцены.

Движение анализируется подобно NoMoSmooth, то есть для каждого пиксела вычисляется сумма отличий данного пиксела и всех окружающих от соответствующих пикселов предыдущего кадра. Полученная сумма делится на 9 чтобы результат лежал между 0 и 255.

Этот алгоритм дает некую оценку движения. Он хорошо работает на краях изображения, и хуже - на однородных участках.

Значения по умолчанию : thY1= 20, thY2 = 20, thC1 = 10, thC2 = 10 и thSD = 10.

### YV12Convolution

`YV12Convolution` (clip, string "horizontal", string "vertical", int "total", bool "automatic", bool "saturate")

Эти фильтры вычисляют свертку картинки с ядром, образованным произведением строки horizontal на столбец vertical. Обе эти параметра должны содержать нечетное количество целых или вещественных чисел, разделенных одиночными пробелами. Параметр total - фактор нормализации, на который делится произведение вышеописанных векторов. Если параметр automatic равен 'true', то результат делится на сумму коэффициентов матрицы. Таким образом, общая яркость картинки не изменяется. Saturate позволяет определить поведение фильтра в случае если результат свертки меньше нуля.

- saturate = true : отрицательные значения заменяются на нули.
- saturate = false : отрицательные значения берутся по модулю.

Если параметр total не задан, он полагается равным сумме коэффициентов ядра свертки, таким образом достигается хорошая нормализация для сверток типа размытие / повышение резкости.

Если хотя бы один коэффициент горизонтального или вертикального векторов представлен вещественным числом, то все вычисления будут производиться с вещественными числами, в результате фильтр будет работать медленнее.

Значения по умолчанию : horizontal = "1 1 1", vertical = "1 1 1", automatic = false, saturate = true.

### YV12Subtract

`YV12Subtract` (clip1, clip2, int tol, bool "widerange")

Этот фильтр вычисляет разность между двумя клипами. Существует несколько способов вычисления такой разности, в зависимости от значений параметров widerange и tol.

- widerange = true : сначала вычисляется разность ( n ) между пикселами двух клипов, потом она пересчитывается по формуле r = 128 + 128 * pow(n / 255,1 / tol). Если tol < 0, 1 / tol считается равным 0.5.
- widerange = false :
  - tol < 0 : вычисляется модуль разности клипов, и пересчитывается как r = n / 2 + 128.
  - tol >= 0 : вычисляется модуль разности клипов, возвращается 0 если n меньше tol, n - tol в противном случае.

Значения по умолчанию : tol = -1, widerange = false.

## III) Примеры практического использования (не протестированные достаточно основательно)

В этих примерах не получатся в точности такие же результаты, как и в исходных фильтрах, работа которых имитируется, кроме того, все это работает довольно медленно. Кроме множества дополнительных функций, никаких новых идей.

Примечания:
- Я слишком ленив чтобы изменять синтаксис каждый раз, особенно в отношении функционирования mode=2, и в отношении изменений в поведении EdgeMask ( например, теперь уже не нужно использовать Binarize )
- Некоторые фильтры, описанные тут, уже существуют (imagereader, пороги для сравнения, ...).

#### 1) MSharpen

    # Строим EdgeMask от clip1, делаем Binarize и называем результат clip3
    # Посредством любого фильтра увеличения резкости (шарп) получаем из clip1 clip2
    ...
    return MaskMerge(clip1, clip2, clip3)

Края деталей изображения, содержащегося в clip2, у которых яркость выше порога, заданного для Binarize заменят исходные значения в clip1. Еще можно сделать фильтр с какой-нибудь таблично заданной функцией (лучше всего подходит колоколообразная кривая), использовать его вместо Binarize, и получить шарпинг взвешенный по яркости границ. Так работает SmartSmoothHiQ.

    clip2 = clip1.<EdgeEnhancer>(<parameters>)
    #Каналы цветности U и V фильтровать не нужно, а Y нужно
    #EdgeMask(<...>, "roberts", Y=3, U=-128, V=-128) работает с яркостями
    clip3 = clip1.EdgeMask(15, 60, "roberts", Y=3, U=1, V=1)
    return MaskedMerge(clip1, clip2, clip3)

#### 2) MSoften

Заменить в предыдущем примере EdgeEnhancer на какой-нибудь фильтр для размытия (несколько раз примененный Blur или spatialsoftenMMX ) и поставить upper=true чтобы выделить однородные участки.

#### 3) Устранение "радуги" (как описано здесь )

Внимание, это тоже не супер-эффективное решение.

    clip2 = clip1 до упора размытый (например deen("m2d") или edeen)
    #Берем маску краев по яркости и растягиваем края
    # чтобы получились более широкие области в этих местах
    clip3 = clip1.EdgeMask(6, "roberts", Y=3, U=1, V=1).Inflate(Y=3, U=1, V=1)
    #Теперь возьмем эту маску и применим ее к каналам цветности
    clip3 = YtoUV(clip3, clip3).ReduceBy2().Binarize(15, upper=false, Y=1, U=3, V=3)
    #Нам надо обработать цветность вокруг краев, но не трогать при этом яркость
    return MaskedMerge(clip1, clip2, clip3, Y=1, U=3, V=3)

#### 4) Передискретизация в fxtoon

Не проверено

    . С помощью tweak затемните картинку или сделайте фильтр, который пропорционально
    уменьшит значения яркости.
    -> clip2
    . Постройте маску краев изображения. Примените сглаживание (Supersampling).
    Примените Binarize с высоким порогом. Сделайте Inflate -> clip3
    . Примените более темные пиксели из clip2 в зависимости от значений clip3

#### 5) Warpsharp для темных клипов

Не проверено

    . Примените warpsharp -> clip2 (материал для замены)
    . Сделайте ограничивающий фильтр по яркости -> clip3 (mask)

#### 6) псевдо - деинтерлейс (проблемы с цветностью все равно останутся)

Не проверено

    clip2 = clip1.SeparateFields().SelectEven().<Method>Resize(<parameters>)
    clip3 = clip1.<CombingDetector>(<parameters>)
    return MaskedMerge(clip1, clip2, clip3, Y=3, U=3, V=3)

#### 7) Непрямоугольные наложения

На самом деле, делается проще через layer и mask...

    #Обманем ImageReader, которому нужно целое число кадров в секунду
    #В основном исходники все в YUY2/YV12
    clip = AviSsource("test.avi").ConvertToYV12().assumefps(fps)
    #Загрузим картинку для наложения
    image = ImageReader("mask.bmp", 0, clip.framecount()-1, 24, use_DevIl=false)
    #Предположим что черный должен быть прозрачным
    #С другими цветами все будет сложнее (*)
    masktemp = imageYV12.Binarize(17, upper=false, Y=3)
    #Подгоним маску, сделанную по яркости, к каналам цветности
    mask = Mask.FitY2UV()
    #Теперь у нас есть маска, в которой записано, что нужно оставить...
    #Заменим все что нужно по маске
    MaskedMerge(clip, image, mask, Y=3, U=3, V=3)
    #* можно сделать так: mask = OverlayMask(image, image.BlankClip("$xxxxxx"), 1, 1)

#### 8) Замена фона

Этот пример работает лучше в RGB. Чтобы избежать типичных проблем с шумом или артефактами сжатия, лучше применить размытие к клипу и к фону.

    source = AviSource("overlay.avi").AssumeFPS(24)
    #Размытие исходного изображения
    clip = source.Blur(1.58).Blur(1.58).Blur(1.58)
    #Загрузим фон
    bgnd = ImageReader("bgnd.ebmp", 0, clip.framecount()-1, 24,
    use_DevIl=false)
    #Загрузим новый фон
    new = ImageReader("new.ebmp", 0, clip.framecount()-1, 24,
    use_DevIl=false)
    #фильтр, делающий mask = (clip~overlay?)
    mask = OverlayMask(clip, overlay.ConvertToYV12(), 10, 10)
    MaskedMerge(source, new.ConvertToYV12(), mask, Y=3, U=3, V=3)

#### 9) K-mfToon

Я должен включить больше информации, в том числе исходные ссылки и постинги, но сейчас я думаю что автор исходного mfToon, mf (mf@onthanet.net) не сильно обидится на это.
Результат функции, содержащейся в K-mfToon.avs должен быть идентичным с результатом исходного mftoon.avs (оба включены в дистрибутив), но она вдвое быстрее.
Для использования функций:
- Из mfToon:
. включите плагины "MaskTools", "warsharp", "awarsharp"

## IV) Планы на будущее

Пока нет, все зависит от реакции общественности.

## V) Предупреждение

Этот плагин распространяется в соответствии с лицензией GPL. Перед использованием ознакомьтесь с ее условиями.
Также рекомендуется учитывать интересы окружающих и не думать так : "я знаю как это сделать, но никому не скажу".
И наконец : я протестировал очень небольшую часть из всех возможных применений этого пакета (думаю что 5% - несколько часов на отладку ;-). Это значит, что ваши сообщения об ошибках будут _очень_ ценны (обратное тоже верно - я про отсутствие таких сообщений...)

## VI) Версии

1.5.8 - 8 Авг 2005

- Добавлен DEdgeMask2.

1.5.7

- Добавлен YUY2LUT.

1.5.6

- Исправлена работа с цветностью в YV12LUTxy.

v1.5.5 - 6 Ноя 2004

- Версия с Binarize заработала;
  для Pentium4 с HT.

v1.5.4 - 14 Окт 2004

- Переработана часть фильтров.

1.5.2 - 1.5.3

- ?

1.5.1

- Полностью переписана документация (Спасибо Вилберту).
- DEdgeMask теперь допускает не только целые делители. Однако, если делитель все-таки целочисленный, фильтр *должен* работать быстрее.
- DEdgeMask получил обратно параметр "setdivisor", но он теперь нужен только для совместимости с уже написанными скриптами.
- YV12LUTxy : новый фильтр, написанный по идее Didee. Символ "y" представляет значение пиксела второго клипа.

1.4.16

- Исправлено : в Logic "min" & "max" работали неправильно.
- Исправлено : в Logic & Subtract не работали режимы MMX & iSSE оптимизаций, вследствие глупой ошибки.

1.4.15.3

- Добавлен RGBLUT : работает как YV12LUT ( только вместо R, G и B используются Y, U и V ).
- Кроме того, можно задавать AMP-файл ( из Фотошопа ).

1.4.15.2

- Устранена ошибка в YV12LUT. Как всегда, глупая...
- В YV12LUT добавлены операторы сравнения и логические ( <, <=, >, >=, ==, !=, &, !&, |, ° ( xor ) )
- В YV12LUT добавлен тернарный оператор : ? ( как в C )

1.4.15.1

- В YV12LUT убрана ошибка. Надеюсь, теперь будет работать.

1.4.15

- Новый фильтр : HysteresyMask. Строит новую маску краев по двум имеющимся. См. документацию.

1.4.14.2

- Несколько исправлений относящихся к отрицательным значениям Y, U и V ( edgemask, dedgemask, motionmask, combmask, logic )
- Несколько исправлений относящихся к использованию offX / offY / w и h ( в фильтрах maskedmerge, binarize, expand, YV12subtract, yv12lut )
- В YV12LUT убрана ошибка, не позволяющая его использовать с некоторым фильтром.
- В YV12Convolution теперь можно использовать не только целые коэффициенты. Но с целыми работает быстрее. Кроме того, при переполнении ( результате большем 255 или меньшем 0 ), медленная но верная функция дополнительной обработки приведет результат к 0 и 255 соответственно.

1.4.14.1

- Исправление в YV12LUT позволяющее использовать отрицательные числа

1.4.14

- Исправлено : В YV12Layer была ненужная проверка, которая могла прводить к неработоспособности фильтра.
- Исправлено : В DEdgeMask не учитывался порог.
- Исправлено : Фильтр Logic теперь полностью работоспособен, в C и MMX
- Добавлено : Документация на фильтр Logic
- Добавлено : Два режима для Logic : "Min" и "Max" ( C, MMX, iSSE )
- Добавлено : В DEdgeMask возможность нормализации.
- Исправлено : Документация.

1.4.13

- Исправлено : ошибка в MotionMask ( последняя строка считалась неверно )
- Оптимизация : MaskedMerge теперь работает одинаково в MMX и C, и MMX оптимизация теперь включена по умолчанию.
- Добавлено : В EdgeMask можно использовать ядро Лапласа. См. документацию
- Добавлено : 'Новый' фильтр, DEdgeMask, позволяет задавать свое преобразование ( ценой уменьшения скорости )

1.4.12

- Изменение поведения : MotionMask и EdgeMask теперь работают с крайними пикселами изображения, расширяя маску на эти пикселы.
- Исправлено : Inflate / Inpand / Expand / Deflate, при использовании отрицательных значений параметров y,u и v вели себя странно.
- Добавлено : В YV12LUT теперь есть функция abs.

1.4.11

- Исправлено : EdgeMask с MMX и без дает разные результаты. Оптимизация отключена. Чтобы включить, ставьте usemmx = true. Работает только для клипов с размерами, делящимися на 16.
- Исправлено : EdgeMask : первая и последняя строки не всегда считались.
- Исправлено : MaskedMerge : MMX давал более темный результат, чем надо. Оптимизация отключена. Чтобы включить, ставьте usemmx = true. Работает только для клипов с размерами, делящимися на 16.

1.4.10

- Исправлено : первая и последняя строки неправильно обрабатывались в inflate / deflate
- Invert исключен из Masktools, и включен в Ависинт.

1.4.9

- Новый фильтр : CombMask. Как обычно, читайте документацию.

1.4.8

- YV12Convolution теперь допускает отрицательные коэффициенты в матрице. Это позволяет использовать фильтр как детектор краев деталей изображения.
- У YV12Convolution теперь есть новый параметр saturate. Если он равен true, то значения пикселей принудительно загоняются в диапазон [0..255] во время вычислений.
- Новый фильтр : LUT. См. документацию

1.4.7

- MotionDetection переименован в MotionMask. Я понимаю что это звучит глупо, зато логично.
- Добавлена проверка размера при использовании MMX в MotionMask
- Немного изменена оптимизация MMX в Binarize.
- Новый фильтр : YV12Convolution. Позволяет делать свертку с матрицей любого (почти любого) размера. См. документацию.

1.4.6

- Определение смены сцен в MotionDetection оптимизировано под iSSE ( а значит вам понадобится Athlon XP / Pentium IV ). Работает с Athlon XP, не тестировано на
  Pentium IV, может быть отключено установкой параметра usemmx = false.
- Оптимизировано вычисление движения, без всякого MMX ( просто избежав необходимости считать одно и то же 3 раза ). Таким образом фильтр должен быть теперь более или менее в 3 раза быстрее.

1.4.5

- Добавлен фильтр MotionDetection, пока без MMX или ассемблерных вставок. См. документацию. Используется идея фильтра Sansgrip (NoMoSmooth) и делает маску движения непосредственно в нужном цветовом пространстве.

1.4.4

- Восстановлена оптимизация MMX в MaskedMerge
- Осуществлен возврат к оптимизации от Kurosu в Invert

1.4.3

- Сделаны некоторые оптимизации под MMX ( binarize, invert )
- Исправлены некоторые оптимизации под MMX ( это в основном значит что некоторые MMX оптимизации были отключены ). Теперь будет работать под P4.

1.4.2

- Исправлены ошибки в inpand / expand / inflate / deflate

1.4.1

- Исправлена страшная ошибка "multiple instances of a filter with different functions needed"

1.4.0

- Добавлен экспериментальный фильтр LUT. Не тестировано, отлажу потом.

1.3.0 (версия для внутреннего употребления)

- Сделана доступной для использования функция FitPlane (ее все равно слишком много если надо изменить размер только одной плоскости), которая раньше была недокументированной. Еще добавлена функция FastFitPlane (соответствующие FitPlane теперь практически бесполезны)
- Теперь допускается задание области обработки для нескольких фильтров, однако это вряд ли приведет к заметному ускорению обработки.
- Подправлен YV12Layer (в основном неиспользуемые режимы "Darken"/"Lighten")
- Добавлена функция OverlayMask, которая сравнивает 2 клипа, и выдает маску по одинаковым их частям. (медленно и далеко от совершенства).

1.2.0 (версия для внутреннего употребления)

- YV12Layer: больше нет бесполезных преобразований в RGB32! Все примерно как в Arithmetic (только третий клип не нужен), так что здесь все нормально...
- YV12Substract: а почему только C-шная версия ? Маски явно недостаточно используются в Ависинте |-[

1.1.0 (версия для внутреннего употребления)

- Бывшие inflate/deflate теперь называются expand/inpand, и появились новые функции с теми же именами.
- Добавлены функции Logic и Arithmetic (не будут работать потому что не отлажены)
- Edgemask теперь использует 4 порога (2 для яркости и 2 для цветности). Они нужны чтобы : установить в 0 или не менять значение, зависящее от первого порога; установить в 255 или не менять значение, зависящее от второго порога.

1.0.2 (последняя версия - публичные релизы приостановлены):

- Исправлен сдвиг для edgemask при использовании преобразований Собеля и Робертса (неправильная инструкция MMX )
- MaskMerge теперь работает (маска очищается перед использованием... можно проверить например используя MaskMerge(clip3,clip3))

1.0.1: Первоначальный релиз

## VII) Обзор для разработчиков

Пропустите все до цифры V) если вам не интересно разбираться в исходном коде.
Исходники представляют собой простой проект VC++ 6. Каждый фильтр лежит в своем собственном каталоге, где находится h-файл, нужный для интерфейса, исходники интерфейсного класса, исходники функций-обработчиков и их h-файлы. Например EdgeMask:
- EdgeMask.h используется интерфейсом чтобы определить, как фильтр "выглядит", (но в interface.cpp находятся определения соглашений о вызовах и экспортируемых функций)
- EM_func.h описывает обработчики (у них у всех должны быть одинаковые параметры):
. Line_MMX и Line_C
. Roberts_MMX и Roberts_C
. Sobel_MMX и Sobel_C
- EM_func.cpp, как и все <что-то>_func.cpp, содержит реализацию обработчиков, и иногда их MMX версии.
- EdgeMask.cpp содержит реализацию класса; в конструкторе выбирается соответствующая функция-обработчик (MMX? C? Roberts? Line? Sobel?) и передается как указатель в GetFrame
Interface.cpp соержит экспортируемые функции и все внешние функции (AVSValue ... Create_<filter>).
ChannelMode.cpp определяет модель Channel. Туда может быть добавлен некий эквивалент функции debugprintf.
Такой краткий обзор вряд ли поможет всем разработчикам, так же как примеры V) не помогут пользователям, но это все что есть. Конечно, со временем, все улучшится, в зависимости от общего успеха идеи. У которой есть один главный недостаток - время исполнения, что скорее всего приведет к тому, что использование этого пакета будет не особенно интенсивным, если оно вообще будет.

`$English Date: 2005/08/28 12:19:19 $
Русский перевод 04.10.2005 Alexander Nickolsky (anickol@yahoo.com)`