Разделение на подклассы CIFilter: рецепты для пользовательских эффектов
Можно создать пользовательские эффекты при помощи вывода одного фильтра изображения как ввод другого, объединив в цепочку столько фильтров вместе, сколько Вы хотели бы. При создании эффекта этот способ, которым Вы хотите использовать многократно, рассмотрите разделение на подклассы CIFilter
инкапсулировать эффект как фильтр.
Эта глава показывает, как Базовое Изображение разделяет на подклассы CIFilter
создать CIColorInvert
фильтр. Тогда это описывает рецепты для объединения в цепочку вместе множества фильтров для достижения интересных эффектов. Путем выполнения процедуры разделения на подклассы в Разделении на подклассы CIFilter для Создания Фильтра CIColorInvert необходимо быть в состоянии создать фильтры из рецептов в этой главе или предприятии дальше для создания собственных интересных комбинаций встроенных фильтров, предоставленных Базовым Изображением.
Разделение на подклассы CIFilter для создания фильтра CIColorInvert
Когда Вы разделяете на подклассы CIFilter
можно изменить существующие фильтры путем кодирования их с предварительно установленными значениями или путем объединения в цепочку их вместе. Базовое Изображение реализует некоторые свои встроенные фильтры с помощью этого метода.
Для разделения на подклассы фильтра, необходимо выполнить следующие задачи:
Объявите свойства для входных параметров фильтра. Необходимо снабдить префиксом каждое входное название параметра
input
, такой какinputImage
.Переопределите
setDefaults
метод, при необходимости. (Это не необходимо в этом примере, потому что входные параметры устанавливаются значения.)Переопределите
outputImage
метод.
Фильтр 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; |
} |
Рецепт фильтра цветовой рирпроекции
Удаляет цвет или диапазон цветов из исходного изображения и затем составляет исходное изображение с фоновым изображением.
Создать фильтр цветовой рирпроекции:
Создайте карту куба данных, отображающих значения цвета, которые Вы хотите удалить так, они прозрачны (альфа-значение 0.0).
Используйте фильтр CIColorCube, и куб отображаются для удаления цвета цветовой рирпроекции из исходного изображения.
Используйте фильтр CISourceOverCompositing для смешивания обработанного исходного изображения по фоновому изображению
Следующие разделы показывают, как выполнить каждый шаг.
Создайте карту куба
Цветной куб является 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)
Увеличивает яркость изображения в периферии поверхности, обнаруженной в изображении.
Создать белый фильтр виньетки:
Найдите человеческую поверхность в изображении.
Создайте основное использование карты оттенка CIRadialGradient, центрируемый на поверхности.
Смешайте основную карту оттенка с исходным изображением.
Следующие разделы показывают, как выполнить каждый шаг.
Найдите поверхность
Используйте 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
к карте оттенка, произведенной на последнем шаге.
Рецепт фильтра наклонного сдвига
Выборочно фокусирует изображение для моделирования миниатюрной сцены.
Создать фильтр наклонного сдвига:
Создайте размытую версию изображения.
Создайте два линейных градиента.
Создайте маску путем составления композита линейных градиентов.
Составьте размытое изображение, маску и исходное изображение.
Следующие разделы показывают, как выполнить каждый шаг.
Создайте Размытую Версию изображения
Установите входные параметры фильтра 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
к маске, т.е. объединенным градиентам.
Маска будет влиять только на внешнюю часть изображения. Прозрачные части маски покажут через исходное, необработанное изображение. Непрозрачные части маски позволяют размытому изображению показывать.
Анонимный рецепт фильтра поверхностей
Находит поверхности в изображении и пикселизирует их так, они не могут быть распознаны.
Создать анонимный фильтр поверхностей:
Создайте пикселизированную версию изображения.
Создайте маску с помощью поверхностей, обнаруженных в изображении.
Смешайте пикселизированное изображение с исходным изображением с помощью маски.
Следующие разделы показывают, как выполнить каждый шаг.
Создайте версию 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
Переходы от одного изображения до другого путем пикселизации каждого изображения.
Создать фильтр pixellate-перехода:
Используйте CIDissolveTransition для перехода между исходными и конечными изображениями.
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
.
Старый пленочный рецепт фильтра
Уменьшает качество видеоизображения, чтобы заставить его быть похожим на старый, неуклюжий аналоговый фильм.
Создать старо-пленочный фильтр:
Примените фильтр CISepiaTone к исходному видеоизображению.
Создайте случайным образом переменные белые пятнышки.
Создайте случайным образом переменные темные царапины.
Составьте пятнышки и царапины на изображение цвета сепии.
Следующие разделы показывают, как выполнить каждый шаг.
Примените сепию к видеоизображению
Установите входные параметры 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.