NSFW模型的iOS CoreML项目[Swift]

一个使用CoreML和开放nsfw模型的小型iOS项目。

自从WWDC2017首次宣布以来,Apple的Core ML已经问世了一段时间。 这是一个令人兴奋的新框架,有了iOS 11,在macOS和iOS上运行ML模型变得更加容易。 Apple提供了许多已经采用Core ML模型格式的开源模型,可以在这里找到。

我的示例项目将使用Yahoo的开放式nsfw模型和python coremltools进行转换。

为了编写Core ML并在您的设备上运行它,您将需要:

  • Xcode 9 Beta
  • iOS 11测试版
  • 打开nsfw模型
  • Python coremltools 0.4.0 我不会详细介绍安装Python的细节。 您将需要Python 2.7作为coremltools。
  • 入门项目 我已经编写了一些UI代码,因此您可以专注于对ML部分进行编码🙂

1.将.caffemodel转换为.mlmodel

由于Yahoo的开放式nsfw模型为caffe模型格式,因此我们需要首先将其转换为CoreML模型格式。 我用python coremltools编写了一个简短的脚本来完成该任务。 该软件包的文档可以在这里找到。

在您刚刚从Yahoo的GitHub页面下载的“ open_nsfw_master ”项目中,进入其子文件夹“ nsfw_model ”并创建convert.py

  import coremltools#将caffe模型转换为Core ML模型caffe_model =('resnet_50_1by2_nsfw.caffemodel','deploy.prototxt')
 coreml_model = coremltools.converters.caffe.convert(caffe_model,      
           image_input_names ='数据', 
           is_bgr = True, 
           red_bias = -104, 
           blue_bias = -123, 
           green_bias = -117, 
           image_scale = 1)#保存模型coreml_model.save('nsfw.mlmodel') 

需要注意的一点是:隐蔽方法的输入基于下面打开的nsfw项目中classify_nsfw.py的代码。

  #…#负载变压器
 #请注意,这些参数是硬编码的,以获得最佳结果caffe_transformer = caffe.io.Transformer({'data':nsfw_net.blobs ['data']。data.shape})caffe_transformer.set_transpose('data',(2,0 ,1)) 
 #将图像通道移动到externalmostcaffe_transformer.set_mean('data',np.array([104,117,123])) 
 #减去每个channelcaffe_transformer.set_raw_scale('data',255)中的数据集平均值 
 #从[0,1]缩放为[0,255] caffe_transformer.set_channel_swap('data',(2,1,0)) 
 #从RGB交换通道到BGR#… 

打开“终端”,cd到您的本地目录,其中包含convert.pyresnet_50_1by2_nsfw.caffemodeldeploy.prototxt

运行“ python convert.py ”。 控制台将开始转换并打印模型的每一层。 完成后,您将在同一目录中获得一个可供使用的nsfw.mlmodel

2.将nsfw.mlmodel添加到Xcode项目

只需将nsfw.mlmodel拖到左侧的文件导航器中即可。 确保在右侧导航器的“目标成员身份”中选中了您的项目。 Xcode将为您自动在Swift或Objetive-C中生成模型类的源代码。 要查看自动生成的类,请单击nsfw模型类旁边的小箭头。

在本教程中,我将使用Swift。 如果要切换语言,请在导航器中单击您的项目,转到“构建设置”,然后搜索CoreML Model Compiler –代码生成 。 您可以从CoreML代码生成语言下的不同选项中进行选择。

现在,我们准备在代码中创建nsfw模型。 只需使用生成的nsfw类的初始化程序,然后在ViewController.swift中的IBOutlet之前添加以下行:

 让模型= nsfw() 

3.代码

让我们快速看一下nsfw类的生成代码。 由于nsfw模型的输入类型为CVPixelBuffer (224 x 224) 而且现在只有UIImage ,让我们编写一些代码进行转换。 在ViewController.swift的末尾,将以下扩展添加到UIImage

  // MARK:— UIImage
扩展程序UIImage { 
     func buffer()-> CVPixelBuffer?  { 
         var pixelBuffer:CVPixelBuffer?  =零宽度= 224 
        让高度= 224让属性= [kCVPixelBufferCGImageCompatibilityKey: 
                  kCFBooleanTrue,    
                 kCVPixelBufferCGBitmapContextCompatibilityKey:
                  kCFBooleanTrue]作为CFDictionary 
        
         CVPixelBufferCreate(kCFAllocatorDefault,width,height, 
                 kCVPixelFormatType_32ARGB,attrs,&pixelBuffer)     
         CVPixelBufferLockBaseAddress(pixelBuffer !, 
                 CVPixelBufferLockFlags(rawValue:0))让colorspace = CGColorSpaceCreateDeviceRGB() 
        让bitmapContext = CGContext(data:     
                 CVPixelBufferGetBaseAddress(pixelBuffer!), 
                宽度:宽度, 
                高度:高度 
                 bitsPerComponent:8 
                 bytesPerRow:
                   CVPixelBufferGetBytesPerRow(pixelBuffer!), 
                空间:色彩空间, 
                 bitmapInfo: 
                  CGImageAlphaInfo.no​​neSkipFirst.rawValue)!  bitmapContext.draw(self.cgImage !,在: 
                 CGRect(x:0,y:0,width:width,height:height))返回pixelBuffer 
     }
 } 

在ViewController内,我创建了一个名为detectPhoto(image:UIImage)的函数,除了在从相机胶卷中选择一张照片后将标签更改为“ predicting”之外,它现在实际上并没有执行任何操作。 这是主要部分:现在,我们将添加用于预测照片是否适合工作的代码。 在完成所有准备工作之后,此步骤相当容易。 在detectPhoto(image:UIImage)///之后添加以下代码。

  //将UIImage转换为CVPixelBuffer
让buffer = image.buffer()!  //预测
守护让输出=尝试?  model.prediction(data:buffer)else { 
     fatalError(“意外的运行时错误。”)
 } //获取预测结果
 let proba = output.prob [1] .doubleValue //更新答案 
 labelself.answerLabel.text =字符串(格式:“%。6f”,proba) 

4.获得预测

在手机或模拟器上运行该应用程序。 从您的相册中选择一张照片,最终乐谱将打印在屏幕上。

从nsfw模型的GitHub页面上的REAMDE:

网络获取图像并给出输出概率(分数在0–1之间),该概率可用于过滤不适合工作图像的图像。 得分 0.8表示该图像很有可能是NSFW。 中间范围的分数可以针对不同的NSFW级别进行分类。

您还可以在其博客页面上找到有关该模型的信息。

这是我得到的两个示例结果。 可爱的小猫绝对比穿着比基尼的辣妹更安全的工作。😉希望这个小项目对您有所帮助。 您还可以在这里找到该项目的完整版本。