Разделение на подклассы CIFilter: рецепты для пользовательских эффектов

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

Эта глава показывает, как Базовое Изображение разделяет на подклассы CIFilter создать CIColorInvert фильтр. Тогда это описывает рецепты для объединения в цепочку вместе множества фильтров для достижения интересных эффектов. Путем выполнения процедуры разделения на подклассы в Разделении на подклассы CIFilter для Создания Фильтра CIColorInvert необходимо быть в состоянии создать фильтры из рецептов в этой главе или предприятии дальше для создания собственных интересных комбинаций встроенных фильтров, предоставленных Базовым Изображением.

Разделение на подклассы CIFilter для создания фильтра CIColorInvert

Когда Вы разделяете на подклассы CIFilter можно изменить существующие фильтры путем кодирования их с предварительно установленными значениями или путем объединения в цепочку их вместе. Базовое Изображение реализует некоторые свои встроенные фильтры с помощью этого метода.

Для разделения на подклассы фильтра, необходимо выполнить следующие задачи:

Фильтр CIColorInvert, предоставленный Базовым Изображением, является изменением на фильтре CIColorMatrix. Как его имя предполагает, CIColorInvert предоставляет векторы к CIColorMatrix, инвертирующим цвета входного изображения. Последуйте простому примеру, показанному в Перечислении 5-1 и Перечислении 5-2 для создания собственных фильтров.

Перечисление 5-1  интерфейс для фильтра CIColorInvert

@interface CIColorInvert: CIFilter{
    CIImage *inputImage;
}
@property (retain, nonatomic) CIImage *inputImage;
@end

Перечисление 5-2  outputImage метод для фильтра CIColorInvert

@implementation CIColorInvert
@synthesize inputmage;
- (CIImage *) outputImage
{
    CIFilter *filter = [CIFilter filterWithName:@"CIColorMatrix" keysAndValues:
        kCIInputImageKey, inputImage,
        @"inputRVector", [CIVector vectorWithX: -1 Y:0 Z:0],
        @"inputGVector", [CIVector vectorWithX:0 Y:-1 Z:0 ],
        @"inputBVector", [CIVector vectorWithX: 0 Y:0 Z:-1],
        @"inputBiasVector", [CIVector vectorWithX:1 Y:1 Z:1],
        nil];
    return filter.outputImage;
}

Рецепт фильтра цветовой рирпроекции

Удаляет цвет или диапазон цветов из исходного изображения и затем составляет исходное изображение с фоновым изображением.

Рисунок 5-1  цепочка обработки фильтра Цветовой рирпроекции

Создать фильтр цветовой рирпроекции:

Следующие разделы показывают, как выполнить каждый шаг.

Создайте карту куба

Цветной куб является 3D таблицей цветов. Базовое Изображение фильтрует CIColorCube, принимает значения цвета, как введено и применяет таблицу поиска к значениям. Таблица поиска по умолчанию для CIColorCube является единичной матрицей — значение, которое является, ничего не делает к его данным, которыми снабжают. Однако этот рецепт требует, чтобы Вы удалили полностью зеленый из изображения. (Можно удалить различный цвет, если Вы хотели бы.)

Необходимо удалить весь зеленый из изображения путем установки зеленый в альфу = 0.0, который делает его прозрачным. «Зеленый» охватывает диапазон цветов. Самый прямой способ продолжиться состоит в том, чтобы преобразовать значения цвета в изображении от RGBA до значений HSV. В HSV оттенок представлен как угол вокруг центральной оси цилиндра. В том представлении можно визуализировать цвет как часть круга и затем просто удалить часть, представляющую цвет цветовой рирпроекции.

Для удаления зеленый необходимо определить минимальные и максимальные углы вокруг центрального доступа, содержащие зеленые оттенки. Затем для чего-либо это зелено, Вы устанавливаете его альфа-значение в 0,0. Чистый зеленый при соответствии значения 120º. Минимальные и максимальные углы должны центрироваться вокруг того значения.

Данные карты куба должны быть предварительно умноженной альфой, таким образом, последний шаг для создания карты куба должен умножиться, значения RGB альфой оценивают, Вы просто вычислили, который является или 0.0 для зеленых оттенков или 1.0 иначе. Перечисление 5-3 показывает, как создать цветной куб, необходимый для этого рецепта фильтра.

Перечисление 5-3  цветной куб в коде

