iOS中的图像处理(二)——卷积运算

关于图像处理中的卷积运算,这里有两份简明扼要的介绍:文一文二

其中,可能的一种卷积运算代码如下:

  1. - (UIImage*)applyConvolution:(NSArray*)kernel  
  2. {  
  3.     CGImageRef inImage = self.CGImage;  
  4.     CFDataRef m_DataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage));    
  5.     CFDataRef m_OutDataRef = CGDataProviderCopyData(CGImageGetDataProvider(inImage));    
  6.     UInt8 * m_PixelBuf = (UInt8 *) CFDataGetBytePtr(m_DataRef);    
  7.     UInt8 * m_OutPixelBuf = (UInt8 *) CFDataGetBytePtr(m_OutDataRef);    
  8.       
  9.     int h = CGImageGetHeight(inImage);  
  10.     int w = CGImageGetWidth(inImage);  
  11.       
  12.     int kh = [kernel count] / 2;  
  13.     int kw = [[kernel objectAtIndex:0] count] / 2;  
  14.     int i = 0, j = 0, n = 0, m = 0;  
  15.       
  16.     for (i = 0; i < h; i++) {  
  17.         for (j = 0; j < w; j++) {  
  18.             int outIndex = (i*w*4) + (j*4);  
  19.             double r = 0, g = 0, b = 0;  
  20.             for (n = -kh; n <= kh; n++) {  
  21.                 for (m = -kw; m <= kw; m++) {  
  22.                     if (i + n >= 0 && i + n < h) {  
  23.                         if (j + m >= 0 && j + m < w) {  
  24.                             double f = [[[kernel objectAtIndex:(n + kh)] objectAtIndex:(m + kw)] doubleValue];  
  25.                             if (f == 0) {continue;}  
  26.                             int inIndex = ((i+n)*w*4) + ((j+m)*4);  
  27.                             r += m_PixelBuf[inIndex] * f;  
  28.                             g += m_PixelBuf[inIndex + 1] * f;  
  29.                             b += m_PixelBuf[inIndex + 2] * f;  
  30.                         }  
  31.                     }  
  32.                 }  
  33.             }  
  34.             m_OutPixelBuf[outIndex]     = SAFECOLOR((int)r);  
  35.             m_OutPixelBuf[outIndex + 1] = SAFECOLOR((int)g);  
  36.             m_OutPixelBuf[outIndex + 2] = SAFECOLOR((int)b);  
  37.             m_OutPixelBuf[outIndex + 3] = 255;  
  38.         }  
  39.     }  
  40.       
  41.     CGContextRef ctx = CGBitmapContextCreate(m_OutPixelBuf,  
  42.                                              CGImageGetWidth(inImage),  
  43.                                              CGImageGetHeight(inImage),  
  44.                                              CGImageGetBitsPerComponent(inImage),  
  45.                                              CGImageGetBytesPerRow(inImage),  
  46.                                              CGImageGetColorSpace(inImage),  
  47.                                              CGImageGetBitmapInfo(inImage)  
  48.                                              );  
  49.       
  50.     CGImageRef imageRef = CGBitmapContextCreateImage(ctx);  
  51.     CGContextRelease(ctx);  
  52.     UIImage *finalImage = [UIImage imageWithCGImage:imageRef];  
  53.     CGImageRelease(imageRef);  
  54.     CFRelease(m_DataRef);  
  55.     CFRelease(m_OutDataRef);  
  56.       
  57.     return finalImage;  
  58. }  

