初探 Core ML:學(xué)習(xí)建立一個(gè)圖像識(shí)別 App

在 WWDC 2017 中塞颁,Apple 發(fā)表了許多令開發(fā)者們?yōu)橹駣^的新框架(Framework) 及 API 祠锣。而在這之中锤岸,最引人注目的莫過(guò)于 Core ML 了是偷。藉由 Core ML蛋铆,你可以為你的 App 添增機(jī)器學(xué)習(xí)(Machine Learning)的能力刺啦。而最棒的是你不需要深入的了解關(guān)于神經(jīng)網(wǎng)絡(luò)(Neural Network)以及機(jī)器學(xué)習(xí)(Machine Learning)的相關(guān)知識(shí)玛瘸。接下來(lái)我們將會(huì)使用 Apple 開發(fā)者網(wǎng)站上提供的 Core ML 模型來(lái)制作示例 App糊渊。話不多說(shuō)渺绒,Let’s Start To Learn Core ML!

注: 接下來(lái)的教學(xué)會(huì)使用 Xcode 9 作為開發(fā)工具,同時(shí)需要有 iOS 11 的設(shè)備以便測(cè)試其中的功能殷绍。Xcode 9 支持 Swift 3.2 及 4.0主到,我們使用 Swift 4.0 開發(fā)镰烧。

什么是 Core ML

根據(jù) Apple 官方說(shuō)明:

Core ML lets you integrate a broad variety of machine learning model types into your app. In addition to supporting extensive deep learning with over 30 layer types, it also supports standard models such as tree ensembles, SVMs, and generalized linear models. Because it’s built on top of low level technologies like Metal and Accelerate, Core ML seamlessly takes advantage of the CPU and GPU to provide maximum performance and efficiency. You can run machine learning models on the device so data doesn’t need to leave the device to be analyzed.

Core ML 是在今年 WWDC 中發(fā)表的全新機(jī)器學(xué)習(xí)框架,將會(huì)隨著 iOS 11 正式發(fā)布结执。使用 Core ML献幔,你可以將機(jī)器學(xué)習(xí)整合進(jìn)自己的 App 之中蜡感。 在這邊我們先停一下,什么是機(jī)器學(xué)習(xí)(Machine Learning)呢犀斋?簡(jiǎn)單來(lái)說(shuō)叽粹,機(jī)器學(xué)習(xí)是給予電腦可以在不明確撰寫程式的情況下學(xué)習(xí)能力的應(yīng)用虫几。而一個(gè)完成訓(xùn)練的模型便是指將資料經(jīng)由演算法結(jié)合后的成果辆脸。

trained-model

作為開發(fā)者,我們主要關(guān)心的是如何使用機(jī)器學(xué)習(xí)模型來(lái)做出有趣的玩意空执。幸運(yùn)的是辨绊,Apple 讓 Core ML 可以很簡(jiǎn)單的將不同的機(jī)器學(xué)習(xí)模型整合進(jìn)我們的 App 中门坷。如此一來(lái)一般的開發(fā)者們也將能夠制作出圖像識(shí)別默蚌、語(yǔ)言處理苇羡、輸入預(yù)測(cè)等等功能。

聽(tīng)起來(lái)是不是很酷呢攘轩?讓我們開始吧度帮。

示例 App 概覽

接下來(lái)要制作的 App 相當(dāng)?shù)睾?jiǎn)單。這個(gè) App 能夠讓使用者拍照或是從相簿中選擇一張相片冕屯,然后機(jī)器學(xué)習(xí)演算法將會(huì)試著辨識(shí)出相片中的物品是什么安聘。雖然可能無(wú)法每次都識(shí)別成功浴韭,但你可以藉此思考出如何在你 App 里使用 Core ML念颈。

coreml-app-demo

現(xiàn)在就開始吧榴芳!

首先窟感,開啟 Xcode 9 然后建立一個(gè)新項(xiàng)目柿祈。選擇 Single View App躏嚎,接著確認(rèn)程式語(yǔ)言為 Swift卢佣。

xcode9-new-proj

