• 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为例:



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

  • 相关阅读:
    jmeter实现上传文件
    jmeter之调度器设置
    存储过程的几种传参方式
    Charles篡改数据
    软件测试职业发展方向
    最近发现一个有意思的lua游戏引擎,名字叫love2d
    2016,新的一年来到。
    Corona手游教程之widget:Slider篇
    Corona手游教程之widget:PickerWheel篇
    Corona手游教程之widget:ProgressView篇
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4946672.html
Copyright © 2020-2023  润新知