方法的参数kernel是卷积运算中的卷积核,下面是几种滤镜的卷积核:
  1. #pragma mark -   
  2. #pragma mark - Basic Convolutions  
  3.   
  4. /* Reference :  
  5.  * http://docs.gimp.org/en/plug-in-convmatrix.html  
  6.  */  
  7.   
  8. - (UIImage *)sharpen  
  9. {  
  10. //  double dKernel[5][5] = {  
  11. //      {0,  0.0, -1.0,  0.0, 0},  
  12. //      {0, -1.0,  5.0, -1.0, 0},  
  13. //      {0,  0.0, -1.0,  0.0, 0}  
  14. //    };  
  15.       
  16.     double dKernel[5][5] = {   
  17.         {0, 0.0, -0.2,  0.0, 0},  
  18.         {0, -0.2, 1.8, -0.2, 0},  
  19.         {0, 0.0, -0.2,  0.0, 0}  
  20.     };  
  21.       
  22.     NSMutableArray *kernel = [[[NSMutableArray alloc] initWithCapacity:5] autorelease];  
  23.     for (int i = 0; i < 5; i++) {  
  24.         NSMutableArray *row = [[[NSMutableArray alloc] initWithCapacity:5] autorelease];  
  25.         for (int j = 0; j < 5; j++) {  
  26.             [row addObject:[NSNumber numberWithDouble:dKernel[i][j]]];  
  27.         }  
  28.         [kernel addObject:row];  
  29.     }  
  30.     return [self applyConvolution:kernel];  
  31. }  
  32.   
  33. - (UIImage *)edgeEnhance  
  34. {  
  35.     double dKernel[5][5] = {  
  36.         {0,  0.0,  0.0,  0.0, 0},  
  37.         {0, -1.0,  1.0,  0.0, 0},  
  38.         {0,  0.0,  0.0,  0.0, 0}  
  39.     };  
  40.       
  41.     NSMutableArray *kernel = [[[NSMutableArray alloc] initWithCapacity:5] autorelease];  
  42.     for (int i = 0; i < 5; i++) {  
  43.         NSMutableArray *row = [[[NSMutableArray alloc] initWithCapacity:5] autorelease];  
  44.         for (int j = 0; j < 5; j++) {  
  45.             [row addObject:[NSNumber numberWithDouble:dKernel[i][j]]];  
  46.         }  
  47.         [kernel addObject:row];  
  48.     }  
  49.       
  50.     return [self applyConvolution:kernel];  
  51. }  
  52.   
  53. - (UIImage *)edgeDetect  
  54. {  
  55.     double dKernel[5][5] = {  
  56.         {0,  0.0,  1.0,  0.0, 0},  
  57.         {0,  1.0, -4.0,  1.0, 0},  
  58.         {0,  0.0,  1.0,  0.0, 0}  
  59.     };  
  60.       
  61.     NSMutableArray *kernel = [[[NSMutableArray alloc] initWithCapacity:5] autorelease];  
  62.     for (int i = 0; i < 5; i++) {  
  63.         NSMutableArray *row = [[[NSMutableArray alloc] initWithCapacity:5] autorelease];  
  64.         for (int j = 0; j < 5; j++) {  
  65.             [row addObject:[NSNumber numberWithDouble:dKernel[i][j]]];  
  66.         }  
  67.         [kernel addObject:row];  
  68.     }  
  69.       
  70.     return [self applyConvolution:kernel];  
  71. }  
  72.   
  73. - (UIImage *)emboss  
  74. {  
  75.     double dKernel[5][5] = {  
  76.         {0, -2.0, -1.0,  0.0, 0},  
  77.         {0, -1.0,  1.0,  1.0, 0},  
  78.         {0,  0.0,  1.0,  2.0, 0}  
  79.     };  
  80.       
  81.     NSMutableArray *kernel = [[[NSMutableArray alloc] initWithCapacity:5] autorelease];  
  82.     for (int i = 0; i < 5; i++) {  
  83.         NSMutableArray *row = [[[NSMutableArray alloc] initWithCapacity:5] autorelease];  
  84.         for (int j = 0; j < 5; j++) {  
  85.             [row addObject:[NSNumber numberWithDouble:dKernel[i][j]]];  
  86.         }  
  87.         [kernel addObject:row];  
  88.     }  
  89.       
  90.     return [self applyConvolution:kernel];  
  91. }  

在此基础上,我Google了下Photoshop中对照片进行黑白处理的简单步骤:
  1. 去色
  2. 调整对比度
  3. 高斯模糊
  4. 浮雕效果
  5. 边缘检测
  6. 调整对比度
  7. 调整亮度
  8. 反相

我按步骤实现了相应代码:

  1. return [[[[[[[[originImage desaturate]  
  2.                           changeContrastByFactor:1.5]  
  3.                          gaussianBlur:1.3] emboss]  
  4.                        edgeDetect]  
  5.                       changeContrastByFactor:1.5]  
  6.                      changeBrightnessByFactor:1.5]  
  7.                     invert];  

可惜效果有点粗糙,照片仍旧以上一篇文章中的Andy为例:



版权声明:本文为博主原创文章,未经博主允许不得转载。

原文地址:https://www.cnblogs.com/Free-Thinker/p/4946672.html