Преобразование CIImage в CGImage слишком медленное

Мне нужно преобразовать CIImage в CGImage. Это код, который я сейчас использую:

CGImageRef img = [myContext createCGImage:ciImage fromRect:[ciImage extent]];

Но его строка кода очень медленная для изображений обычного размера. Слишком медленно, чтобы я мог использовать его должным образом. Есть ли другой более быстрый способ преобразовать эти CIImages в CGImages?

В конце концов я использую Core Graphics, чтобы нарисовать CGImages в CGContext. Если есть способ напрямую нарисовать CIImages в CGContext, я думаю, это тоже должно быть быстрее. Это возможно?

Спасибо


person Laurens    schedule 29.01.2015    source источник


Ответы (2)


Из документации CIImage:

Хотя объект CIImage имеет связанные с ним данные изображения, он не является изображением. Вы можете думать об объекте CIImage как о «рецепте» изображения. Объект CIImage содержит всю информацию, необходимую для создания изображения, но Core Image на самом деле не отображает изображение, пока ему об этом не будет сообщено. Этот метод «ленивой оценки» позволяет Core Image работать максимально эффективно.

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

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

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

Изменить

Я только что попытался создать пример проекта, который фильтрует поток изображений, поступающий с камеры устройства (960x540) на iPad3, применяя цветовой фильтр CIColorMap, и я получаю более 60 кадров в секунду (~ 16 мс).

В зависимости от вашего приложения вы получите лучшую производительность, повторно используя CIContext, ColorMapFilter, inputGradientImage (если они не меняются со временем) и обновляя только inputImage на каждой итерации.

Например, вы должны вызывать prepareFrameFiltering один раз, а затем многократно вызывать applyFilterToFrame: для каждого кадра, который хотите обработать.

@property (nonatomic, strong) CIContext *context;
@property (nonatomic, strong) CIFilter *colorMapFilter;

- (void)prepareFrameFiltering {
    self.context = [CIContext contextWithOptions:nil];
    CIImage *colorMap = [CIImage imageWithCGImage:[UIImage imageNamed:@"gradient.jpg"].CGImage];
    self.colorMapFilter = [CIFilter filterWithName:@"CIColorMap"];
    [self.colorMapFilter setValue:colorMap forKey:@"inputGradientImage"];
}

- (void)applyFilterToFrame:(CIImage *)ciFrame {    
    // filter
    [self.colorMapFilter setValue:ciFrame forKey:@"inputImage"];
    CIImage *ciImageResult = [self.colorMapFilter valueForKey: @"outputImage"];

    CGImageRef ref = [self.context createCGImage:ciImageResult fromRect:ciFrame.extent];

    // do whatever you need

    CGImageRelease(ref);
}
person Tomas Camin    schedule 29.01.2015
comment
А, интересно. Я не знал этого. Итак, я думаю, что на самом деле CIFilter, который я использую, очень медленный. Я использую фильтр ColorMap. Для изображения размером 600x800 требуется около 1 секунды, чтобы отобразить его в CGImage. Что для меня слишком много, так как я делаю это много раз подряд. В любом случае, спасибо за ваш ответ. Я кое-что узнал. И если у вас есть идея, как ускорить этот процесс, пожалуйста, скажите мне. - person Laurens; 29.01.2015
comment
извините, забыл упомянуть, это было на моем macbook pro в iossimulator. На реальном устройстве еще хуже - person Laurens; 29.01.2015
comment
Это странно, поскольку я ожидал, что CIColorMap должен выполняться на графическом процессоре и, следовательно, быстро. Я сам проверю позже. В то же время, какое устройство вы использовали? - person Tomas Camin; 29.01.2015
comment
у меня есть старый ipad 2, на котором я запускаю это - person Laurens; 29.01.2015
comment
Использование графического процессора в симуляторе на самом деле довольно медленное — на самом деле оно медленнее, чем использование графического процессора на реальном устройстве iOS. Фильтр CIColorMap на самом деле довольно прост, всего лишь немного математики и поиска в градиентном изображении. - person David Hayward; 01.02.2015

Самый быстрый способ рендеринга CIImage — это рендеринг в EAGLContext.

Рендеринг CIImage в CGContext не так эффективен, потому что CI работает на графическом процессоре, а CG — это процессорный рендерер. CI должен считывать свои результаты с графического процессора на ЦП, чтобы компьютерная графика могла их отобразить.

Примечание. Это обратное чтение произойдет, когда createCGImage: вызывается, если изображение меньше 4K. Это произойдет при вызове CGContextDrawImage, если изображение больше.

person David Hayward    schedule 01.02.2015