2016-04-28 76 views
0

我寫了下面的代碼到懷舊濾鏡應用於圖像:目標C提高CIImage過濾速度

- (void)applySepiaFilter { 
    // Set previous image 
    NSData *buffer = [NSKeyedArchiver archivedDataWithRootObject: self.mainImage.image]; 
    [_images push:[NSKeyedUnarchiver unarchiveObjectWithData: buffer]]; 


    UIImage* u = self.mainImage.image; 
    CIImage *image = [[CIImage alloc] initWithCGImage:u.CGImage]; 
    CIFilter *filter = [CIFilter filterWithName:@"CISepiaTone" 
            keysAndValues: kCIInputImageKey, image, 
         @"inputIntensity", @0.8, nil]; 
    CIImage *outputImage = [filter outputImage]; 
    self.mainImage.image = [self imageFromCIImage:outputImage]; 
} 

- (UIImage *)imageFromCIImage:(CIImage *)ciImage { 
    CIContext *ciContext = [CIContext contextWithOptions:nil]; 
    CGImageRef cgImage = [ciContext createCGImage:ciImage fromRect:[ciImage extent]]; 
    UIImage *image = [UIImage imageWithCGImage:cgImage]; 
    CGImageRelease(cgImage); 
    return image; 
} 

當我運行這段代碼似乎落後1-2秒。我聽說核心圖像比核心圖形更快,但我對渲染時間無動於衷。我想知道這是否會在CoreGraphics甚至OpenCV(在項目中的其他地方使用)中更快地處理?如果沒有,我有什麼辦法可以優化這段代碼以更快運行?

+0

你用儀器找出這裏真的很慢嗎? – zneak

+0

@zneak這些工具是什麼? –

+0

掉下我的腦袋,像「時間分析器」。 – zneak

回答

3

根據圖像的大小,我幾乎可以保證它在覈心圖形上的速度比使用核心圖像要慢。如果圖像很小,Core Graphics可能會很好,但如果您正在進行大量處理,則會比使用GPU渲染慢得多。

核心圖像非常快,但是,您必須非常清楚發生了什麼。 Core Image的大部分性能都是由於上下文的設置以及將圖像複製到Core Image /從Core Image複製而來的。除了複製字節之外,核心圖像也可以在圖像格式之間進行轉換。

你的代碼做什麼,每次執行以下操作:

  • 創建CIContext。 (慢)
  • 從CGImage中取字節並創建一個CIImage。
  • 將圖像數據複製到GPU(慢速)。
  • 處理棕褐色過濾器(快速)。
  • 將結果圖像複製回CGImage。 (慢)

這不是峯值性能的配方。 CGImage中的字節通常位於CPU內存中,但Core Image想要使用GPU進行處理。在Getting the Best Performance文檔中提供

出於性能考慮一個很好的參考爲核心圖片:

  • 不要創建CIContext對象每次渲染時間。 上下文存儲大量狀態信息;重用它們會更有效率。
  • 評估您的應用是否需要色彩管理。除非你需要它,否則不要使用它。請參閱您的應用是否需要色彩管理?
  • 避免使用GPU上下文呈現CIImage對象時的Core Animation動畫。 如果您需要同時使用兩者,則可以同時設置使用CPU。

  • 確保圖像不超過CPU和GPU限制。 (iOS)

  • 儘可能地使用較小的圖像。 性能與輸出像素數量成比例。您可以將Core Image呈現爲更小的視圖,紋理或幀緩衝區。允許Core Animation高級顯示大小。

  • 使用核心圖形或圖像I/O函數來裁剪或縮小比例,如函數CGImageCreateWithImageInRect或CGImageSourceCreateThumbnailAtIndex。

  • UIImageView類最適合靜態圖像。 如果您的應用需要獲得最佳性能,請使用較低級別的API。

  • 避免CPU和GPU之間不必要的紋理傳輸。 在應用內容比例因子之前,渲染到與源圖像大小相同的矩形。

  • 考慮使用更簡單的過濾器,可以產生類似於算法過濾器的結果。例如,CIColorCube可以產生類似於CISepiaTone的輸出,並且可以更高效地執行此操作。

  • 利用在iOS 6.0及更高版本中對YUV圖像的支持。

如果你需要實時處理性能,你將要使用的OpenGL認爲CoreImage可以輸出渲染,以及讀取圖像直接字節到GPU,而不是從一個CGImage拉的。使用GLKView和覆蓋drawRect:是一個相當簡單的解決方案,可以獲得Core Image可以直接渲染的視圖。在GPU上保存數據是獲得Core Image峯值性能的最佳方式。

儘量重複使用。爲後續渲染保留CIContext(如文檔所述)。如果你最終使用OpenGL視圖,這些也是你可能想要儘可能重用的東西。

您也可以使用軟件渲染獲得更好的性能。軟件渲染將避免從GPU複製。 [CIContext contextWithOptions:@{kCIContextUseSoftwareRenderer: @(YES)}]但是,這在實際渲染中會有性能限制,因爲CPU渲染速度通常比GPU渲染速度慢。

因此,您可以選擇難度水平來獲得最佳性能。最好的性能可能會更具挑戰性,但是一些調整可能會使您的使用情況達到「可接受」的性能。