IOS 用openCv实现简单的扣人像的

最近要实现人像扣图的功能,我在网上查到的扣图的方式主要有两种,一种是coreImage 色域,一种是openCv边缘检测

第一种适合纯色背景,扣图精准,第二种,适合复杂背景,但是默认的扣图不精确,如下图

1.处理前的照片

2.处理后的照片

coreImage 网上已经有很多实现了,也有很多文章,我就不多说了,我只把我实现的代码贴出来,代码粘过去就能用,另忘了,导入CubeMap.c

//coreImage 扣图 createCubeMap(值1,值2)值范围0~360 扣掉值1到值2范围内的颜色

CubeMap myCube = createCubeMap(self.slider1.value, self.slider2.value);

NSData *myData = [[NSData alloc]initWithBytesNoCopy:myCube.data length:myCube.length freeWhenDone:true];

CIFilter *colorCubeFilter = [CIFilter filterWithName:@"CIColorCube"];

[colorCubeFilter setValue:[NSNumber numberWithFloat:myCube.dimension] forKey:@"inputCubeDimension"];

[colorCubeFilter setValue:myData forKey:@"inputCubeData"];

[colorCubeFilter setValue:[CIImage imageWithCGImage:_preview.image.CGImage] forKey:kCIInputImageKey];

CIImage *outputImage = colorCubeFilter.outputImage;

CIFilter *sourceOverCompositingFilter = [CIFilter filterWithName:@"CISourceOverCompositing"];

[sourceOverCompositingFilter setValue:outputImage forKey:kCIInputImageKey];

[sourceOverCompositingFilter setValue:[CIImage imageWithCGImage:backgroundImage.CGImage] forKey:kCIInputBackgroundImageKey];

outputImage = sourceOverCompositingFilter.outputImage;

CGImage *cgImage = [[CIContext contextWithOptions: nil]createCGImage:outputImage fromRect:outputImage.extent];

下面我讲一下,ios结合openCv实现扣图的方法

下载opencv2

具体怎么IOS下弄opencv 请见我之前写的一贴博客:

http://blog.csdn.net/wuzehai02/article/details/8439778

IOS使用OPENCV实现物体跟踪

头文件导入下面几个

#import <opencv2/opencv.hpp>

#import "UIImage+OpenCV.h"

UIImage+OpenCV类

//

//  UIImage+OpenCV.h

#import <UIKit/UIKit.h>

#import <opencv2/opencv.hpp>

@interface UIImage (UIImage_OpenCV)

+(UIImage *)imageWithCVMat:(constcv::Mat&)cvMat;

-(id)initWithCVMat:(constcv::Mat&)cvMat;

@property(nonatomic,readonly)
cv::Mat CVMat;

@property(nonatomic,readonly)
cv::Mat CVGrayscaleMat;

@end

//

//  UIImage+OpenCV.mm

#import "UIImage+OpenCV.h"

staticvoid ProviderReleaseDataNOP(void *info,const
void *data,size_t size)

{

// Do not release memory

return;

}

@implementation UIImage (UIImage_OpenCV)

-(cv::Mat)CVMat

{

CGColorSpaceRef colorSpace =CGImageGetColorSpace(self.CGImage);

CGFloat cols =self.size.width;

CGFloat rows =self.size.height;

cv::Mat cvMat(rows, cols,CV_8UC4);
// 8 bits per component, 4 channels

CGContextRef contextRef =
CGBitmapContextCreate(cvMat.data,                // Pointer to backing data

cols,                     // Width of bitmap

rows,                    // Height of bitmap

8,                         // Bits per component

cvMat.step[0],             // Bytes per row

colorSpace,                // Colorspace

kCGImageAlphaNoneSkipLast |

kCGBitmapByteOrderDefault);
// Bitmap info flags

CGContextDrawImage(contextRef,
CGRectMake(0, 0, cols, rows),
self.CGImage);

CGContextRelease(contextRef);

return cvMat;

}

-(cv::Mat)CVGrayscaleMat

{

CGColorSpaceRef colorSpace =CGColorSpaceCreateDeviceGray();

CGFloat cols =self.size.width;

CGFloat rows =self.size.height;

cv::Mat cvMat =cv::Mat(rows,
cols,CV_8UC1);
// 8 bits per component, 1 channel

CGContextRef contextRef =
CGBitmapContextCreate(cvMat.data,                // Pointer to backing data

cols,                     // Width of bitmap

rows,                    // Height of bitmap

8,                         // Bits per component

cvMat.step[0],             // Bytes per row

colorSpace,                // Colorspace

kCGImageAlphaNone |

kCGBitmapByteOrderDefault);
// Bitmap info flags

CGContextDrawImage(contextRef,
CGRectMake(0, 0, cols, rows),
self.CGImage);

CGContextRelease(contextRef);

CGColorSpaceRelease(colorSpace);

return cvMat;

}