// Allocate memory
const unsigned int size = 64;
float *cubeData = (float *)malloc (size * size * size * sizeof (float) * 4);
float rgb[3], hsv[3], *c = cubeData;
 
// Populate cube with a simple gradient going from 0 to 1
for (int z = 0; z < size; z++){
    rgb[2] = ((double)z)/(size-1); // Blue value
    for (int y = 0; y < size; y++){
        rgb[1] = ((double)y)/(size-1); // Green value
        for (int x = 0; x < size; x ++){
            rgb[0] = ((double)x)/(size-1); // Red value
            // Convert RGB to HSV
            // You can find publicly available rgbToHSV functions on the Internet
            rgbToHSV(rgb, hsv);
            // Use the hue value to determine which to make transparent
            // The minimum and maximum hue angle depends on
            // the color you want to remove
            float alpha = (hsv[0] > minHueAngle && hsv[0] < maxHueAngle) ? 0.0f: 1.0f;
            // Calculate premultiplied alpha values for the cube
            c[0] = rgb[0] * alpha;
            c[1] = rgb[1] * alpha;
            c[2] = rgb[2] * alpha;
            c[3] = alpha;
            c += 4; // advance our pointer into memory for the next color value
        }
    }
}
// Create memory with the cube data
NSData *data = [NSData dataWithBytesNoCopy:cubeData
                       length:cubeDataSize
                       freeWhenDone:YES];
CIColorCube *colorCube = [CIFilter filterWithName:@"CIColorCube"];
[colorCube setValue:@(size) forKey:@"inputCubeDimension"];
// Set data for cube
[colorCube setValue:data forKey:@"inputCubeData"];

Удалите зеленый из исходного изображения

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

[colorCube setValue:myInputImage forKey:kCIInputImageKey];
CIImage *result = [colorCube valueForKey:kCIOutputImageKey];

Смешайте обработанное исходное изображение по фоновому изображению

Установите входные параметры фильтра CISourceOverCompositing следующим образом:

  • Набор inputImage к изображению, произведенному из фильтра CIColorCube.

  • Набор inputBackgroundImage к изображению, показывающему новый фон. Этот пример использует изображение пляжа.

Изображение переднего раздела теперь появляется, как будто это находится на пляже.

Белый Vignette для Рецепта Фильтра Поверхностей (только iOS)

Увеличивает яркость изображения в периферии поверхности, обнаруженной в изображении.

Рисунок 5-2  Белая цепочка обработки фильтра Vignette

Создать белый фильтр виньетки:

Следующие разделы показывают, как выполнить каждый шаг.

Найдите поверхность

Используйте CIDetector класс для определения местоположения поверхности в изображении. Первый элемент в массиве это featuresInImage:options: возвраты являются поверхностью, на которую воздействует фильтр. После того, как Вы имеете поверхность, вычисляете центр поверхности от границ, предоставленных детектором. Вам нужно центральное значение для создания карты оттенка. Перечисление 5-4 показывает, как определить местоположение поверхности с помощью CIDetector.

Перечисление 5-4  Используя CIDetector для определения местоположения одной поверхности

CIDetector *detector = [CIDector detectorOfType:CIDetectorTypeFace
                                        context:nil
                                        options:nil];
NSArray *faceArray = [detector featuresInImage:image options:nil];
CIFeature *face = faceArray[0];
CGFloat xCenter = face.bounds.origin.x + face.bounds.size.width/2.0;
CGFloat yCenter = face.bounds.origin.y + face.bounds.size.height/2.0;
CIVector *center = [CIVector vectorWithX:xCenter Y:yCenter];

Создайте карту оттенка

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

Для достижения этого эффекта установите входные параметры на CIRadialGradient следующим образом:

  • Набор inputRadius0 к значению, больше, чем самая длинная размерность изображение.

  • Набор inputRadius1 к значению, больше, чем поверхность, такой как face.bounds.size.height + 50.

  • Набор inputColor0 непрозрачному белому.

  • Набор inputColor1 прозрачному белому.

  • Установите inputCenter к центру границ поверхности, которые Вы вычислили с Перечислением 5-4.

Смешайте градиент с поверхностью

Установите входные параметры фильтра CISourceOverCompositing следующим образом:

  • Набор inputImage к исходному изображению.

  • Набор inputBackgroundImage к карте оттенка, произведенной на последнем шаге.

Рецепт фильтра наклонного сдвига

