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

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

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

[cpp] view plaincopy

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

方法的参数kernel是卷积运算中的卷积核,下面是几种滤镜的卷积核:

[cpp] view plaincopy

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

在此基础上,我Google了下Photoshop中对照片进行黑白处理的简单步骤:

  1. 去色
  2. 调整对比度
  3. 高斯模糊
  4. 浮雕效果
  5. 边缘检测
  6. 调整对比度
  7. 调整亮度
  8. 反相

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

[cpp] view plaincopy

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

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

时间: 2024-10-26 07:11:30

iOS中的图像处理(二)——卷积运算的相关文章

iOS中的图像处理(三)——混合运算

有时候,单独对一张图像进行处理是很难或者根本达不到我们想要的效果的.一个好的滤镜效果的诞生,往往要经过很多复杂步骤.细致微调.图片应用效果观察以及很多图层叠加. 我在JSWidget上发现了一些常用混合算法,对应着一些常用混合模式,通过这些blend modes,我们可以指定两张图像如何混合. 不过在此之前,我们需要纯颜色图像和渐变图像来做辅助: [cpp] view plaincopy + (UIImage *)imageWithColor:(UIColor *)color size:(CGS

iOS中如何生成二维码

首先导入框架 然后通过滤镜CIFiter生成二维码 #import <CoreImage/CoreImage.h> /** *  生成二维码 */ - (void)creat { //1.创建过滤对象 CIFilter *filter = [CIFilter filterWithName:@"CIQRCodeGenerator"]; //2.设置相关属性 [filter setDefaults]; //3.设置输入数据 NSString *inputData = @&quo

iOS中的图像处理(一)——基础滤镜

最近在稍微做一些整理,翻起这部分的代码,发现是两个多月前的了. 这里讨论的是基于RGBA模型下的图像处理,即将变换作用在每个像素上. 代码是以UIImage的category形式存在的: [cpp] view plaincopy typedef struct _singleRGBA { unsigned char red; unsigned char green; unsigned char blue; unsigned char alpha; } RGBA; @interface UIImag

图像处理之基础---二维卷积运算原理剖析

卷积运算(Convolution)是通过两个函数f 和g 生成第三个函数的一种数学算子,表示函数f 与经过翻转和平移与g 的重叠部分的累积.如果将参加卷积的一个函数看作区间的指示函数,卷积还可以被看作是“滑动平均”的推广.假设: f(x),g(x)是R1上的两个可积函数,并且积分是存在的.这样,随着 x 的不同取值,这个积分就定义了一个新函数h(x),称为函数f 与g 的卷积,记为h(x)=(f*g)(x). 两个向量卷积,说白了就是多项式乘法.下面用个矩阵例子说明其工作原理: a和d的卷积就是

Caffe 中卷积运算的原理与实现

caffe中卷积运算设计的很巧妙,今天就来讨论一下caffe中卷积运算的原理,最后会给出一个自己的实现版本,便于初学者理解. Caffe中卷积运算的原理 俗话说,一图胜千言,首先先给出原理示意图,为了方便,这里以二维核为例 滑动窗口在图像中每滑动一个地方,将图像中该滑动窗口图像展开为一列,所有列组成图中的滑动窗口矩阵,这里假设pad=1,stride=1,K=3,则滑动窗口矩阵每行大小为W*H,一共K*K行. 每个核展开为一行,N个核形成的核矩阵大小为N*K*K. 最后将核矩阵和滑动窗口矩阵相乘

图像处理---基础(模板、卷积运算)

转自:图像处理:基础(模板.卷积运算) 1.使用模板处理图像相关概念: 模板:矩阵方块,其数学含义是一种卷积运算.      卷积运算:可看作是加权求和的过程,使用到的图像区域中的每个像素分别于卷积核(权矩阵)的每个元素对应相                乘,所有乘积之和作为区域中心像素的新值.      卷积核:卷积时使用到的权用一个矩阵表示,该矩阵与使用的图像区域大小相同,其行.列都是奇数,              是一个权矩阵.      卷积示例:              3 *

IOS中的多线程【二】— NSOperation和NSOperationQueue

NSOperationQueue是一套基于Objective-c语言的API. GCD与NSOperationQueue的优缺点: NSOperationQueue:比较安全 GCD:没有NSOperationQueue安全,但使用起来简单,快速,还提供了一些操控底层的方法.实际开发中还是以GCD为主. NSOperationQueue实现多线程流程 1.定义一个任务队列. 2.定义一个任务. 3.把任务添加到队列中.一旦任务被添加到队列中,任务会马上被调度执行. 任务队列(NSOperatio

二维卷积运算工作原理剖析(转载)

卷积运算(Convolution)是通过两个函数f 和g 生成第三个函数的一种数学算子,表示函数f 与经过翻转和平移与g 的重叠部分的累积.如果将参加卷积的一个函数看作区间的指示函数,卷积还可以被看作是"滑动平均"的推广.假设: f(x),g(x)是R1上的两个可积函数,并且积分是存在的.这样,随着 x 的不同取值,这个积分就定义了一个新函数h(x),称为函数f 与g 的卷积,记为h(x)=(f*g)(x). 两个向量卷积,说白了就是多项式乘法.下面用个矩阵例子说明其工作原理: a和d

二维矩阵卷积运算实现

http://z.download.csdn.net/detail/wangfei0117/4408649 http://download.csdn.net/detail/wanwenliang2008/1767686 二维矩阵卷积运算实现,布布扣,bubuko.com