+ (UIImage *)imageWithCVMat:(constcv::Mat&)cvMat

{

return [[[UIImagealloc]
initWithCVMat:cvMat]autorelease];

}

- (id)initWithCVMat:(constcv::Mat&)cvMat

{

NSData *data = [NSDatadataWithBytes:cvMat.datalength:cvMat.elemSize()
* cvMat.total()];

CGColorSpaceRef colorSpace;

if (cvMat.elemSize() == 1)

{

colorSpace = CGColorSpaceCreateDeviceGray();

}

else

{

colorSpace = CGColorSpaceCreateDeviceRGB();

}

CGDataProviderRef provider =CGDataProviderCreateWithCFData((CFDataRef)data);

CGImageRef imageRef =
CGImageCreate(cvMat.cols,                                    // Width

cvMat.rows,                                    // Height

8,                                             // Bits per component

8 * cvMat.elemSize(),                          // Bits per pixel

cvMat.step[0],                                 // Bytes per row

colorSpace,                                    // Colorspace

kCGImageAlphaNone |
kCGBitmapByteOrderDefault, 
// Bitmap info flags

provider,                                      // CGDataProviderRef

NULL,                                          // Decode

false,                                         // Should interpolate

kCGRenderingIntentDefault);                    // Intent

self = [selfinitWithCGImage:imageRef];

CGImageRelease(imageRef);

CGDataProviderRelease(provider);

CGColorSpaceRelease(colorSpace);

return
self;

}

@end

好了,上面的都是准备工作,具体的代码其实很简单

cv::Mat grayFrame,_lastFrame, mask,bgModel,fgModel;

_lastFrame = [self.preview.imageCVMat];

cv::cvtColor(_lastFrame, grayFrame,cv::COLOR_RGBA2BGR);//转换成三通道bgr

cv::Rect rectangle(1,1,grayFrame.cols-2,grayFrame.rows -2);//检测的范围

//分割图像

cv::grabCut(grayFrame, mask, rectangle, bgModel, fgModel, 3,cv::GC_INIT_WITH_RECT);//openCv强大的扣图功能

int nrow = grayFrame.rows;

int ncol = grayFrame.cols * grayFrame.channels();

for(int j=0; j<nrow; j++){//扣图,不知道这样写对不对,我也是新手,请大家多多指教

for(int i=0; i<ncol; i++){

uchar val = mask.at<uchar>(j,i);

if(val==cv::GC_PR_BGD){

grayFrame.at<cv::Vec3b>(j,i)[0]= ‘\255‘;

grayFrame.at<cv::Vec3b>(j,i)[1]= ‘\255‘;

grayFrame.at<cv::Vec3b>(j,i)[2]= ‘\255‘;

}

}

}

cv::cvtColor(grayFrame, grayFrame,cv::COLOR_BGR2RGB); //转换成彩色图片

_preview.image = [[UIImagealloc]
initWithCVMat:grayFrame];//显示结果

上面的代码测试可用,其实这里最关键的代码是使用了opencv的grabCut
图像分割函数

grabCut函数的API说明如下:

void cv::grabCut( InputArray _img, InputOutputArray _mask, Rect rect,

InputOutputArray _bgdModel, InputOutputArray _fgdModel,

int iterCount, int mode )

/*

****参数说明:

img——待分割的源图像,必须是8位3通道(CV_8UC3)图像,在处理的过程中不会被修改;

mask——掩码图像,如果使用掩码进行初始化,那么mask保存初始化掩码信息;在执行分割的时候,也可以将用户交互所设定的前景与背景保存到mask中,然后再传入grabCut函数;在处理结束之后,mask中会保存结果。mask只能取以下四种值:

GCD_BGD(=0),背景;

GCD_FGD(=1),前景;

GCD_PR_BGD(=2),可能的背景;

GCD_PR_FGD(=3),可能的前景。

如果没有手工标记GCD_BGD或者GCD_FGD,那么结果只会有GCD_PR_BGD或GCD_PR_FGD;

rect——用于限定需要进行分割的图像范围,只有该矩形窗口内的图像部分才被处理;

bgdModel——背景模型,如果为null,函数内部会自动创建一个bgdModel;bgdModel必须是单通道浮点型(CV_32FC1)图像,且行数只能为1,列数只能为13x5;

fgdModel——前景模型,如果为null,函数内部会自动创建一个fgdModel;fgdModel必须是单通道浮点型(CV_32FC1)图像,且行数只能为1,列数只能为13x5;

iterCount——迭代次数,必须大于0;

mode——用于指示grabCut函数进行什么操作,可选的值有:

GC_INIT_WITH_RECT(=0),用矩形窗初始化GrabCut;

GC_INIT_WITH_MASK(=1),用掩码图像初始化GrabCut;

GC_EVAL(=2),执行分割。

*/

参考文章:http://blog.csdn.net/zouxy09/article/details/8534954

时间: 2024-11-02 21:19:32