制作界面

編注: 如果不想重頭開始制作UI的話晚缩,你可以下載 后,直接閱讀關(guān)于 Core ML 實(shí)作的段落

一開始我們要做的是打開 Main.storyboard 然后加入幾個(gè) UI 元件到 View 之中待笑。因此我們先點(diǎn)選 StoryBoard 中的 ViewController暮蹂,然后到 Xcode 的功能列中點(diǎn)選 Editor-> Embed In-> Navigation Controller仰泻。當(dāng)完成后你會(huì)看到 Navigation Bar 出現(xiàn)在 View 之上集侯,接著我們將這個(gè) Navigation Bar 的標(biāo)題命名為 Core ML(或是任何你覺(jué)得適合的文字)棠枉。

Core ML Demo UI

接下來(lái)辈讶,拖曳兩個(gè)按鈕到 Navigation Bar 里頭,一個(gè)放在標(biāo)題左邊一個(gè)放右邊月幌。接著點(diǎn)選左邊的按鈕然后到右側(cè)的 Attributes Inspector 里將按鈕由 System Item 改為 「Camera」飞醉。右邊的按鈕則修改文字為 「Library」缅帘。這兩個(gè)按鈕的用途是讓使用者可以從相簿中選取相片或開啟相機(jī)拍照钦无。

最后我們還需要加入兩個(gè)元件盖袭,分別是 UILabel 及 UIImageView失暂。拖曳 UIImageView 到 View 裡設(shè)定垂直水平置中以及長(zhǎng)寬為 299彼宠,讓 UIImageView 看起來(lái)是個(gè)正方形。現(xiàn)在輪到 UILabel弟塞,將其放入到 View 的底部并延伸兩端到 View 的兩側(cè)凭峡。這樣我們完成這個(gè) App 的 UI 了。

雖然沒(méi)有提到設(shè)定這些 View 的 Auto Layout决记,但很推薦你嘗試設(shè)定 Auto Layout 以避免 UI 元件的錯(cuò)置。如果你不了解如何設(shè)定系宫,也可以將 Storyboard 的尺寸設(shè)定為你要運(yùn)行的設(shè)備尺寸索昂。

coreml-storyboard

實(shí)作相機(jī)以及相簿功能

現(xiàn)在我們已經(jīng)完成 UI 了,接下來(lái)往實(shí)作功能的方向前進(jìn)吧扩借。在這個(gè)段落中椒惨,我們將會(huì)實(shí)作相簿以及相機(jī)按鈕功能。首先在 ViewController.swift 中潮罪,我們要先調(diào)用 UINavigationControllerDelegate 康谆,因?yàn)楹罄m(xù)的 UIImagePickerController 會(huì)需要用到這部份。

class ViewController: UIViewController, UINavigationControllerDelegate 

接著為畫面上的 UILabel 及 UIImageView 加上 IBoutlet错洁。為了方便起見(jiàn)秉宿,我將 UIImageView 命名為 imageView,UILabel 則命名為 classifier屯碴。完成后的代碼應(yīng)該會(huì)如下面所呈現(xiàn)的樣子:

import UIKit
 
class ViewController: UIViewController, UINavigationControllerDelegate {
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var classifier: UILabel!
    
     override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

接下來(lái)描睦,你需要為兩個(gè)按鈕分別建立 IBAction 。請(qǐng)將以下的 Action 方法加入至 Viewcontroller 中吧:

@IBAction func camera(_ sender: Any) {
    
    if !UIImagePickerController.isSourceTypeAvailable(.camera) {
        return
    }
    
    let cameraPicker = UIImagePickerController()
    cameraPicker.delegate = self
    cameraPicker.sourceType = .camera
    cameraPicker.allowsEditing = false
    
    present(cameraPicker, animated: true)
}
 
@IBAction func openLibrary(_ sender: Any) {
    let picker = UIImagePickerController()
    picker.allowsEditing = false
    picker.delegate = self
    picker.sourceType = .photoLibrary
    present(picker, animated: true)
}

到這邊我們先了解一下上述的 Action 方法导而。我們各產(chǎn)生了一個(gè) UIImagePickerController 常數(shù)忱叭,然后將其設(shè)定為不允許編輯圖像(不論是相機(jī)拍攝或是相簿選取)今艺,接著將 Delegate 指向?yàn)樽约涸铣蟆W詈蟪尸F(xiàn) UIImagePickerController 給使用者。

