zoukankan      html  css  js  c++  java
  • [Xcode 实际操作]七、文件与数据-(20)CoreML机器学习框架:检测和识别图片中的物体

    目录:[Swift]Xcode实际操作

    本文将演示机器学习框架的使用,实现对图片中物体的检测和识别。

    首先访问苹果开发者网站关于机器学习的网址:

    https://developer.apple.com/cn/machine-learning/

    点击右侧的滚动条,跳转到模型知识区域。

    点击页面最下方的【Learn about working with models】进入机器学习模型页面:

    https://developer.apple.com/cn/machine-learning/build-run-models/

    点击右侧的垂直滚动条,跳转到模型下载区域。

    苹果提供了多个已经完成训练的机器学习模型,

    选择【ResNet 50】:从 1000 种类别对象 (如树木、动物、食物、汽车及人物等) 中检测出图像中的主体。

    点击下方的【Core】进行下载,https://docs-assets.developer.apple.com/coreml/models/Resnet50.mlmodel

    模型下载后将模型拖动到项目中【DemoApp】

    在弹出的选项设置窗口中,保持默认的参数设置,然后点击完成【Finish】按钮,确认模型的导入。

    在左侧的模型框架区,选择查看模型文件。

    从右侧的属性面板可以看出模型的类型、体积、作者、版权声明、描述信息。

    从底部的参数可以看出,该模型拥有一个输入参数,和两个输出参数。

    在资源文件中导入一张鸟类的图片,将使用机器学习迅雷模型,检测图片中出现的鸟类的名称。

    在项目导航区,打开视图控制器的代码文件【ViewController.swift】

      1 import UIKit
      2 //导入机器学习框架
      3 import CoreML
      4 
      5 class ViewController: UIViewController {
      6     
      7     override func viewDidLoad() {
      8         super.viewDidLoad()
      9         // Do any additional setup after loading the view, typically from a nib.
     10         
     11         //加载项目中指定名称的图片资源
     12         let image = UIImage(named: "sample")
     13         
     14         //机器学习模型只可以识别像素缓存格式的图像,
     15         //需要将图片的格式进行转换,
     16         //首先定义图片格式转换后的宽度和高度
     17         let width : CGFloat = 224.0
     18         let height : CGFloat = 224.0
     19         
     20         //然后获得一个基于位图的上下文,并设置其为当前的上下文。
     21         UIGraphicsBeginImageContext(CGSize( width, height: height))
     22         //将从项目中加载的图像,绘制在上下文的指定区域
     23         image?.draw(in:CGRect(x: 0, y: 0,  width, height: height))
     24         //接着从上下文中获得格式转换后的图像
     25         let newImage = UIGraphicsGetImageFromCurrentImageContext()
     26         //完成图像的格式转换后,关闭当前的上下文。
     27         UIGraphicsEndImageContext()
     28         
     29         //添加一个版本兼容性的判断语句
     30         if #available(iOS 11.0, *)
     31         {
     32             //初始化机器学习模型的对象
     33             let resnet50 = Resnet50()
     34             
     35             //通过调用机器学习模型的对象的预测方法,对图像中的物体进行识别。
     36             //需要注意的是,传入的图片需要是CVPixelBuffer格式,
     37             //这里使用一个方法将图片进行格式转换,此方法在下方实现
     38             guard let output = try? resnet50.prediction(image:pixelBufferFromImage(image: newImage!)) else
     39             {
     40                 fatalError("Unexpected error.")
     41             }
     42             
     43             //在控制台输出识别的结果
     44             print(output.classLabel)
     45         }
     46     }
     47     
     48     //添加一个方法,用来实现图片格式的转换
     49     func pixelBufferFromImage(image: UIImage) -> CVPixelBuffer
     50     {
     51         //初始化一个上下文对象,它将被用来渲染CIImage图像
     52         let ciContext = CIContext(options: nil)
     53         //通过UIImage对象,初始化一个CIImage对象。
     54         let ciImage = CIImage(image: image)
     55         //通过上下文对象,将CIImage对象,转换为CGImage类型。
     56         //其中extend属性表示该对象在上下文中的区域。
     57         let cgImage = ciContext.createCGImage(ciImage!, from: ciImage!.extent)
     58         
     59         //创建一个非安全的可变指针,并给指针分配相应的内存。
     60         let umPointer = UnsafeMutablePointer<UnsafeRawPointer>.allocate(capacity: 1)
     61         //初始化一个CFNumber格式的数字,该类型位于Core Foundation框架
     62         let cfNum = CFNumberCreate(kCFAllocatorDefault, .intType, umPointer)
     63         //初始化一个数组对象,它将作为后面的字典对象的值
     64         let values: [CFTypeRef] = [kCFBooleanTrue, kCFBooleanTrue, cfNum!]
     65         //初始化两个非安全可变指针,作为字典的键和值
     66         //
     67         let keysPointer = UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: 1)
     68         //
     69         let valuesPointer =  UnsafeMutablePointer<UnsafeRawPointer?>.allocate(capacity: 1)
     70         
     71         //初始化一个字符串数组,包含三个键
     72         //1.像素缓存图像兼容性
     73         //2.像素缓存位图上下文兼容性
     74         //3..像素缓存每行的字节数
     75         let keys: [CFString] = [kCVPixelBufferCGImageCompatibilityKey,//1.像素缓存图像兼容性
     76         kCVPixelBufferCGBitmapContextCompatibilityKey,//2.像素缓存位图上下文兼容性
     77         kCVPixelBufferBytesPerRowAlignmentKey]//3..像素缓存每行的字节数
     78         //使用上文创建的两个数字,
     79         //对键、值两个非安全可变指针进行初始化
     80         keysPointer.initialize(to: keys)
     81         valuesPointer.initialize(to: values)
     82         
     83         //通过键、值两个指针,以及默认的内存分配方式和键的数量等参数,初始化一个字典对象。
     84         //该字典对象将作为配置选项,被用来创建像素缓存
     85         let options = CFDictionaryCreate(kCFAllocatorDefault, keysPointer, valuesPointer, keys.count, nil, nil)
     86         //新建一个图像缓存变量
     87         var pxbuffer: CVPixelBuffer?
     88         //然后对输入的缓存变量进行初始化。
     89         //参数依次标注
     90         var status = CVPixelBufferCreate(kCFAllocatorDefault, //1.内存分配方式
     91         cgImage!.width,//2.图像宽度
     92         cgImage!.height,//3.图像高度
     93         kCVPixelFormatType_32BGRA, //4.像素格式类型
     94         options, //5.配置参数
     95         &pxbuffer)//6.像素缓存的内存地址
     96         //接着锁定像素缓冲区的基址,在使用CPU访问像素数据之前,必须调用该函数
     97         status = CVPixelBufferLockBaseAddress(pxbuffer!, CVPixelBufferLockFlags(rawValue: 0))
     98         
     99         //获得像素缓冲区的基址
    100         let bufferAddress = CVPixelBufferGetBaseAddress(pxbuffer!)
    101         //然后创建一个基于设备的RGB颜色空间。
    102         //当在输出设备上显示时,依赖于设备的颜色空间中的颜色,
    103         //不会被变换或以其他方式被修改
    104         let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
    105         //获得像素缓冲区每行的字节数
    106         let bytesperrow = CVPixelBufferGetBytesPerRow(pxbuffer!)
    107         //通过上文创建的参数,初始化一个二维绘图环境
    108         let context = CGContext(data: bufferAddress,
    109                                  cgImage!.width,
    110                                 height: cgImage!.height,
    111                                 bitsPerComponent: 8,
    112                                 bytesPerRow: bytesperrow,
    113                                 space: rgbColorSpace,
    114                                 bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue 
    115                                 | CGBitmapInfo.byteOrder32Little.rawValue)
    116         //重置二维绘图环境的旋转角度为0
    117         context?.concatenate(CGAffineTransform(rotationAngle: 0))
    118         //由于当前的二维绘图环境的坐标系统,和设备屏幕的坐标系统不同,
    119         //所以在此对二维绘图环境进行上下文翻转
    120         context?.concatenate(__CGAffineTransformMake( 1, 0, 0, -1, 0, CGFloat(cgImage!.height) ))
    121         
    122         //将图像绘制在二维绘图环境中,并指定图像的显示区域。
    123         context?.draw(cgImage!,
    124         in: CGRect(x:0, y:0, 
    125         CGFloat(cgImage!.width), 
    126         height:CGFloat(cgImage!.height)))
    127         //最后解锁橡树缓冲区的基地址。
    128         //在使用CPU访问像素数据之后,必须调用该函数。
    129         status = CVPixelBufferUnlockBaseAddress(pxbuffer!, CVPixelBufferLockFlags(rawValue: 0))
    130 
    131         //返回处理完成的像素缓存
    132         return pxbuffer!
    133     }
    134     
    135     override func didReceiveMemoryWarning() {
    136         super.didReceiveMemoryWarning()
    137         // Dispose of any resources that can be recreated.
    138     }
    139 }
  • 相关阅读:
    springboot自动装配mybatisplus时,凭啥MybatisPlusAutoConfiguration比MybatisAutoConfiguration先装配
    mybatis 整合 spring 时,mapper 是怎么被设置必要的参数的
    canvas 画的线无法清除的问题
    大学英语单词 第二单元
    快乐纪中(二)2
    jzoj 2644. 数列
    jzoj【NOIP2011模拟10.31】T1游戏
    快乐纪中
    树形DP
    炮兵阵地
  • 原文地址:https://www.cnblogs.com/strengthen/p/10052267.html
Copyright © 2011-2022 走看看