最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

iOS利用CoreImage實現(xiàn)人臉識別詳解

 更新時間:2017年05月04日 10:49:54   作者:Mr_Victory  
OS的人臉識別從iOS 5(2011)就有了,不過一直沒怎么被關(guān)注過。人臉識別API允許開發(fā)者不僅可以檢測人臉,也可以檢測到面部的一些特殊屬性,比如說微笑或眨眼。下面這篇文章主要給大家介紹了iOS利用CoreImage實現(xiàn)人臉識別的相關(guān)資料,需要的朋友可以參考下。

前言

CoreImage是Cocoa Touch中一個強大的API,也是iOS SDK中的關(guān)鍵部分,不過它經(jīng)常被忽視。在本篇教程中,我會帶大家一起驗證CoreImage的人臉識別特性。在開始之前,我們先要簡單了解下CoreImage framework 組成

CoreImage framework組成

Apple 已經(jīng)幫我們把image的處理分類好,來看看它的結(jié)構(gòu):

主要分為三個部分:

1、定義部分:CoreImage 和CoreImageDefines。見名思義,代表了CoreImage 這個框架和它的定義。

2、操作部分:

  • 濾鏡(CIFliter):CIFilter 產(chǎn)生一個CIImage。典型的,接受一到多的圖片作為輸入,經(jīng)過一些過濾操作,產(chǎn)生指定輸出的圖片。
  • 檢測(CIDetector):CIDetector 檢測處理圖片的特性,如使用來檢測圖片中人臉的眼睛、嘴巴、等等。
  • 特征(CIFeature):CIFeature 代表由 detector處理后產(chǎn)生的特征。

3、圖像部分:

  • 畫布(CIContext):畫布類可被用與處理Quartz 2D 或者 OpenGL??梢杂盟鼇黻P(guān)聯(lián)CoreImage類。如濾鏡、顏色等渲染處理。
  • 顏色(CIColor): 圖片的關(guān)聯(lián)與畫布、圖片像素顏色的處理。
  • 向量(CIVector): 圖片的坐標(biāo)向量等幾何方法處理。
  • 圖片(CIImage): 代表一個圖像,可代表關(guān)聯(lián)后輸出的圖像。

在了解上述基本知識后,我們開始通過創(chuàng)建一個工程來帶大家一步步驗證Core Image的人臉識別特性。

將要構(gòu)建的應(yīng)用

iOS的人臉識別從iOS 5(2011)就有了,不過一直沒怎么被關(guān)注過。人臉識別API允許開發(fā)者不僅可以檢測人臉,也可以檢測到面部的一些特殊屬性,比如說微笑或眨眼。

首先,為了了解Core Image的人臉識別技術(shù)我們會創(chuàng)建一個app來識別照片中的人臉并用一個方框來標(biāo)記它。在第二個demo中,讓用戶拍攝一張照片,檢測其中的人臉并檢索人臉位置。這樣一來,就充分掌握了iOS中的人臉識別,并且學(xué)會如何利用這個強大卻總被忽略的API。

話不多說,開搞!

建立工程(我用的是Xcode8.0)

這里提供了初始工程,當(dāng)然你也可以自己創(chuàng)建(主要是為了方便大家)點我下載 用Xcode打開下載后的工程,可以看到里面只有一個關(guān)聯(lián)了IBOutlet和imageView的StoryBoard。


使用CoreImage識別人臉

在開始工程中,故事板中的imageView組件與代碼中的IBOutlet已關(guān)聯(lián),接下來要編寫實現(xiàn)人臉識別的代碼部分。在ViewController.swift文件中寫下如下代碼:

import UIKit
import CoreImage // 引入CoreImage
class ViewController: UIViewController {
 @IBOutlet weak var personPic: UIImageView!

 override func viewDidLoad() {
 super.viewDidLoad()

 personPic.image = UIImage(named: "face-1")
 // 調(diào)用detect
 detect()

 }
 //MARK: - 識別面部
 func detect() {
 // 創(chuàng)建personciImage變量保存從故事板中的UIImageView提取圖像并將其轉(zhuǎn)換為CIImage,使用Core Image時需要用CIImage
 guard let personciImage = CIImage(image: personPic.image!) else {
  return
 }
 // 創(chuàng)建accuracy變量并設(shè)為CIDetectorAccuracyHigh,可以在CIDetectorAccuracyHigh(較強的處理能力)與CIDetectorAccuracyLow(較弱的處理能力)中選擇,因為想讓準(zhǔn)確度高一些在這里選擇CIDetectorAccuracyHigh
 let accuracy = [CIDetectorAccuracy: CIDetectorAccuracyHigh]
 // 這里定義了一個屬于CIDetector類的faceDetector變量,并輸入之前創(chuàng)建的accuracy變量
 let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: accuracy)
 // 調(diào)用faceDetector的featuresInImage方法,識別器會找到所給圖像中的人臉,最后返回一個人臉數(shù)組
 let faces = faceDetector?.features(in: personciImage)
 // 循環(huán)faces數(shù)組里的所有face,并將識別到的人臉強轉(zhuǎn)為CIFaceFeature類型
 for face in faces as! [CIFaceFeature] {

  print("Found bounds are \(face.bounds)")
  // 創(chuàng)建名為faceBox的UIView,frame設(shè)為返回的faces.first的frame,繪制一個矩形框來標(biāo)識識別到的人臉
  let faceBox = UIView(frame: face.bounds)
  // 設(shè)置faceBox的邊框?qū)挾葹?
  faceBox.layer.borderWidth = 3
  // 設(shè)置邊框顏色為紅色
  faceBox.layer.borderColor = UIColor.red.cgColor
  // 將背景色設(shè)為clear,意味著這個視圖沒有可見的背景
  faceBox.backgroundColor = UIColor.clear
  // 最后,把這個視圖添加到personPic imageView上
  personPic.addSubview(faceBox)
  // API不僅可以幫助你識別人臉,也可識別臉上的左右眼,我們不在圖像中標(biāo)識出眼睛,只是給你展示一下CIFaceFeature的相關(guān)屬性
  if face.hasLeftEyePosition {
  print("Left eye bounds are \(face.leftEyePosition)")
  }

  if face.hasRightEyePosition {
  print("Right eye bounds are \(face.rightEyePosition)")
  }
 }
 }
}