因?yàn)槲覀兩形磳?UIImagePickerControllerDelegate 的方法們加入至 ViewController.swift中虚缎,所以會(huì)發(fā)生錯(cuò)誤撵彻。我們另外建立 Extension 來(lái)調(diào)用 delegate:

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

上面的代碼處理了使用者取消選取圖像的動(dòng)作,同時(shí)也指派了 UIImagePickerControllerDelegate 的類別方法到我們的 Swift 檔案中∈的担現(xiàn)在陌僵,你的代碼會(huì)如同下面所示:

import UIKit
 
class ViewController: UIViewController, UINavigationControllerDelegate {
    
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var classifier: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
 
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    @IBAction func camera(_ sender: Any) {
        
        if !UIImagePickerController.isSourceTypeAvailable(.camera) {
            return
        }
        
        let cameraPicker = UIImagePickerController()
        cameraPicker.delegate = self
        cameraPicker.sourceType = .camera
        cameraPicker.allowsEditing = false
        
        present(cameraPicker, animated: true)
    }
    
    @IBAction func openLibrary(_ sender: Any) {
        let picker = UIImagePickerController()
        picker.allowsEditing = false
        picker.delegate = self
        picker.sourceType = .photoLibrary
        present(picker, animated: true)
    }
 
}
 
extension ViewController: UIImagePickerControllerDelegate {
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        dismiss(animated: true, completion: nil)
    }
}

現(xiàn)在回頭確認(rèn)一下 Storyboard 上的 UI 元件是否有與 Outlet 辨識(shí)及 Action 方法確實(shí)連結(jié)。

為了使用手機(jī)上的相機(jī)以及相簿创坞,還有一項(xiàng)必需要做的事碗短。前往 Info.plist 然后新增 Privacy – Camera Usage DescriptionPrivacy – Photo Library Usage Description。從 iOS 10 開始题涨,你需要添注說(shuō)明為何你的 App 需要使用相機(jī)及相簿功能偎谁。

coreml-plist-privacy

好了总滩,現(xiàn)在你已經(jīng)準(zhǔn)備好前往本篇教學(xué)的核心部分了。再次提醒巡雨,如果你不想重頭建立示例 App 的話闰渔,可以下載此份檔案

整合 Core ML Data 模型

現(xiàn)在讓我們轉(zhuǎn)換一下開始整合 Core ML 資料模型到我們的 App鸯隅。如同早先提到的澜建,我們需要一份預(yù)先訓(xùn)練的資料模型來(lái)與 Core ML 合作。雖然你也可以自己建立一份資料模型蝌以,但在本次示例里我們會(huì)使用由 Apple 開發(fā)者網(wǎng)站所提供預(yù)先訓(xùn)練完畢的資料模型。

前往 Apple 開發(fā)者網(wǎng)站的 Machine Learning 頁(yè)面然后拉到最底下何之,你會(huì)找到四個(gè)已預(yù)先訓(xùn)練好的 Core ML 資料模型跟畅。

coreml-pretrained-model

在這里,我們使用了 Inception v3 模型溶推。當(dāng)然徊件,你也可以程式其他另外三種的資料模型。當(dāng)你下載完 Inception v3 后蒜危,將它放入 Xcode 項(xiàng)目中虱痕,然后看一下他顯示了哪些東西。

Core ML Inception v3 model

注:請(qǐng)確認(rèn)已選擇了項(xiàng)目的 Target Membership辐赞,否則你的 App 將無(wú)法存取檔案部翘。

