OpenCV图像处理——iOS端人脸检测

Liana ·
更新时间:2024-11-10
· 705 次阅读

前言

1.OpenCV有专门的iOS平台的包,可以真接下载导入工程,也可以用cmake把OpenCV源码编成.a文件,以静态库的形式导入工程。
2.我这里用的Xcode11,OpenCV用的是最4.20这个版本。
3.这里用到的人脸检测是OpenCV官方给的级联分类器,可以在OpenCV源码的Data目录中找到。

iOS人脸检测

1.新建一个iOS工程,把用于与C++混编的文件后缀.m改成.mm,添加一个用于做图像处理的文件,也改成.mm文件。如下:
在这里插入图片描述
2.把OpenCV和人脸检测的级联分类器导入工程。
在这里插入图片描述
3.在main.storyboard里面添加一个UIImageView,两个Button,然后关联到事件,如下:
在这里插入图片描述
4.处理文件里Commom.mm里面的代码:

void UIImageToMat(UIImage *ui_image, cv::Mat &cv_dst) { assert(ui_image.size.width > 0 && ui_image.size.height > 0); assert(ui_image.CGImage != nil || ui_image.CIImage != nil); //开缓冲区 NSInteger width = ui_image.size.width; NSInteger height = ui_image.size.height; cv::Mat cv_mat8uc4 = cv::Mat((int)height, (int)width, CV_8UC4); CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); if (ui_image.CGImage) { CGContextRef contextRef = CGBitmapContextCreate(cv_mat8uc4.data, cv_mat8uc4.cols, cv_mat8uc4.rows, 8, cv_mat8uc4.step, colorSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrderDefault); CGContextDrawImage(contextRef, CGRectMake(0, 0, width, height), ui_image.CGImage); CGContextRelease(contextRef); } else { static CIContext* context = nil; if (!context) { context = [CIContext contextWithOptions:@{ kCIContextUseSoftwareRenderer: @NO }]; } CGRect bounds = CGRectMake(0, 0, width, height); [context render:ui_image.CIImage toBitmap:cv_mat8uc4.data rowBytes:cv_mat8uc4.step bounds:bounds format:kCIFormatRGBA8 colorSpace:colorSpace]; } CGColorSpaceRelease(colorSpace); cv::Mat cv_mat8uc3 = cv::Mat((int)width, (int)height, CV_8UC3); cv::cvtColor(cv_mat8uc4, cv_mat8uc3, cv::COLOR_RGBA2BGR); cv_dst = cv_mat8uc3; } UIImage *MatToUIImage(cv::Mat &cv_src) { assert(cv_src.elemSize() == 1 || cv_src.elemSize() == 3); cv::Mat cv_rgb; if (cv_src.elemSize() == 1) { cv::cvtColor(cv_src, cv_rgb, cv::COLOR_GRAY2RGB); } else if (cv_src.elemSize() == 3) { cv::cvtColor(cv_src, cv_rgb, cv::COLOR_BGR2RGB); } NSData *data = [NSData dataWithBytes:cv_rgb.data length:(cv_rgb.elemSize() * cv_rgb.total())]; CGColorSpaceRef colorSpace; if (cv_rgb.elemSize() == 1) { colorSpace = CGColorSpaceCreateDeviceGray(); } else { colorSpace = CGColorSpaceCreateDeviceRGB(); } CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data); CGImageRef imageRef = CGImageCreate(cv_rgb.cols, cv_rgb.rows, 8, 8 * cv_rgb.elemSize(), cv_rgb.step.p[0], colorSpace, kCGImageAlphaNone|kCGBitmapByteOrderDefault, provider, NULL, false, kCGRenderingIntentDefault); UIImage *ui_image = [UIImage imageWithCGImage:imageRef]; CGImageRelease(imageRef); CGDataProviderRelease(provider); CGColorSpaceRelease(colorSpace); return ui_image; } void faceDetection(cv::Mat &cv_src, cv::Mat &cv_dst,std::string &face_class) { cv::CascadeClassifier face_classifier; face_classifier.load(face_class); if (cv_src.empty()) { return; } cv_dst = cv_src.clone(); cv::Mat cv_gray; //灰度化 cv::cvtColor(cv_src, cv_gray, cv::COLOR_BGR2GRAY); //直方图均衡化,用于提高图像的质量 equalizeHist(cv_gray, cv_gray); //存放检测到人脸的矩形 std::vector faces; //开始检测 face_classifier.detectMultiScale(cv_gray, faces, 1.2, 3, 0, cv::Size(24, 24)); //画出检测到的矩形的位置 for (size_t t = 0; t < faces.size(); t++) { rectangle(cv_dst, faces[static_cast(t)], cv::Scalar(0, 0, 255), 2, 8, 0); } }

5.交互文件ViewController.mm里面的代码:

#import "Common.h" #import "ViewController.h" #import #import @interface ViewController () @property (strong, nonatomic) UIImagePickerController *ui_album_selected;/* 相册选择器 */ @property (strong, nonatomic) AVPlayerViewController *ui_player;/* 视频播放器 */ @property (weak, nonatomic) IBOutlet UIImageView *ui_show_view;/* 显示图片 */ @property (nonatomic, weak) UIImage *ui_selected_image; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //设置显示图片可交互 self.ui_show_view.userInteractionEnabled = YES; //创建AVPlayerViewController控制器 AVPlayerViewController *playerVC = [[AVPlayerViewController alloc] init]; playerVC.view.frame = self.ui_show_view.bounds; [self.ui_show_view addSubview:playerVC.view]; self.ui_player = playerVC; self.ui_player.view.hidden = YES; } #pragma mark - UI点击 /* 点击打开本地相册 */ - (IBAction)pickImage:(id)sender { //如果正在播放视频,停止播放 if (self.ui_player.player) { [self.ui_player.player pause]; } //创建图片选择控制器 UIImagePickerController *ipc = [[UIImagePickerController alloc] init]; //判断设备是否有图册 if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) { //设置拾取源类型 ipc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary; //设置媒体类型,这里设置图册支持的所有媒体类型,图片和视频 ipc.mediaTypes = [UIImagePickerController availableMediaTypesForSourceType:ipc.sourceType]; } ipc.delegate = self;//设置代理 ipc.allowsEditing = YES;//设置可编辑 self.ui_album_selected = ipc; //弹出图片选择控制器 [self presentViewController:ipc animated:YES completion:nil]; } #pragma mark - UIImagePickerControllerDelegate代理方法 /* 选择了一个图片或者视频后调用 */ - (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info { //获取选择文件的媒体类型 NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType]; NSURL *videoURL = nil; if ([mediaType isEqualToString:@"public.image"]) {//选择了图片 //获取选择的图片 self.ui_selected_image = [info objectForKey:UIImagePickerControllerOriginalImage]; //self.ui_id = self.ui_selected_image; //显示图片 self.ui_show_view.image = self.ui_selected_image; self.ui_show_view.contentMode = UIViewContentModeScaleAspectFit; NSLog(@"found an image %@",self.ui_selected_image); //删除视频 self.ui_player.player = nil; self.ui_player.view.hidden = YES; } else if ([mediaType isEqualToString:@"public.movie"]) {//选择了视频 //获取临时保存视频的URL videoURL = [info objectForKey:UIImagePickerControllerMediaURL]; NSLog(@"found a video %@",videoURL); //直接创建AVPlayer,它内部也是先创建AVPlayerItem,这个只是快捷方法 AVPlayer *player = [AVPlayer playerWithURL:videoURL]; self.ui_player.player = player; self.ui_player.view.hidden = NO; } [self dismissViewControllerAnimated:YES completion:^{ if (videoURL) { //调用控制器的属性player的开始播放方法 [self.ui_player.player play]; } }]; } /* 取消选择后调用 */ - (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { [self dismissViewControllerAnimated:YES completion:^ { //取消选择后继续播放视频 if (self.ui_player.player) { [self.ui_player.player play]; } }]; NSLog(@"取消选择"); } - (IBAction)faceDetection:(id)sender { NSString* const model_file_name = @"haarcascade_frontalface_default"; NSString* const model_file_type = @"xml"; NSString* model = [[NSBundle mainBundle] pathForResource:model_file_name ofType:model_file_type]; std::string face_class = [model UTF8String]; cv::Mat cv_src; UIImageToMat(self.ui_selected_image, cv_src); cv::Mat cv_dst; faceDetection(cv_src, cv_dst, face_class); UIImage *face_image = MatToUIImage(cv_dst); self.ui_show_view.image = face_image; } @end

6.连接到真机运行如下:
在这里插入图片描述

注:有兴趣于OpenCV学习的可以加。

在这里插入图片描述


作者:知来者逆



opencv IOS 人脸检测

需要 登录 后方可回复, 如果你还没有账号请 注册新账号