編譯并運行app,結(jié)果應(yīng)如下圖所示:


根據(jù)控制臺的輸出來看,貌似識別器識別到了人臉:

Found bounds are (314.0, 243.0, 196.0, 196.0)

當(dāng)前的實現(xiàn)中沒有解決的問題:

  • 人臉識別是在原始圖像上進(jìn)行的,由于原始圖像的分辨率比image view要高,因此需要設(shè)置image view的content mode為aspect fit(保持縱橫比的情況下縮放圖片)。為了合適的繪制矩形框,需要計算image view中人臉的實際位置與尺寸
  • 還要注意的是,CoreImage與UIView使用兩種不同的坐標(biāo)系統(tǒng)(看下圖),因此要實現(xiàn)一個CoreImage坐標(biāo)到UIView坐標(biāo)的轉(zhuǎn)換。

UIView坐標(biāo)系:


CoreImage坐標(biāo)系:

現(xiàn)在使用下面的代碼替換detect()方法:

func detect1() {

 guard let personciImage = CIImage(image: personPic.image!) else { return }
 let accuracy = [CIDetectorAccuracy: CIDetectorAccuracyHigh]
 let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: accuracy)
 let faces = faceDetector?.features(in: personciImage)

 // 轉(zhuǎn)換坐標(biāo)系
 let ciImageSize = personciImage.extent.size
 var transform = CGAffineTransform(scaleX: 1, y: -1)
 transform = transform.translatedBy(x: 0, y: -ciImageSize.height)

 for face in faces as! [CIFaceFeature] {
 print("Found bounds are \(face.bounds)") 
 // 應(yīng)用變換轉(zhuǎn)換坐標(biāo)
 var faceViewBounds = face.bounds.applying(transform)
 // 在圖像視圖中計算矩形的實際位置和大小
 let viewSize = personPic.bounds.size
 let scale = min(viewSize.width / ciImageSize.width, viewSize.height / ciImageSize.height)
 let offsetX = (viewSize.width - ciImageSize.width * scale) / 2
 let offsetY = (viewSize.height - ciImageSize.height * scale) / 2

 faceViewBounds = faceViewBounds.applying(CGAffineTransform(scaleX: scale, y: scale))
 faceViewBounds.origin.x += offsetX
 faceViewBounds.origin.y += offsetY

 let faceBox = UIView(frame: faceViewBounds)
 faceBox.layer.borderWidth = 3
 faceBox.layer.borderColor = UIColor.red.cgColor
 faceBox.backgroundColor = UIColor.clear
 personPic.addSubview(faceBox)

 if face.hasLeftEyePosition {
  print("Left eye bounds are \(face.leftEyePosition)")
 }

 if face.hasRightEyePosition {
  print("Right eye bounds are \(face.rightEyePosition)")
 }
 }
}

上述代碼中,首先使用仿射變換(AffineTransform)將Core Image坐標(biāo)轉(zhuǎn)換為UIKit坐標(biāo),然后編寫了計算實際位置與矩形視圖尺寸的代碼。

再次運行app,應(yīng)該會看到人的面部周圍會有一個框。OK,你已經(jīng)成功使用Core Image識別出了人臉。

但是有的童鞋在使用了上面的代碼運行后可能會出現(xiàn)方框不存在(即沒有識別人臉)這種情況,這是由于忘記關(guān)閉Auto Layout以及Size Classes了。 選中storyBoard中的ViewController,選中view下的imageView。然后在右邊的面板中的第一個選項卡中找到use Auto Layout ,將前面的✔️去掉就可以了

經(jīng)過上面的設(shè)置后我們再次運行App,就會看到圖三出現(xiàn)的效果了。

構(gòu)建一個人臉識別的相機(jī)應(yīng)用

想象一下你有一個用來照相的相機(jī)app,照完相后你想運行一下人臉識別來檢測一下是否存在人臉。若存在一些人臉,你也許想用一些標(biāo)簽來對這些照片進(jìn)行分類。我們不會構(gòu)建一個保存照片后再處理的app,而是一個實時的相機(jī)app,因此需要整合一下UIImagePicker類,在照完相時立刻進(jìn)行人臉識別。

