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 :
 * http://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中对照片进行黑白处理的简单步骤:

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

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

return [[[[[[[[originImage desaturate]
                          changeContrastByFactor:1.5]
                         gaussianBlur:1.3] emboss]
                       edgeDetect]
                      changeContrastByFactor:1.5]
                     changeBrightnessByFactor:1.5]
                    invert];

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

时间: 2024-12-09 08:00:32

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

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

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

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

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

iOS中动态更新补丁策略JSPatch运用基础二

iOS中动态更新补丁策略JSPatch运用基础二 一.引言     上篇博客中介绍了iOS开发中JSPatch引擎进行动态热修复的一些基础功能,其中包括向Objective-C类中添加类方法与成员方法.添加临时成员变量,使用JavaScript调用原生的Objective-C属性和方法等.本篇博客将基于上一篇继续介绍Objective-C中的一些特殊数据类型在JavaScript文件中的使用方法,博客中大部分内容扩展自JSPatch开源git的wiki:https://github.com/ba

iOS中CoreData数据管理系列二——CoreData框架中三个重要的类

iOS中CoreData数据管理系列二--CoreData框架中三个重要的类 一.引言     在上一篇博客中,介绍了iOS中使用CoreData框架设计数据模型的相关步骤.CoreData框架中通过相关的类将数据--数据模型--开发者无缝的衔接起来.NSManagedObjectModel对应数据模型,即上篇博客中我们创建的.xcdatamodeld文件:NSPersistentStoreCoordinator相当于数据库与数据模型之间的桥接器,通过NSPersistentStoreCoord

iOS中线程Call Stack的捕获和解析(二)

上接iOS中线程Call Stack的捕获和解析(一). 1. 部分参考资料 做这一块时也是查阅了很多链接和书籍,包括但不限于: <OS X ABI Mach-O File Format Reference> <Mach-O Programming Topics> <程序员的自我修养>--这本几年前读过的,又一次从书架上拿下来温习,主要是用来对比确认: <The Mac Hacker's Handbook> <Mac OS X and iOS Inte

支付宝扫描二维码-ios中怎样调用支付宝扫一扫功能?

问题描述 ios中怎样调用支付宝扫一扫功能? 在ios开发中,怎样调用支付宝钱包的扫一扫功能,或者,支付宝钱包里的扫一扫可以扫描手机图片怎样把图片传给支付宝使支付宝能够扫描?

优化iOS程序性能的二十五个方法

1. 用ARC管理内存 ARC(Automatic ReferenceCounting, 自动引用计数)和iOS5一起发布,它避免了最常见的也就是经常是由于我们忘记释放内存所造成的内存泄露.它自动为你管理retain和release的过程,所以你就不必去手动干预了.忘掉代码段结尾的release简直像记得吃饭一样简单.而ARC会自动在底层为你做这些工作.除了帮你避免内存泄露,ARC还可以帮你提高性能,它能保证释放掉不再需要的对象的内存. 现在所有的iOS程序都用ARC了,这条可以忽略. 2. 在

iOS面试题总结 二

1. Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么? 答:Object-c的类不可以多重继承;可以实现多个接口,通过实现多个接口可以完成C++的多重继承;Category是类别,一般情况用分类好,用Category去重写类的方法,仅对本Category有效,不会影响到其他类与原有类的关系. 2. #import 跟#include 又什么区别,@class呢, #import<> 跟 #import"&qu

ios-需要在IOS中设置延迟功能

问题描述 需要在IOS中设置延迟功能 需要一个延时器,进行23秒的延迟然后执行函数.应该怎么实现?用不用NSTimer? 解决方案 performSelector: withObject: afterDelay: 解决方案二: 简单点的话,使用performSelector: withObject: afterDelay: 方法 [self performSelector:@selector(delayMethod:) withObject:nil afterDelay:23];