максимальный размер изображения в CIFilter / CIKernel? - PullRequest
3 голосов
/ 06 октября 2010

Кто-нибудь знает, каковы ограничения на размер изображения с помощью пользовательских фильтров CIF?Я создал фильтр, который работает, как и ожидалось, когда изображения имеют размер до 2 мегапикселей, но затем дает очень странные результаты, когда изображения больше.Я проверял это как в своем приложении какао, так и в кварцевом композиторе.Фильтр, который я разработал, является фильтром искажений геометрического типа, который (я думаю) требует ROI и DOD, которые охватывают все входное изображение.Я создал этот фильтр для переназначения панорамных изображений, поэтому мне бы хотелось, чтобы он работал с очень большими (50–100 мегапиксельными) изображениями.

В качестве простого теста рассмотрим следующий фильтр CIF (можно использовать вQuartz Composer), который просто переводит изображение так, что левый нижний угол изображения переводится в центр (я знаю, что это можно сделать с помощью аффинного преобразования, но мне нужно выполнить такую ​​операцию в более сложном фильтре).Этот фильтр работает, как и ожидалось, когда изображение имеет размер 2000x1000, но дает странные результаты, когда входное изображение имеет размер 4000x2000 пикселей.Проблема в том, что либо перевод не смещает угол к центру точно, либо вывод изображения полностью отсутствует.Я заметил другие странные проблемы с более сложными фильтрами на больших изображениях, но я думаю, что этот простой фильтр иллюстрирует мою проблему и может быть воспроизведен в Quartz Composer.

kernel vec4 equidistantProjection(sampler src, __color color)
{
     vec2 coordinate = samplerCoord(src);
     vec2 result;
     vec4 outputImage;

     result.x = (coordinate.x - samplerSize(src).x / 2.0);
     result.y = (coordinate.y - samplerSize(src).y / 2.0);

     outputImage = unpremultiply(sample(src,result));

     return premultiply(outputImage);
}

Такое же странное поведение появляется при использовании рабочих координатвместо координат сэмплера, но в этом случае ошибка возникает для изображений размером 2000x1000, но отлично работает для изображений размером 1000x500

kernel vec4 equidistantProjection(sampler src, __color color, vec2 destinationDimensions)
{
     vec2 coordinate = destCoord();
     vec2 result;
     vec4 outputImage;

     result.x = (coordinate.x - destinationDimensions.x / 2.0);
     result.y = (coordinate.y - destinationDimensions.y / 2.0);

     outputImage = unpremultiply(sample(src,result));
     outputImage = unpremultiply(sample(src,samplerTransform(src, result)));

     return premultiply(outputImage);
}

Для справки я добавил к части Objective-C моего фильтра - (CIImage *)outputImage используйте следующий метод, чтобы установить DOD в качестве всего входного изображения.

- (CIImage *)outputImage
{
    CISampler *src = [CISampler samplerWithImage: inputImage];



     NSArray * outputExtent = [NSArray arrayWithObjects:
            [NSNumber numberWithInt:0],
            [NSNumber numberWithInt:0],
            [NSNumber numberWithFloat:[inputImage extent].size.width],
            [NSNumber numberWithFloat:[inputImage extent].size.height],nil];


return [self apply: filterKernel, src, inputColor, zoom, viewBounds, inputOrigin,
     kCIApplyOptionDefinition, [src definition], kCIApplyOptionExtent, outputExtent, nil];

}

Кроме того, я добавил следующий метод для установки ROI, которую я вызываю в моем методе - (id)init, с помощью этого: [filterKernel setROISelector:@selector(regionOf:destRect:userInfo:)];

- (CGRect) regionOf:(int)samplerIndex destRect:(CGRect)r userInfo:obj
{

     return r;
}

Любая помощь или совет по этому вопросу будет принята с благодарностью.Я уверен, что CIF-фильтры могут работать с большими изображениями, так как я использовал CIBumpDistortion с изображениями размером более 50 мегапикселей, поэтому я должен что-то делать не так.Есть идеи?

1 Ответ

4 голосов
/ 01 ноября 2010

Работая с CoreImage, я обнаружил, что он разрезает большие изображения на части.Например, в вашем случае изображение 4k x 2k можно разделить на 4 изображения 2k x 1k и визуализировать отдельно.К сожалению, эти приемы оптимизации влияют на samplerCoord , и некоторые координатно-зависимые фильтры некорректно работают на больших изображениях.

Мое решение заключалось в использовании destCoord вместо samplerCoord .Конечно, вы должны иметь в виду, что изображение может быть получено с ненулевым происхождением и destCoord .Я написал свой собственный фильтр, поэтому смог передать весь экстент в качестве параметра vec4.

Пример : попробуйте сгенерировать изображение с помощью CIFilter, что-то вроде этого:

float gray = (samplerCoord.x / samplerSize.width) * (samplerCoord.y / samplerSize.height);

Этот вывод должен дать нам черный цвет в (0,0) и белый в (1,1), верно?Однако для больших изображений вы увидите несколько квадратов, а не один градиент.Это происходит из-за оптимизированного рендеринга из ядра CoreImage, я не нашел способа передать его, но вы можете переписать ядро ​​следующим образом:

float gray = ((destCoord.x - rect.x) / rect.size) * ((destCoord.y - rect.y) / rect.height)

Где rect реальный экстент сэмплера, который вы должны передать.Я использовал [inputImage экстент] для этой цели, но это зависит от фильтра и может быть чем-то другим в вашем случае.

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

...