iOS 原生目標(biāo)(口罩)檢測 Core ML - 模型訓(xùn)練尝艘、使用模型

我們的目的: 在圖片中找出口罩的位置,當(dāng)然你也可以找出其他你想要檢測出的東西,這里只拿口罩舉例

老規(guī)矩, 看下效果

IMB_AKAqS6.GIF

IMB_5YIMBZ.GIF

這只是13張圖片的訓(xùn)練的效果,我懶得找圖了,用的就是訓(xùn)練數(shù)據(jù)測試的,效果還行,最后會解釋為什么有的圖片檢測不到

(一)準(zhǔn)備

  • 訓(xùn)練的樣本 (帶有口罩的圖片)
  • https://cloud.annotations.ai/ 這個是IBM在線標(biāo)注的服務(wù),自己去注冊免費的,還要注冊一個云存儲啥的,自己搞定就完事了
  • Xcode with Create ML 這才是核心

(一)標(biāo)注

image.png
  • (2) 輸入項目名字 選擇標(biāo)注類型
image.png

我們選右邊的小企鵝,這個是用來做地標(biāo)檢測的(就是 landmarks),不知道咋翻,左邊那個小企鵝是做圖片分類的,沒有位置信息啥的

  • (3)開始標(biāo)注

我們將要標(biāo)注的圖片直接拖進(jìn)網(wǎng)頁就行了


image.png

用鼠標(biāo)標(biāo)注好后.我們可以在右側(cè)將這個標(biāo)注命名,比如 mask

  • (4)導(dǎo)出標(biāo)注文件
image.png

這里我們導(dǎo)出 Create ML 所需要的文件格式,基本上就是下面這個樣子,帶一個json文件

image.png

(二) 開始訓(xùn)練

  • (1) 打開Xcode -> Open Developer Tools -> Create ML


    image.png

我們選擇 Object Detector 目標(biāo)檢測器(多個小企鵝),同樣左邊的適用一個小企鵝的標(biāo)注

  • (2) 開始訓(xùn)練
image.png

我們將剛才導(dǎo)出的Create ML的標(biāo)注圖片的文件夾直接拖進(jìn)來, 然后點擊左上角的Train 就可以

-------------------- A Few Moments Later -------------------

  • 等到迭代的數(shù)量達(dá)到max (1000)后, loss(損失函數(shù)) 也比較低的時候 ,就證明我們的模型已經(jīng)訓(xùn)練好了, Create ML 會自己結(jié)束的,我們只有等就行了.

  • 這個時間很長 電腦放在那里就可以了

(三) 測試模型

image.png

點擊右邊的Output , 然后將我們的測試數(shù)據(jù)集拖進(jìn)來,切換一下,就可以看到我們模型的測試結(jié)果了.

PS : 模型的效果 取決于 網(wǎng)絡(luò)的結(jié)構(gòu)(這個我們改不了), 訓(xùn)練樣本的數(shù)量和質(zhì)量,標(biāo)注的準(zhǔn)確性

如何提高訓(xùn)練的效率

  • 建議訓(xùn)練樣本在訓(xùn)練前,我們用python 或者其他什么語言隨便你, 將我們的訓(xùn)練樣本處理一遍,比如處理好樣本的尺寸、質(zhì)量等,過濾掉質(zhì)量差的圖片
  • 還有一個思路就是, 初代模型 來處理訓(xùn)練樣本, 雖然說初代模型可能效果不好,但是也可以做到目標(biāo)的大致定位,在得到大致的位置之后,我們再做圖片的尺寸和質(zhì)量處理,這樣我們的訓(xùn)練樣本會更好

---------------- 開始貼代碼 ---------------

(四) 代碼事例

  • (1) 新建一個工程 在storyboard 里拖一個 UIImageView 和一個 UIButton 就可以了
  • (2) 把訓(xùn)練好的model 拖到工程中
    找到你的Create ML 工程 然后顯示包內(nèi)容 就能找到你的model 了


    image.png
