iOS中的圖像處理(二)——卷積運算
關於圖像處理中的卷積運算,這裏有兩份簡明扼要的介紹:文一,文二。
其中,可能的一種卷積運算代碼如下:
- (UIImage*)applyConvolution:(NSArray*)kernel { CGImageRef inImage = self.CGImage; CFDataRef m_DataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage)); CFDataRef m_OutDataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage)); UInt8 * m_PixelBuf = (UInt8 *) CFDataGetBytePtr(m_DataRef); UInt8 * m_OutPixelBuf = (UInt8 *) CFDataGetBytePtr(m_OutDataRef); int h = CGImageGetHeight(inImage); int w = CGImageGetWidth(inImage); int kh = [kernel count] / 2; int kw = [[kernel objectAtIndex:0] count] / 2; int i = 0, j = 0, n = 0, m = 0; for (i = 0; i < h; i++) { for (j = 0; j < w; j++) { int outIndex = (i*w*4) + (j*4); double r = 0, g = 0, b = 0; for (n = -kh; n <= kh; n++) { for (m = -kw; m <= kw; m++) { if (i + n >= 0 && i + n < h) { if (j + m >= 0 && j + m < w) { double f = [[[kernel objectAtIndex:(n + kh)] objectAtIndex:(m + kw)] doubleValue]; if (f == 0) {continue;} int inIndex = ((i+n)*w*4) + ((j+m)*4); r += m_PixelBuf[inIndex] * f; g += m_PixelBuf[inIndex + 1] * f; b += m_PixelBuf[inIndex + 2] * f; } } } } m_OutPixelBuf[outIndex] = SAFECOLOR((int)r); m_OutPixelBuf[outIndex + 1] = SAFECOLOR((int)g); m_OutPixelBuf[outIndex + 2] = SAFECOLOR((int)b); m_OutPixelBuf[outIndex + 3] = 255; } } CGContextRef ctx = CGBitmapContextCreate(m_OutPixelBuf, CGImageGetWidth(inImage), CGImageGetHeight(inImage), CGImageGetBitsPerComponent(inImage), CGImageGetBytesPerRow(inImage), CGImageGetColorSpace(inImage), CGImageGetBitmapInfo(inImage) ); CGImageRef imageRef = CGBitmapContextCreateImage(ctx); CGContextRelease(ctx); UIImage *finalImage = [UIImage imageWithCGImage:imageRef]; CGImageRelease(imageRef); CFRelease(m_DataRef); CFRelease(m_OutDataRef); return finalImage; }
方法的參數kernel是卷積運算中的卷積核,下麵是幾種濾鏡的卷積核:
#pragma mark - #pragma mark - Basic Convolutions /* Reference : * https://docs.gimp.org/en/plug-in-convmatrix.html */ - (UIImage *)sharpen { // double dKernel[5][5] = { // {0, 0.0, -1.0, 0.0, 0}, // {0, -1.0, 5.0, -1.0, 0}, // {0, 0.0, -1.0, 0.0, 0} // }; double dKernel[5][5] = { {0, 0.0, -0.2, 0.0, 0}, {0, -0.2, 1.8, -0.2, 0}, {0, 0.0, -0.2, 0.0, 0} }; NSMutableArray *kernel = [[[NSMutableArray alloc] initWithCapacity:5] autorelease]; for (int i = 0; i < 5; i++) { NSMutableArray *row = [[[NSMutableArray alloc] initWithCapacity:5] autorelease]; for (int j = 0; j < 5; j++) { [row addObject:[NSNumber numberWithDouble:dKernel[i][j]]]; } [kernel addObject:row]; } return [self applyConvolution:kernel]; } - (UIImage *)edgeEnhance { double dKernel[5][5] = { {0, 0.0, 0.0, 0.0, 0}, {0, -1.0, 1.0, 0.0, 0}, {0, 0.0, 0.0, 0.0, 0} }; NSMutableArray *kernel = [[[NSMutableArray alloc] initWithCapacity:5] autorelease]; for (int i = 0; i < 5; i++) { NSMutableArray *row = [[[NSMutableArray alloc] initWithCapacity:5] autorelease]; for (int j = 0; j < 5; j++) { [row addObject:[NSNumber numberWithDouble:dKernel[i][j]]]; } [kernel addObject:row]; } return [self applyConvolution:kernel]; } - (UIImage *)edgeDetect { double dKernel[5][5] = { {0, 0.0, 1.0, 0.0, 0}, {0, 1.0, -4.0, 1.0, 0}, {0, 0.0, 1.0, 0.0, 0} }; NSMutableArray *kernel = [[[NSMutableArray alloc] initWithCapacity:5] autorelease]; for (int i = 0; i < 5; i++) { NSMutableArray *row = [[[NSMutableArray alloc] initWithCapacity:5] autorelease]; for (int j = 0; j < 5; j++) { [row addObject:[NSNumber numberWithDouble:dKernel[i][j]]]; } [kernel addObject:row]; } return [self applyConvolution:kernel]; } - (UIImage *)emboss { double dKernel[5][5] = { {0, -2.0, -1.0, 0.0, 0}, {0, -1.0, 1.0, 1.0, 0}, {0, 0.0, 1.0, 2.0, 0} }; NSMutableArray *kernel = [[[NSMutableArray alloc] initWithCapacity:5] autorelease]; for (int i = 0; i < 5; i++) { NSMutableArray *row = [[[NSMutableArray alloc] initWithCapacity:5] autorelease]; for (int j = 0; j < 5; j++) { [row addObject:[NSNumber numberWithDouble:dKernel[i][j]]]; } [kernel addObject:row]; } return [self applyConvolution:kernel]; }
在此基礎上,我Google了下Photoshop中對照片進行黑白處理的簡單步驟:
- 去色
- 調整對比度
- 高斯模煳
- 浮雕效果
- 邊緣檢測
- 調整對比度
- 調整亮度
- 反相
我按步驟實現了相應代碼:
return [[[[[[[[originImage desaturate] changeContrastByFactor:1.5] gaussianBlur:1.3] emboss] edgeDetect] changeContrastByFactor:1.5] changeBrightnessByFactor:1.5] invert];
可惜效果有點粗糙,照片仍舊以上一篇文章中的Andy為例:
最後更新:2017-04-02 16:48:10