在 Xcode 中将 OpenCV 集成到你的 Swift iOS 项目中并使用 UIImages

人工智能等各类编程培训资料整理,所有资源无秘无压缩-购买会员

假设在你的 iOS 应用程序中,你想对图像执行抓取或使用特定插值调整图像大小,作为机器学习模型的预处理步骤。你无法在 Xcode 上使用 Apple 的原生框架(例如 Core Image)轻易地做到这一点。如果你想坚持使用 Apple 的工具,你可能不得不使用Metal,并且仍然需要从头开始编写代码。

或者,你可以将 OpenCV 与你的 Xcode swift 项目集成,并使用 100 多种现成的优化图像处理算法来完成你的工作。尽管集成部分并不完全直接,但它执行起来非常快,因为它使用 C++。(这只会使你的应用程序在 iOS 设备上的大小增加大约 2MB。)

1. 获取OpenCV iOS框架

首先,从其发布(https://opencv.org/releases/)页面下载最新的 OpenCV 版本 3 或 4 iOS 包。解压缩 zip 文件并获取opencv2.framework文件。

(本指南将基于 Xcode 12.3 和 OpenCV3。OpenCV4 的 API 会略有不同。)

2. 将 OpenCV 框架添加到你的项目中

将 opencv2.framework 文件拖放到 Xcode 项目左侧的项目导航器窗格中。然后,Xcode 将提示一个窗口,其中包含用于添加框架的选项。

对于Destination勾选Copy items if needed

对于Added folders选择Create groups选项

对于Add to targets勾选你的目标应用程序。

在左侧导航器窗格中单击你的项目,然后转到Build Phases -> Link Binary With Libraries。你应该能够在那里看到opencv2.framework。(注意,将框架复制到项目中可能需要几秒钟)

3.(可选)添加与 OpenCV 配合使用的其他框架

根据你的项目使用的内容,你可能还必须链接以下一些框架,以便 OpenCV 正常工作。

AssetsLibrary.frameworkCoreGraphics.frameworkCoreMedia.frameworkCoreFoundation.frameworkAccelerate.framework

在Build Phases -> Link Binary With Libraries下,点击+号,搜索上面的frameworks并添加。

4. 设置框架搜索路径

在左侧导航器窗格中单击你的项目,然后转到Build Settings -> Framework Search Paths。确保在那里说明了opencv2.framework的正确目录路径。对于项目的根目录,你可以使用**$(PROJECT_DIR)/。**

5. 创建包装器类文件

转到File -> New -> File。创建一个名为OpenCVWrapper的Cocoa Touch 类,并为Language选择Objective-C。将其保存在你的项目目录中,然后单击“ Create Bridging Header ”。

你将在左侧项目导航器窗格中看到 3 个新文件。

OpenCVWrapper.hOpenCVWrapper.m{Project Name}-Bridging-Header.h

现在,通过将“OpenCVWrapper.m”重命名为“OpenCVWrapper.mm”,将“OpenCVWrapper.m”的文件扩展名从“ .m ”更改为“ .mm ”。然后,你可以看到 Xcode 将文件识别为Objective-C++文件,位于右侧窗格的File Inspector -> Identity and Type。(你可以按Option+Command+1打开文件检查器)

7. 编辑桥接头文件

打开**{Project Name}-Bridging-Header.h**并添加以下行。

#import”OpenCVWrapper.h”

8. 添加前缀头文件

转到File -> New -> File并筛选“ PCH ”。创建并保存在项目目录中。

将以下行添加到PrefixHeader.pch文件的最后一行#endif之前。

#ifdef__cplusplus

#include

#endif

现在,该文件应包含以下行。

#ifndefPrefixHeader_pch

#definePrefixHeader_pch

#ifdef__cplusplus

#include

#endif

#endif

单击左侧导航窗格中的项目,然后转到Build Settings -> Prefix Header。在那里为PrefixHeader.pch添加正确的文件路径。如果该文件位于项目的“ .xcodeproj ”文件所在的目录中,则可以使用$(SRCROOT)/PrefixHeader.pch.

9. 编辑 OpenCVWrapper.h

我们将创建 3 个类方法。

getOpenCVVersion — 以字符串形式提供 OpenCV 版本。(我们可以用它来快速检查 OpenCV 是否集成成功。)grayscaleImg — 采用 UIImage 并将其灰度输出为 UIImage。(这将给出如何使用 UIImages 的想法。)resizeImg — 获取一个 UIImage 并输出其调整大小的UIImage。(这会让你了解如何使用带有 alpha 通道的 UIImages 。)

因此,OpenCVWrapper.h应如下所示。

#import

#import

NS_ASSUME_NONNULL_BEGIN

@interfaceOpenCVWrapper:NSObject

+(NSString*)getOpenCVVersion;

+(UIImage*)grayscaleImg:(UIImage*)image;

+(UIImage*)resizeImg:(UIImage*)image:(int)width:(int)height:(int)interpolation;

@end

NS_ASSUME_NONNULL_END

10. 编辑 OpenCVWrapper.mm

OpenCVWrapper.mm应如下所示。

#import

#import

#import”OpenCVWrapper.h”

*addamethodconvertToMattoUIImageclass

@interfaceUIImage(OpenCVWrapper)

-(void)convertToMat:(cv::Mat*)pMat:(bool)alphaExists;

@end

@implementationUIImage(OpenCVWrapper)

-(void)convertToMat:(cv::Mat*)pMat:(bool)alphaExists{

if(self.imageOrientation==UIImageOrientationRight){

*Whentakingpictureinportraitorientation,

*convertUIImagetoOpenCVMatrixinlandscaperight-side-uporientation,

*andthenrotateOpenCVMatrixtoportraitorientation

UIImageToMat([UIImageimageWithCGImage:self.CGImagescale:1.0orientation:UIImageOrientationUp],*pMat,alphaExists);

cv::rotate(*pMat,*pMat,cv::ROTATE_90_CLOCKWISE);

}elseif(self.imageOrientation==UIImageOrientationLeft){

*Whentakingpictureinportraitupside-downorientation,

*convertUIImagetoOpenCVMatrixinlandscaperight-side-uporientation,

*andthenrotateOpenCVMatrixtoportraitupside-downorientation

UIImageToMat([UIImageimageWithCGImage:self.CGImagescale:1.0orientation:UIImageOrientationUp],*pMat,alphaExists);

cv::rotate(*pMat,*pMat,cv::ROTATE_90_COUNTERCLOCKWISE);

}else{

*Whentakingpictureinlandscapeorientation,

*convertUIImagetoOpenCVMatrixdirectly,

*andthenONLYrotateOpenCVMatrixforlandscapeleft-side-uporientation

UIImageToMat(self,*pMat,alphaExists);

if(self.imageOrientation==UIImageOrientationDown){

cv::rotate(*pMat,*pMat,cv::ROTATE_180);

}

}

}

@end

@implementationOpenCVWrapper

+(NSString*)getOpenCVVersion{

return[NSStringstringWithFormat:@”OpenCVVersion%s”,CV_VERSION];

}

+(UIImage*)grayscaleImg:(UIImage*)image{

cv::Matmat;

[imageconvertToMat:&mat:false];

cv::Matgray;

NSLog(@”channels=%d”,mat.channels());

if(mat.channels()>1){

cv::cvtColor(mat,gray,CV_RGB2GRAY);

}else{

mat.copyTo(gray);

}

UIImage*grayImg=MatToUIImage(gray);

returngrayImg;

}

+(UIImage*)resizeImg:(UIImage*)image:(int)width:(int)height:(int)interpolation{

cv::Matmat;

[imageconvertToMat:&mat:false];

if(mat.channels()==4){

[imageconvertToMat:&mat:true];

}

NSLog(@”sourceshape=(%d,%d)”,mat.cols,mat.rows);

cv::Matresized;

//cv::INTER_NEAREST=0,

//cv::INTER_LINEAR=1,

//cv::INTER_CUBIC=2,

//cv::INTER_AREA=3,

//cv::INTER_LANCZOS4=4,

//cv::INTER_LINEAR_EXACT=5,

//cv::INTER_NEAREST_EXACT=6,

//cv::INTER_MAX=7,

//cv::WARP_FILL_OUTLIERS=8,

//cv::WARP_INVERSE_MAP=16

cv::Sizesize={width,height};

cv::resize(mat,resized,size,0,0,interpolation);

NSLog(@”dstshape=(%d,%d)”,resized.cols,resized.rows);

UIImage*resizedImg=MatToUIImage(resized);

returnresizedImg;

}

@end

“ convertToMat”方法是(https://github.com/tobyliu-sw/OpenCVSample/blob/28ae9c733c4a7545eb126c9b90dca60e22c13e40/OpenCVSample/OpenCVSample.mm#L27)的修改版本,用于将UIImage转换为cv::Mat。

或者你可以按照这个方法(https://docs.opencv.org/3.4.16/d3/def/tutorial_image_manipulation.html),虽然我没有亲自尝试过。

注意:

NSLog可用于将字符串打印到控制台。在 OpenCV4 中,方法grayscaleImg中的CV_RGB2GRAY应该是cv::COLOR_RGB2GRAY。在灰度图像中,没有 alpha 通道。因此,在grayscaleImg方法中调用convertToMat时,它被忽略,alphaExists 被设置为 false。调整大小时,alpha 通道也必须调整大小。因此,如果图像有 4 个通道,则在resizeImg方法中调用convertToMat 时,将考虑 alpha 通道并将 alphaExists 设置为 true。检查resizeImg方法下的注释以找到每个插值的输入整数代码。(例如 — 最近邻 = 0;双线性 = 1;双三次 = 2 等等。)11. 检查集成

你可以调用“getOpenCVVersion”,如下所示,在“ViewController.swift”中的super.viewDidLoad()行之后的viewDidLoad()中,如果集成成功,它会将OpenCV版本打印到控制台。

print(“(OpenCVWrapper.getOpenCVVersion())”)

12. 使用 UIImages

假设你有一个名为“ sample_img.png ”的 1280×720 RGBA 图像作为应用程序中的资产,你将能够获得它的灰度UIImage使用swift如下(例如,在第 11 节中的ViewController.swift)。

letrgbaIn=UIImage(named:”sample_img”)!

letgrayOut=OpenCVWrapper.grayscaleImg(rgbaIn)

同样,你可以使用双线性插值获得其调整为 640×360 大小的 RGBA UIImage ,如下所示。

letrgbaIn=UIImage(named:”sample_img”)!

letrgba256=OpenCVWrapper.resizeImg(rgbaIn,640,360,1)

(如果出现任何错误,请使用顶部的“Product”菜单再次尝试清洁和构建。)

现在你已经了解了如何使用 OpenCV 处理 UIImage。你可以参考 OpenCV C++ 文档来浏览该库。

OpenCV C++ 文档:https://docs.opencv.org/3.4.16/d3/d63/classcv_1_1Mat.html

免责声明: 1、本站信息来自网络,版权争议与本站无关 2、本站所有主题由该帖子作者发表,该帖子作者与本站享有帖子相关版权 3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和本站的同意 4、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责 5、用户所发布的一切软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。 6、您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。 7、请支持正版软件、得到更好的正版服务。 8、如有侵权请立即告知本站,本站将及时予与删除 9、本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章和视频仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。
600学习网 » 在 Xcode 中将 OpenCV 集成到你的 Swift iOS 项目中并使用 UIImages