Выборочно фокусирует изображение для моделирования миниатюрной сцены.

Рисунок 5-3  цепочка обработки фильтра Наклонного Сдвига

Создать фильтр наклонного сдвига:

Следующие разделы показывают, как выполнить каждый шаг.

Создайте Размытую Версию изображения

Установите входные параметры фильтра CIGaussianBlur следующим образом:

  • Набор inputImage к изображению Вы хотите обработать.

  • Набор inputRadius к 10,0 (который является значением по умолчанию).

Создайте два линейных градиента

Создайте линейный градиент из единственного цвета (такой как зеленый или серый), который варьируется сверху донизу. Установите входные параметры CILinearGradient следующим образом:

  • Набор inputPoint0 к (0, 0.75 * h)

  • Набор inputColor0 к (0,1,0,1)

  • Набор inputPoint1 к (0, 0.5*h)

  • Набор inputColor1 к (0,1,0,0)

Создайте зеленый линейный градиент, варьирующийся от нижней части до вершины. Установите входные параметры CILinearGradient следующим образом:

  • Набор inputPoint0 к (0, 0.25 * h)

  • Набор inputColor0 к (0,1,0,1)

  • Набор inputPoint1 к (0, 0.5*h)

  • Набор inputColor1 к (0,1,0,0)

Создайте маску из линейных градиентов

Для создания маски установите входные параметры фильтра CIAdditionCompositing следующим образом:

  • Набор inputImage к первому линейному градиенту Вы создали.

  • Набор inputBackgroundImage к второму линейному градиенту Вы создали.

Объедините размытое изображение, исходное изображение и градиенты

Последний шаг должен использовать фильтр CIBlendWithMask, устанавливая входные параметры следующим образом:

  • Набор inputImage к размытой версии изображения.

  • Набор inputBackgroundImage к исходному, необработанному изображению.

  • Набор inputMaskImage к маске, т.е. объединенным градиентам.

Маска будет влиять только на внешнюю часть изображения. Прозрачные части маски покажут через исходное, необработанное изображение. Непрозрачные части маски позволяют размытому изображению показывать.

Анонимный рецепт фильтра поверхностей

Находит поверхности в изображении и пикселизирует их так, они не могут быть распознаны.

Рисунок 5-4  Анонимная цепочка обработки фильтра Поверхностей

Создать анонимный фильтр поверхностей:

Следующие разделы показывают, как выполнить каждый шаг.

Создайте версию Pixellated изображения

Установите входные параметры фильтра CIPixellate следующим образом:

  • Набор inputImage к изображению, содержащему поверхности.

  • Набор inputScale к max(width, height)/60 или другое значение, кажущееся приятным Вам, где width и height обратитесь к ширине и высоте изображения.

Создайте маску из поверхностей, обнаруженных в изображении

Используйте CIDetector класс для находки поверхности в изображении. Для каждой поверхности:

  • Используйте CIRadialGradient filtBuilding маска для поверхностей, обнаруженных в искусственном создании репутации маска для поверхностей, обнаруженных в формирователе изображения для создания круга, окружающего поверхность.

  • Используйте фильтр CISourceOverCompositing для добавления градиента к маске.

Перечисление 5-5  , Создающее маску для поверхностей, обнаруживается в изображении

CIDetector *detector = [CIDetector detectorOfType:CIDetectorTypeFace
                                          context:nil
                                          options:nil];
NSArray *faceArray = [detector featuresInImage:image options:nil];
 
// Create a green circle to cover the rects that are returned.
 
CIImage *maskImage = nil;
 
for (CIFeature *f in faceArray) {
    CGFloat centerX = f.bounds.origin.x + f.bounds.size.width / 2.0;
    CGFloat centerY = f.bounds.origin.y + f.bounds.size.height / 2.0;
    CGFloat radius = MIN(f.bounds.size.width, f.bounds.size.height) / 1.5);
    CIFilter *radialGradient = [CIFilter filterWithName:@"CIRadialGradient" keysAndValues:
        @"inputRadius0", @(radius),
        @"inputRadius1", @(radius + 1.0f),
        @"inputColor0", [CIColor colorWithRed:0.0 green:1.0 blue:0.0 alpha:1.0],
        @"inputColor1", [CIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0],
        kCIInputCenterKey, [CIVector vectorWithX:centerX Y:centerY],
        nil];
    CIImage *circleImage = [radialGradient valueForKey:kCIOutputImageKey];
    if (nil == maskImage)
        maskImage = circleImage;
    else
        maskImage = [[CIFilter filterWithName:@"CISourceOverCompositing" keysAndValues:
            kCIInputImageKey, circleImage,
            kCIInputBackgroundImageKey, maskImage,
            nil] valueForKey:kCIOutputImageKey];
}