從上面的畫面中,你可以看到資料模型的類型也就是神經(jīng)網(wǎng)絡(luò)(Neural Networks)的分類器响委。其他你需要注意的資訊有模型評(píng)估參數(shù)(Model Evaluation Parameters)新思,這告訴你模型放入的是什么,輸出的又是什么赘风。以這來(lái)說(shuō)夹囚,這個(gè)模型可以放入一張 299×299 的圖像,然后回傳給你這張圖像最有可能的分類以及每種分類的可能性邀窃。

另外一個(gè)你會(huì)注意到的是模型的類別(Model Class)荸哟。這個(gè)模型類別(Inceptionv3)是由機(jī)器學(xué)習(xí)模型中產(chǎn)生出來(lái)并且可以讓我們直接在代碼里使用。如果點(diǎn)擊 Inceptionv3 旁的箭頭瞬捕,你可以看到這個(gè)類別的原始碼鞍历。

inceptionv3-class

現(xiàn)在,讓我們把資料模型加入至我們的代碼中吧山析⊙吡牵回到 ViewController.swift,將 CoreML 引入:

import CoreML

接著笋轨,為 Inceptionv3 宣告一個(gè) model 變數(shù)并且在 viewWillAppear() 中初始化秆剪。

var model: Inceptionv3!
 
override func viewWillAppear(_ animated: Bool) {
    model = Inceptionv3()
}

我知道你現(xiàn)在在想什么赊淑。

「為何我們不更早一點(diǎn)初始化呢?」

「在 viewWillAppear 中定義的要點(diǎn)是什么?」

這要點(diǎn)是當(dāng)你的 App 試著識(shí)別你的圖像里有哪些物件時(shí)仅讽,會(huì)快上許多陶缺。

現(xiàn)在,回頭看一下 Inceptionv3.mlmodel洁灵,我們看到這個(gè)模型只能放入尺寸為 299x299 的圖像饱岸。所以,我們?cè)撊绾巫屢粡垐D像符合這樣的尺寸呢徽千?這就是我們接下來(lái)要做的苫费。

圖像轉(zhuǎn)換

ViewController.swift 的 Extension 中,添加下述的代碼双抽。在新增的代碼里百框,我們實(shí)作了 imagePickerController(_:didFinishPickingMediaWithInfo) 來(lái)處理選取完照片的后續(xù)動(dòng)作。

extension ViewController: UIImagePickerControllerDelegate {
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        dismiss(animated: true, completion: nil)
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        picker.dismiss(animated: true)
        classifier.text = "Analyzing Image..."
        guard let image = info["UIImagePickerControllerOriginalImage"] as? UIImage else {
            return
        } 
        
        UIGraphicsBeginImageContextWithOptions(CGSize(width: 299, height: 299), true, 2.0)
        image.draw(in: CGRect(x: 0, y: 0, width: 299, height: 299))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        
        let attrs = [kCVPixelBufferCGImageCompatibilityKey: kCFBooleanTrue, kCVPixelBufferCGBitmapContextCompatibilityKey: kCFBooleanTrue] as CFDictionary
        var pixelBuffer : CVPixelBuffer?
        let status = CVPixelBufferCreate(kCFAllocatorDefault, Int(newImage.size.width), Int(newImage.size.height), kCVPixelFormatType_32ARGB, attrs, &pixelBuffer)
        guard (status == kCVReturnSuccess) else {
            return
        } 
        
        CVPixelBufferLockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
        let pixelData = CVPixelBufferGetBaseAddress(pixelBuffer!)
        
        let rgbColorSpace = CGColorSpaceCreateDeviceRGB()
        let context = CGContext(data: pixelData, width: Int(newImage.size.width), height: Int(newImage.size.height), bitsPerComponent: 8, bytesPerRow: CVPixelBufferGetBytesPerRow(pixelBuffer!), space: rgbColorSpace, bitmapInfo: CGImageAlphaInfo.noneSkipFirst.rawValue) //3
        
        context?.translateBy(x: 0, y: newImage.size.height)
        context?.scaleBy(x: 1.0, y: -1.0)
        