在開始工程中已經(jīng)創(chuàng)建好了CameraViewController類,使用如下代碼實現(xiàn)相機(jī)的功能:

class CameraViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
 @IBOutlet var imageView: UIImageView!
 let imagePicker = UIImagePickerController()

 override func viewDidLoad() {
  super.viewDidLoad()
  imagePicker.delegate = self
 }

 @IBAction func takePhoto(_ sender: AnyObject) {

  if !UIImagePickerController.isSourceTypeAvailable(.camera) {
   return
  }

  imagePicker.allowsEditing = false
  imagePicker.sourceType = .camera

  present(imagePicker, animated: true, completion: nil)
 }

 func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

  if let pickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {
   imageView.contentMode = .scaleAspectFit
   imageView.image = pickedImage
  }

  dismiss(animated: true, completion: nil)
  self.detect()
 }

 func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
  dismiss(animated: true, completion: nil)
 }
}

前面幾行設(shè)置UIImagePicker委托為當(dāng)前視圖類,在didFinishPickingMediaWithInfo方法(UIImagePicker的委托方法)中設(shè)置imageView為在方法中所選擇的圖像,接著返回上一視圖調(diào)用detect函數(shù)。

還沒有實現(xiàn)detect函數(shù),插入下面代碼并分析一下:

func detect() {
 let imageOptions = NSDictionary(object: NSNumber(value: 5) as NSNumber, forKey: CIDetectorImageOrientation as NSString)
 let personciImage = CIImage(cgImage: imageView.image!.cgImage!)
 let accuracy = [CIDetectorAccuracy: CIDetectorAccuracyHigh]
 let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: accuracy)
 let faces = faceDetector?.features(in: personciImage, options: imageOptions as? [String : AnyObject])

 if let face = faces?.first as? CIFaceFeature {
  print("found bounds are \(face.bounds)")

  let alert = UIAlertController(title: "提示", message: "檢測到了人臉", preferredStyle: UIAlertControllerStyle.alert)
  alert.addAction(UIAlertAction(title: "確定", style: UIAlertActionStyle.default, handler: nil))
  self.present(alert, animated: true, completion: nil)

  if face.hasSmile {
   print("face is smiling");
  }

  if face.hasLeftEyePosition {
   print("左眼的位置: \(face.leftEyePosition)")
  }

  if face.hasRightEyePosition {
   print("右眼的位置: \(face.rightEyePosition)")
  }
 } else {
  let alert = UIAlertController(title: "提示", message: "未檢測到人臉", preferredStyle: UIAlertControllerStyle.alert)
  alert.addAction(UIAlertAction(title: "確定", style: UIAlertActionStyle.default, handler: nil))
  self.present(alert, animated: true, completion: nil)
 }
}

這個detect()函數(shù)與之前實現(xiàn)的detect函數(shù)非常像,不過這次只用它來獲取圖像不做變換。當(dāng)識別到人臉后顯示一個警告信息“檢測到了人臉!”,否則顯示“未檢測到人臉”。運行app測試一下:

我們已經(jīng)使用到了一些CIFaceFeature的屬性與方法,比如,若想檢測人物是否微笑,可以調(diào)用.hasSmile,它會返回一個布爾值??梢苑謩e使用.hasLeftEyePosition與.hasRightEyePosition檢測是否存在左右眼。

同樣,可以調(diào)用hasMouthPosition來檢測是否存在嘴,若存在則可以使用mouthPosition屬性,如下所示:

if (face.hasMouthPosition) {
 print("mouth detected")
}

如你所見,使用Core Image來檢測面部特征是非常簡單的。除了檢測嘴、笑容、眼睛外,也可以調(diào)用leftEyeClosed與rightEyeClosed檢測左右眼是否睜開,這里就不在貼出代碼了。

總結(jié)

在這篇教程中嘗試了CoreImage的人臉識別API與如何在一個相機(jī)app中應(yīng)用它,構(gòu)建了一個簡單的UIImagePicker來選取照片并檢測圖像中是否存在人物。

如你所見,Core Image的人臉識別是個強大的API!希望這篇教程能給你提供一些關(guān)于這個鮮為人知的iOS API有用的信息。

Github地址:點擊swift版地址,OC版地址下載

本地下載:點擊swift版地址,OC版地址下載

好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

最新評論

封开县| 青川县| 太湖县| 玉龙| 安多县| 施秉县| 乐业县| 喀什市| 巩义市| 蓝山县| 六盘水市| 陈巴尔虎旗| 略阳县| 临城县| 东乌珠穆沁旗| 南投市| 洛川县| 拜城县| 房山区| 台南县| 泗水县| 樟树市| 莒南县| 利津县| 繁昌县| 辽阳市| 长治市| 江达县| 淮南市| 灌阳县| 尤溪县| 梅河口市| 清涧县| 缙云县| 紫云| 瓮安县| 山东省| 靖宇县| 渭南市| 平乡县| 安图县|