Sử dụng framework Vision để xử lý Text Detection trong iOS11

Giới thiệu

Vision là một trong những framework mới được giới thiệu trong phiên bản iOS11. Framework Vision cho phép lập trình viên dễ dàng sử dụng các kỹ thuật, thuật toán xử lý hinh ảnh trong ứng dụng của mình như phát hiện khuôn mặt, phát hiện các đặc điểm trên khuôn mặt (như mặt cười, nhíu mày...), phát hiện barcode, phát hiện và theo dõi đối tượng...

Trong bài viết này, chúng ta sẽ sử dụng framework Vision để xử lý phát hiện chữ viết, từng bước xây dựng một ứng dụng cho phép phát hiện ra chữ viết xuất hiện trong ảnh hoặc camera (không quan tâm tới font chữ, kích thước, chữ in, hay chữ viết tay).

Chuẩn bị

Trước khi đi vào chi tiết các bước, do framework Vision có trong iOS11 nên ta cần chuẩn bị các công cụ sau:

  • XCODE 9
  • Điện thoại hoặc thiết bị giả lập sử dụng iOS11

Xây dựng chương trình demo

Chương trình demo đơn giản như sau:

  • Lấy tín hiệu hình ảnh từ camera (hiển thị trên một Image View)
  • Đóng khung các vùng là chữ viết xuất hiện trên ImageView.

Thiết lập để lấy hình ảnh từ camera

Cấu hình project cho phép sử dụng Camera

Từ iOS10 ta cần phải cấu hình thêm info.plist trong project để sử dụng Camera trong ứng dụng, như hình dưới đây

Lấy tín hiệu từ camera hiển thị trên image view

Sử dụng framework AVFoundation để lấy dữ liệu từ camera, đoạn chương trình sau sẽ lấy tín hiệu từ camera để hiển thị trên ImageView

 var session = AVCaptureSession()
 func startLiveVideo() {
        // Thiết lập chế độ Video
        session.sessionPreset = AVCaptureSession.Preset.photo
        let captureDevice = AVCaptureDevice.default(for: AVMediaType.video)
        
        // Thiết lập cấu hình cho input và output của tín hiệu
        let deviceInput = try! AVCaptureDeviceInput(device: captureDevice!)
        let deviceOutput = AVCaptureVideoDataOutput()
        deviceOutput.videoSettings = [kCVPixelBufferPixelFormatTypeKey as String: Int(kCVPixelFormatType_32BGRA)]
        deviceOutput.setSampleBufferDelegate(self, queue: DispatchQueue.global(qos: DispatchQoS.QoSClass.default))
        session.addInput(deviceInput)
        session.addOutput(deviceOutput)
        
        // Thiết lập cho ImageView hiển thị
        let imageLayer = AVCaptureVideoPreviewLayer(session: session)
        imageLayer.frame = imageView.bounds
        imageView.layer.addSublayer(imageLayer)
        
        session.startRunning()
   }

Xử lý phát hiện Text từ tín hiệu camera

Để sử dụng chức năng Text Detection của framework Vision, ta cần phải thực hiện các bước sau:

  • Requests - đăng ký thuật toán sẽ sử dụng của Vison framework
  • Handlers - đăng ký xử lý sau khi gửi request xử lý
  • Observations - đăng ký xử lý khi thuật toán chạy và trả về kết quả

Giờ ta sẽ thực hiện chi tiết các bước trên

Khai báo sử dụng Text Detection

var requests = [VNRequest]()
func startTextDetection() {
    let textRequest = VNDetectTextRectanglesRequest(completionHandler: self.detectTextHandler)
    textRequest.reportCharacterBoxes = true
    self.requests = [textRequest]
}

Đoạn code trên sẽ cho phép phát hiện các vùng chữ nhật có chứa text bên trong nó. Khi qua request được đăng ký nó sẽ trả về kết quả thông qua hàm xử lý detectTextHandler

Xử lý sau khi request Text Detection

func detectTextHandler(request: VNRequest, error: Error?) {
        guard let observations = request.results else {
            print("no result")
            return
        }
        
        let result = observations.map({$0 as? VNTextObservation})
        
        DispatchQueue.main.async() {
            self.imageView.layer.sublayers?.removeSubrange(1...)
            for region in result {
                guard let rg = region else {
                    continue
                }
                
                // Xử lý highlight cho một từ
                self.highlightWord(box: rg)
                
                if let boxes = region?.characterBoxes {
                    for characterBox in boxes {
                        // Xử lý highligh cho một ký tự
                        self.highlightLetters(box: characterBox)
                    }
                }
            }
        }
    }
  • guard let observations = request.results sẽ chứa tất cả các kết quả của** VNDetectTextRectanglesRequest**
  • Duyệt qua các kết quả tìm được để highlight các vùng text đã phát hiện được thông qua hai hàm:
    • highlightWord
    • highlightLetters

Truyền dữ liệu từ camera tới detector

Ta sẽ implement delegate AVCaptureVideoDataOutputSampleBufferDelegate và gửi request tới Text Dectector mỗi khi có tín hiệu từ camera trong hàm này

extension ViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
            return
        }
        
        var requestOptions:[VNImageOption : Any] = [:]
        
        if let camData = CMGetAttachment(sampleBuffer, kCMSampleBufferAttachmentKey_CameraIntrinsicMatrix, nil) {
            requestOptions = [.cameraIntrinsics:camData]
        }
        
        let imageRequestHandler = VNImageRequestHandler(cvPixelBuffer: pixelBuffer, orientation: CGImagePropertyOrientation.right, options: requestOptions)
        
        do {
            try imageRequestHandler.perform(self.requests)
        } catch {
            print(error)
        }
    }
}

Chạy thử chương trình demo

Khi chạy thử đoạn chương trình trên ta sẽ có kết quả như hình dưới đây:

Kết luận

Vision framework thật sự là một công cụ mạnh mẽ và giúp việc áp dụng các thuật toán xử lý hình ảnh vào các ứng dụng trở nên nhanh chóng và đơn giản hơn rất nhiều. Ngoài việc sử dụng Text Detection ta còn có thể sử dụng các thuật toán phát hiện khác của Vision framework, hoặc có thể kết hợp hai framework VisionCore ML để triển khai các thuật toán phức tạp hơn và thông minh hơn.

Nguồn thao khảo và mã nguồn chương trình Demo.