        UIGraphicsPushContext(context!)
        newImage.draw(in: CGRect(x: 0, y: 0, width: newImage.size.width, height: newImage.size.height))
        UIGraphicsPopContext()
        CVPixelBufferUnlockBaseAddress(pixelBuffer!, CVPixelBufferLockFlags(rawValue: 0))
        imageView.image = newImage
    }
}

在上述代碼中被標(biāo)記起來(lái)的部分:

  1. 第 7-11 行: 我們從 info 這個(gè) Dictionary (使用 UIImagePickerControllerOriginalImage 這個(gè) key)里取回了選取的的圖像牍汹。同時(shí)我們讓 UIImagePickerController 在我們選取圖像后消失铐维。
  2. 第 13-16 行: 因?yàn)槲覀兪褂玫哪P椭唤邮?299x299 的尺寸,所以將圖像轉(zhuǎn)換為正方形慎菲,并將這個(gè)新的正方形圖像指定給另個(gè)常數(shù) newImage嫁蛇。
  3. 第 18-23 行: 我們把 newImage 轉(zhuǎn)換為 CVPixelBuffer。 給對(duì)于 CVPixelBuffer 不熟悉的人露该, CVPixelBuffers 是一個(gè)將像數(shù)(Pixcel)存在主記憶體里的圖像緩沖器睬棚。你可以從這里了解更多關(guān)于 CVPixelBuffers 的資訊
  4. 第 31-32 行: 然后我們?nèi)〉昧诉@個(gè)圖像里的像數(shù)并轉(zhuǎn)換為設(shè)備的 RGB 色彩。接著把這些資料作成 CGContext有决。這樣一來(lái)每當(dāng)我們需要渲染(或是改變)一些底層屬性時(shí)可以很輕易的呼叫使用闸拿。最后的兩行代碼即是以此進(jìn)行翻轉(zhuǎn)以及縮放。
  5. 第 34-38 行: 最后书幕,我們完成新圖像的繪製并把舊的資料移除新荤,然后將 newImage 指定給 imageView.image

如果你有點(diǎn)不明白上面的代碼台汇,別擔(dān)心苛骨。這些是有點(diǎn)進(jìn)階的 Core Image 語(yǔ)法,并不在這次教學(xué)范圍內(nèi)苟呐。你只要明白這些是要將選取的圖像轉(zhuǎn)換為資料模型可以接受的資料即可痒芝。不過(guò)推薦你可以換個(gè)數(shù)值執(zhí)行幾次,看看執(zhí)行結(jié)果以更進(jìn)一步的了解牵素。

使用 Core ML

無(wú)論如何严衬,讓我們把注意力拉回到 Core ML 上吧。我們使用 Inceptionv3 模型來(lái)作物件識(shí)別笆呆。藉由 Core ML请琳,我們只需幾行代碼就可以完成工作了粱挡。貼上下述的代碼到 imageView.image = newImage 底下吧。

guard let prediction = try? model.prediction(image: pixelBuffer!) else {
    return
}
 
classifier.text = "I think this is a \(prediction.classLabel)."

沒(méi)錯(cuò)俄精,就是這樣询筏!Inceptionv3 類別已經(jīng)產(chǎn)生了名為 prediction(image:) 的方法,它被用來(lái)預(yù)測(cè)所提供的圖像裡的物件竖慧。這裡我們把 pixelBuffer 變數(shù)放入方法中嫌套,這個(gè)變數(shù)代表的是縮放后的圖像。一旦完成預(yù)測(cè)會(huì)以字串形式回傳結(jié)果圾旨,我們把 classifier 的文字內(nèi)容更新為收到的結(jié)果文字踱讨。

是時(shí)候來(lái)測(cè)試我們的 App 蘿!在模擬器或上手機(jī)上(需安裝 iOS 11)Build 及 Run 砍的,接著從相簿選取或相機(jī)拍攝圖像勇蝙,App 就會(huì)告訴你圖像是什么。

coreml-successful-case

當(dāng)測(cè)試 App 時(shí)挨约,你可能注意到 App 并不能很正確的預(yù)測(cè)出內(nèi)容。這并不是你的代碼有問(wèn)題产雹,而是出在這份資料模型上诫惭。