IOS 用openCv实现简单的扣人像的的相关文章

iOS开发网络篇—简单介绍ASI框架的使用

iOS开发网络篇—简单介绍ASI框架的使用 说明:本文主要介绍网络编程中常用框架ASI的简单使用. 一.ASI简单介绍 ASI:全称是ASIHTTPRequest,外号“HTTP终结者”,功能十分强大. ASI的实现基于底层的CFNetwork框架,因此运行效率很高.可惜作者早已停止更新,有一些潜在的BUG无人去解决 ASI的github地址 https://github.com/pokeb/asi-http-request ASI的使用参考 http://www.cnblogs.com/dot

iOS开发UI篇—简单介绍静态单元格的使用

iOS开发UI篇-简单介绍静态单元格的使用 一.实现效果与说明 说明:观察上面的展示效果,可以发现整个界面是由一个tableview来展示的,上面的数据都是固定的,且几乎不会改变. 要完成上面的效果,有几种方法: (1)可以直接利用代码,返回三组,在判断每组有多少行,展示些什么数据,这样写"死"的代码建议绝不要使用. (2)稍微灵活一些的,可以把plist文件一懒加载的方式,加载到程序中,动态获取.但是观察界面结构,很容易看出这样需要进行模型嵌套,很麻烦. (3)storyboard提

文顶顶 iOS开发UI篇—简单的浏览器查看程序

文顶顶 iOS开发UI篇—简单的浏览器查看程序 iOS开发UI篇—简单的浏览器查看程序 一.程序实现要求 1.要求 2. 界面分析 (1) 需要读取或修改属性的控件需要设置属性 序号标签 图片 图片描述 左边按钮 右边按钮 (2) 需要监听响应事件的对象,需要添加监听方法 左边按钮 右边按钮 二.实现基本功能的程序 1 // 2 // YYViewController.m 3 // 03-图片浏览器初步 4 // 5 // Created by apple on 14-5-21. 6 // Co

iOS中动画的简单使用

//***简单动画 [UIView animateWithDuration:3 animations:^{ //      _animationView.center = CGPointMake(arc4random()%320, arc4random()%480);//改变中心点 //      _animationView.frame = CGRectMake(arc4random()%320, arc4random()%480,arc4random()%320, arc4random()%

Socket在iOS客户端上的简单实现 - 利用GCAsyncSocket框架

GCAsyncSocket 这是一个2003的开发出来的一个开源框架 首先把GCDAsyncSocket的.h和.m文件拖入到工程中 试图控制器遵守GCDAsyncSocketDelegate协议 实例:在页面上有一个简单的textView和textField 在textField中输入文字后,点击发送即可把文字发送到服务器 ,服务器端返回的文字数据会显示到textView上 //  服务器主机ip地址#define kHost @"172.16.3.101"//  服务器主机通信端口

iOS开发UI基础—简单的浏览器查看程序

iOS开发UI基础-简单的浏览器查看程序 一.程序实现要求 1.要求 2. 界面分析 (1) 需要读取或修改属性的控件需要设置属性 序号标签 图片 图片描述 左边按钮 右边按钮 (2) 需要监听响应事件的对象,需要添加监听方法 左边按钮 右边按钮 二.实现基本功能的程序 1 // 2 // YYViewController.m 3 // 03-图片浏览器初步 4 // 5 // Created by apple on 14-5-21. 6 // Copyright (c) 2014年 itcas

iOS开发Swift篇—简单介绍

iOS开发Swift篇—简单介绍 一.简介 Swift是苹果于2014年WWDC(苹果开发者大会)发布的全新编程语言 Swift在天朝译为“雨燕”,是它的LOGO 是一只燕子,跟Objective-C一样,可以用于开发iOS.Mac应用程序 苹果从2010年7月开始设计Swift语言,耗时4年打造 Swift的语法特点 从它的语法中能看到Objective-C.JavaScript.Python等语言的影子 语法简单.代码简洁.使用方便 可与Objective-C混合使用(相互调用) 为什么要设

iOS 中级数据持久化——简单的数据库(Sqlite3)

sqlite是嵌入式的和轻量级的sql数据库.sqlite是由c实现的.广泛用于包括浏览器(支持html5的大部分浏览器,ie除外).ios.android以及一些便携需求的小型web应用系统. 数据库无非就是增,删,改,查四种.除了查询以为,其他的三种方法比较类似 //使用数据库之前,打开数据库 - (void)openDB { if (db != nil) { return; } //数据库存储在沙河中的caches文件夹下 NSString * cachesPath = [NSSearch

IOS多线程_GCD的简单使用和详细说明

//你可以先看看这个例子的效果找点感觉,再看说明 @interface yxpGCDVController () { UIImageView *_imageView; } @end @implementation yxpGCDVController - (void)viewDidLoad { [super viewDidLoad]; self.title=@"GCD"; //初始化一_ImageView _imageView=[[UIImageView alloc] initWithF