lazy var detectorRequest: VNCoreMLRequest = {
        do {
            let model = try VNCoreMLModel(for: faceMask().model)
            
            let request = VNCoreMLRequest(model: model, completionHandler: { [weak self] request, error in
                self?.detectionResult(request: request, error: error)
            })
            request.imageCropAndScaleOption = .scaleFit
            return request
        } catch {
            fatalError("Failed to load Vision ML model: \(error)")
        }
    }()
    
    @IBAction func choosePic(_ sender: Any) {
        choosePic()
    }
    
    func detectionResult(request:VNRequest,error:Error?) -> Void {
        DispatchQueue.main.async {
            guard let resutls = request.results else {
                print("啥也沒有")
                return
            }
            let detections = resutls as! [VNRecognizedObjectObservation]
            self.drawMaskRect(detections: detections)
        }
    }
    
    func drawMaskRect(detections:[VNRecognizedObjectObservation]) -> Void {
        guard let image = self.content?.image else {
            return
        }
        
        let imageSize = image.size
        let scale: CGFloat = 0
        UIGraphicsBeginImageContextWithOptions(imageSize, false, scale)
        
        image.draw(at: CGPoint.zero)
        
        for detection in detections {
            processed image, with the origin at the image's lower-left corner.
            let boundingBox = detection.boundingBox
            let rectangle = CGRect(x: boundingBox.minX*image.size.width, y: (1-boundingBox.minY-boundingBox.height)*image.size.height, width: boundingBox.width*image.size.width, height: boundingBox.height*image.size.height)
            UIColor(red: 0, green: 1, blue: 0, alpha: 0.4).setFill()
            UIRectFillUsingBlendMode(rectangle, CGBlendMode.normal)
        }
        
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        self.content?.image = newImage
    }
    
    
    
    func detectImage(image:UIImage) -> Void {
        let orientation = CGImagePropertyOrientation(rawValue: UInt32(image.imageOrientation.rawValue))
        guard let ciImage = CIImage(image: image) else { fatalError("Unable to create \(CIImage.self) from \(image).") }
        
        DispatchQueue.global(qos: .userInitiated).async {
            let handler = VNImageRequestHandler(ciImage: ciImage, orientation: orientation!)
            do {
                try handler.perform([self.detectorRequest])
            } catch {
                print("Failed to perform detection.\n\(error.localizedDescription)")
            }
        }
    }
    
    func choosePic() {
        let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
        
        let camera = UIAlertAction(title: "相機(jī)", style: .default) { (action) in
            if (UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera)){
                let pickerVC = UIImagePickerController()
                pickerVC.delegate = self
                pickerVC.allowsEditing = true
                pickerVC.sourceType = .camera
                self .present(pickerVC, animated: true, completion: nil)
            }
        }
        
        let album = UIAlertAction(title: "相冊", style: .default) { (action) in
            if (UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.photoLibrary)){
                let pickerVC = UIImagePickerController()
                pickerVC.delegate = self
                pickerVC.allowsEditing = true
                pickerVC.sourceType = .photoLibrary
                self .present(pickerVC, animated: true, completion: nil)
            }
        }
        
        let cancel = UIAlertAction(title: "取消", style: .cancel, handler: nil)
        
        alert.addAction(camera)
        alert.addAction(album)
        alert.addAction(cancel)
        
        self.present(alert, animated: true, completion: nil)
    }
    
}

extension ViewController : UIImagePickerControllerDelegate ,UINavigationControllerDelegate{
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        picker.dismiss(animated: true, completion: nil)
         guard let image = info[.originalImage] as? UIImage else {
                   return
               }
       self.content.image = image
        self.detectImage(image: image)
        
    }
}

遇到的問題

  • (1)檢測結(jié)果不準(zhǔn), 這個問題處理半天,不知道為什么結(jié)果 跟在Create ML里測試的結(jié)果不一樣, 而且非常離譜,在真機(jī)上也一樣

解決辦法: 升級Xcode,我不知道是Xcode 的原因 還是iOS 系統(tǒng)的原因,升級Xcode 到11.3.1后 模擬器應(yīng)該是13.0 這回結(jié)果就對了, 沒升級手機(jī)系統(tǒng)太慢了,只在模擬器上測試了

看下模擬器的效果

image.png

效果還可以吧, 別拍照檢測了 , 數(shù)據(jù)量少大部分檢測不出來,我這是運氣好,建議直接用訓(xùn)練的樣本來測試, 我試了用相機(jī)去拍樣本,還是檢測不到,要拍的尺寸差不多才能檢測的到,這也就是上面為什么說訓(xùn)練樣本要預(yù)處理,你的輸入數(shù)據(jù)最好都是一樣的

怎么將圖片放到模擬器的?

打開模擬器的相冊 ,直接把圖片拖進(jìn)去就可以了

擴(kuò)展

以上只是一種機(jī)器學(xué)習(xí)的應(yīng)用, 我們可以看到Create ML 的模版還有很多分類,不僅可以檢測地標(biāo), 還可以進(jìn)行圖片分類、語音分類、動作分類缎罢、文字分類等等, 有了這些模版,我們就可以做很多東西的識別

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市考杉,隨后出現(xiàn)的幾起案子策精,更是在濱河造成了極大的恐慌,老刑警劉巖崇棠,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咽袜,死亡現(xiàn)場離奇詭異,居然都是意外死亡易茬,警方通過查閱死者的電腦和手機(jī)酬蹋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門及老,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人范抓,你說我怎么就攤上這事骄恶。” “怎么了匕垫?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵僧鲁,是天一觀的道長。 經(jīng)常有香客問我象泵,道長寞秃,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任偶惠,我火速辦了婚禮春寿,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘忽孽。我一直安慰自己绑改,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布兄一。 她就那樣靜靜地躺著厘线,像睡著了一般。 火紅的嫁衣襯著肌膚如雪出革。 梳的紋絲不亂的頭發(fā)上造壮,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機(jī)與錄音骂束,去河邊找鬼耳璧。 笑死,一個胖子當(dāng)著我的面吹牛展箱,可吹牛的內(nèi)容都是我干的楞抡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼析藕,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了凳厢?” 一聲冷哼從身側(cè)響起账胧,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎先紫,沒想到半個月后治泥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡遮精,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年居夹,在試婚紗的時候發(fā)現(xiàn)自己被綠了败潦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡准脂,死狀恐怖劫扒,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情狸膏,我是刑警寧澤沟饥,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站湾戳,受9級特大地震影響贤旷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜砾脑,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一幼驶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧韧衣,春花似錦盅藻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至顶瞒,卻和暖如春夸政,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背榴徐。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工守问, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人坑资。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓耗帕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親袱贮。 傳聞我的和親對象是個殘疾皇子仿便,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容