coreml-failed-case

小結(jié)

我希望你現(xiàn)在了解了如何將 Core ML 整合至你的 App 之中。本篇只是介紹性的教學(xué)文章蔓挖,如果你對(duì)如何將其他的機(jī)器學(xué)習(xí)模型(如:Caffe夕土、Keras、SciKit)整合至 Core ML 模型感興趣的話瘟判,敬請(qǐng)鎖定我們 Core ML 系列的下篇教學(xué)文章怨绣。我將會(huì)講述如何將這些模型轉(zhuǎn)換至 Core ML 模型。

如果想了解整個(gè) Demo App 的話拷获,你可以到 GitHub 上下載完整項(xiàng)目篮撑。

如果想知道更多關(guān)于 Core ML 的資訊,你可以參考 Core ML 官方文件匆瓜∮浚或是參考 Apple 于 WWDC 2017 上關(guān)于 Core ML 的 Session 演講:

至此,你對(duì)于 Core ML 有任何的想法嗎驮吱?歡迎分享你的意見(jiàn)茧妒。

原文Introduction to Core ML: Building a Simple Image Recognition App

簡(jiǎn)寶玉寫作群日更打卡第 25 天

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市左冬,隨后出現(xiàn)的幾起案子桐筏,更是在濱河造成了極大的恐慌,老刑警劉巖拇砰,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梅忌,死亡現(xiàn)場(chǎng)離奇詭異狰腌,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)铸鹰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門癌别,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人蹋笼,你說(shuō)我怎么就攤上這事展姐。” “怎么了剖毯?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵圾笨,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我逊谋,道長(zhǎng)擂达,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任胶滋,我火速辦了婚禮板鬓,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘究恤。我一直安慰自己俭令,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布部宿。 她就那樣靜靜地躺著抄腔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪理张。 梳的紋絲不亂的頭發(fā)上赫蛇,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音雾叭,去河邊找鬼悟耘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛拷况,可吹牛的內(nèi)容都是我干的作煌。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼赚瘦,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼粟誓!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起起意,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤鹰服,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體悲酷,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡套菜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了设易。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片逗柴。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖顿肺,靈堂內(nèi)的尸體忽然破棺而出戏溺,到底是詐尸還是另有隱情,我是刑警寧澤屠尊,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布旷祸,位于F島的核電站,受9級(jí)特大地震影響讼昆,放射性物質(zhì)發(fā)生泄漏托享。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一浸赫、第九天 我趴在偏房一處隱蔽的房頂上張望闰围。 院中可真熱鬧,春花似錦既峡、人聲如沸辫诅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至么夫,卻和暖如春者冤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背档痪。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工涉枫, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人腐螟。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓愿汰,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親乐纸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子衬廷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355

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

  • 這是一篇譯文原文地址Introduction to Core ML: Building a Simple Imag...
    yydev閱讀 3,020評(píng)論 6 17
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件汽绢、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,105評(píng)論 4 62
  • 有病就吃藥吗跋,這好像已經(jīng)成為人們根深蒂固的一種觀念。有病就去醫(yī)院開藥,也是一般人的做法跌宛,但其實(shí)這存在幾個(gè)誤區(qū): 一是...
    好聽(tīng)的暖陽(yáng)閱讀 172評(píng)論 0 0
  • 無(wú)論何等微不足道的舉動(dòng)酗宋,只要日日?qǐng)?jiān)持,從中總會(huì)產(chǎn)生出某些類似觀念的東西來(lái)疆拘。--村上春樹 我們活得似乎永遠(yuǎn)不會(huì)死蜕猫,我...
    徐徐歸晚閱讀 352評(píng)論 0 0
  • 初三那會(huì),閨蜜y說(shuō)她認(rèn)識(shí)了一個(gè)叫h的朋友哎迄。她說(shuō)h的長(zhǎng)處很多回右, 畫畫寫作唱歌都會(huì)。 有一次芬失,我和...
    穆小閱讀 245評(píng)論 0 0