Смешайте изображение Pixellated, маску и исходное изображение

Установите входные параметры фильтра CIBlendWithMask к следующему:

  • Набор inputImage к пикселизированной версии изображения.

  • Набор inputBackgroundImage к исходному изображению.

  • Набор inputMaskImage к к составленным зеленым кругам.

Рецепт фильтра перехода Pixellate

Переходы от одного изображения до другого путем пикселизации каждого изображения.

Рисунок 5-5  цепочка обработки фильтра Перехода Pixellate

Создать фильтр pixellate-перехода:

Следующие разделы показывают, как выполнить каждый шаг.

Создайте растворить переход

Установите входные параметры фильтра CIDissolveTransition следующим образом:

  • Набор inputImage к изображению, от которого Вы хотите перейти.

  • Набор inputTagetImage к изображению, к которому Вы хотите перейти.

  • Набор inputTime к значению, подобному min(max(2*(time - 0.25), 0), 1), который является функцией ската, это фиксируется между двумя значениями.

Pixellate результат перехода

Установите фильтр CIPixellate для варьирования масштаба пикселей в течение долгого времени путем установки его входных параметров как:

  • Набор inputImage к выводу отображают от фильтра CIDissolveTransition.

  • Набор inputScale изменяться в течение долгого времени путем предоставления значений от треугольной функции: 90*(1 - 2*abs(time - 0.5))

  • Используйте значение по умолчанию для inputCenter.

Старый пленочный рецепт фильтра

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

Рисунок 5-6  Старая Пленочная цепочка обработки фильтра

Создать старо-пленочный фильтр:

Следующие разделы показывают, как выполнить каждый шаг.

Примените сепию к видеоизображению

Установите входные параметры CISepiaTone следующим образом:

  • Набор inputImage к видеоизображению для применения эффекта к.

  • Набор inputIntensity к 1,0.

Создайте случайным образом Переменные белые пятнышки

Используйте фильтр CIRandomGenerator, производящий цветной шум. Это не имеет никаких входных параметров.

Для обработки шума так, чтобы Вы получили только белые пятнышки используйте фильтр CIColorMatrix с входным набором параметров следующим образом:

  • Набор inputImage к выводу, произведенному случайным генератором.

  • Набор inputRVector, inputGVector, и inputBVector к (0,1,0,0).

  • Набор inputBiasVector к (0,0,0,0).

Используйте фильтр CISourceOverCompositing для смешивания пятнышек с видеоизображением путем установки входных параметров фильтра следующим образом:

  • Набор inputImage к изображению белых пятнышек, произведенному фильтром CIColorMatrix.

  • Набор inputBackgroundImage к изображению, произведенному фильтром CISepiaTone.

Создайте случайным образом Переменные темные царапины

Используйте фильтр CIRandomGenerator снова для генерации окрашенный шумом. Тогда обработайте его вывод с помощью фильтра CIAffineTransform с этими входными параметрами:

  • Набор inputImage к шуму, сгенерированному фильтром CIRandomGenerator.

  • Набор inputTransform масштабировать x 1,5 и y 25. Это делает пиксели толстыми и длинными, но они будут все еще окрашены.

Альтернатива использованию CIAffineTransform должна преобразовать шум с помощью imageByApplyingTransform: метод.

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

  • Набор inputImage к преобразованному видеоизображению.

  • Набор inputRVector к (4,0,0,0).

  • Набор inputGVector, inputBVector, и inputAVector к (0,0,0,0).

  • Набор inputBiasVector к (0,1,1,1).

Это приводит к голубым царапинам.

Для создания царапин темными примените фильтр CIMinimumComponent к голубым царапинам. Этот фильтр использует минимальное значение r, g, b, значения для создания полутонового изображения.

Составьте пятнышки и царапины к видеоизображению сепии

Установите входные параметры фильтра CIMultiplyCompositing следующим образом:

  • НаборinputBackgroundImage к обработанному видеоизображению (тон сепии, белые пятнышки).

  • НаборinputImage к темным царапинам, т.е. выводу от фильтра CIMinimumComponent.