Nhảy đến nội dung
Reader

Tự động trích xuất thông tin từ hình ảnh với API của FPT.AI

by content 15.01.2021

Trước khi tiến hành kết nối API, chúng ta cần lưu ý một số quy định về ảnh CMT/CCCD: Ảnh đầu vào phải đủ bốn góc rõ ràng, đầy đủ các bộ phận chính của một CMT như: Ảnh, quốc huy, thông tin cá nhân… Các trường thông tin phải rõ ràng, có thể đọc được bằng mắt thường, không tẩy xoá hay bị nhoè nước. Ảnh đầu vào không vượt quá 5 MB và độ phân giải tối thiểu khoảng 640×480 để đảm bảo tỉ lệ đọc chính xác. Tỉ lệ diện tích CMT hoặc CCCD phải chiếm tối thiểu ¼ tổng diện tích ảnh trở lên. 

Tiếp theo, chúng ta sẽ bắt tay vào thực hiện kết nối đến API OCR (Nhận diện CMT/CCCD). Để kết nối đến API OCR, chúng ta cần tạo một account trên Console.fpt.ai. Nếu chưa có tài khoản FPT.AI, hãy tạo mới ngay để tiến hành các bước tiếp theo. Sau đó tạo một API key để có thể gửi request tới gateway (mặc định mỗi API key tạo mới chỉ có thể gửi 50 requests).  

1. Backend

Việc đầu tiên để thực hiện kết nối đến API ở backend là khai báo thư viện. Chúng ta dùng các thư viện như ‘form-data’, ’node-fetch’. Ở đây ‘fetch’ là một simple interface giúp gửi/nhận API, ‘form-data’ là dữ liệu kiểu form giúp chúng ta gửi dữ liệu đi theo mẫu đã định. OCR

var FormData = require('form-data');

const fetch = require('node-fetch');

Tiếp theo, chúng ta cần khai báo dữ liệu theo biểu mẫu cho trước. Ở đây, dữ liệu tác giả sử dụng dưới dạng base64 nên cần truyền key ‘image_base64’ vào form data khai báo (req.body.data là dữ liệu của chứng minh thư với định dạng base64). 

OCR

let data = new FormData();

data.append('image_base64', req.body.data);

Sau khi đã khai báo form-data, chúng ta sẽ tiến hành call API bằng ‘fetch’ với method ‘Post’. Truyền API_key vào header, truyền data chúng ta vừa khai báo ở trên vào body. Để sử dụng API_key, bạn cần tạo một tài khoản trên Console, sau đó tạo một API_key để có thể gửi request tới gateway.

OCR

fetch('https://api.fpt.ai/vision/idr/vnm', {

    method: 'POST',

    headers: {

        'api_key': '******'

    },

    body: data

Cuối cùng là phần lấy kết quả trả về ‘resData’. Trong ví dụ này, chúng ta chỉ gửi và lấy thông tin của một chứng minh thư duy nhất. Vì vậy, chúng ta sẽ trả về phần tử đầu tiên trong dữ liệu trả về resData.data[0].

OCR

then(resData => {

    try {

        if (resData.data[0]) {

            res.json({message: "OK", data: resData.data[0]});

        } else {

            res.json({message: "Not OK"});

        }

    } catch (e) {

        res.json({message: e});

    }

})

Cuối cùng, dữ liệu trả về căn cước công dân mặt trước sẽ có dạng như sau: 

OCR

{

  "errorCode" : 0,

  "errorMessage" : "",

  "data": [

    {

      "id": "xxxx",

      "id_prob": "xxxx",

      "name": "xxxx",

      "name_prob": "xxxx",

      "dob": "xxxx",

      "dob_prob": "xxxx",

      "sex": "xxxx",

      "sex_prob": "xxxx",

      "nationality": "xxxx",

      "nationality_prob": "xxxx",

      "home": "xxxx",

      "home_prob": "xxxx",

      "address": "xxxx",

      "address_prob": "xxxx",

      "address_entities": {

            "province": "xxxx",

            "district": "xxxx",

            "ward": "xxxx",

            "street": "xxxx"

      },

      "doe": "xxxx",

      "doe_prob": "xxxx",

      "type": "xxxx"

    }

  ]

}

Còn đây là dữ liệu trả về căn cước công dân mặt sau:

OCR

{

  "errorCode" : 0,

  "errorMessage" : "",

  "data": [

    {

      "religion_prob": "xxxx",

      "religion": "xxxx",

      "ethnicity_prob": "xxxx",

      "ethnicity": "xxxx",

      "features": "xxxx",

      "features_prob": "xxxx",

      "issue_date": "xxxx",

      "issue_date_prob": "xxxx",

      "issue_loc_prob": "xxxx",

      "issue_loc": "xxxx",

      "type": "xxxx"

    }

  ]

Khi gặp lỗi, hệ thống sẽ trả về các messages rõ ràng và cụ thể nhằm chỉ thị cho users cách sử dụng API một cách chính xác nhất. Hệ thống sử dụng các error code như sau: 

  • Error Code – Không ý nghĩa. 
  • No error – Không có lỗi. 
  • Invalid Parameters or Values! – Sai thông số trong request (không có key hoặc ảnh trong request body). 
  • Failed in cropping – CMT trong ảnh bị thiếu góc nên không thể crop về dạng chuẩn. 
  • Unable to find ID card in the image – Hệ thống không tìm thấy CMT trong ảnh hoặc ảnh có chất lượng kém (quá mờ, quá tối/sáng). 
  • No URL in the request – Request sử dụng key image_url nhưng giá trị bỏ trống. 
  • Failed to open the URL! – Request sử dụng key image_url nhưng hệ thống không thể mở được URL này. 
  • Invalid image file – File gửi lên không phải là file ảnh. 
  • Bad data – File ảnh gửi lên bị hỏng hoặc format không được hỗ trợ. 
  • No string base64 in the request – Request sử dụng key image_base64 nhưng giá trị bỏ trống. 
  • String base64 is not valid – Request sử dụng key image_base64 nhưng string cung cấp không hợp lệ. 

Sau khi hoàn thành kết nối API OCR từ NodeJs, màn hình sẽ hiển thị:

OCR

const express = require('express');

const router = express.Router();

var FormData = require('form-data');

const fetch = require('node-fetch');

router.post('/', function (req, res, next) {

    try {

        let data = new FormData();

        data.append('image_base64', req.body.data);

        fetch('https://api.fpt.ai/vision/idr/vnm', {

            method: 'POST',

            headers: {

                'api_key': '******'

            },

            body: data

        })

            .then(response => response.json())

            .then(resData => {

                try {

                    if (resData.data[0]) {

                        res.json({message: "OK", data: resData.data[0]});

                    } else {

                        res.json({message: "Not OK"});

                    }

                } catch (e) {

                    res.json({message: e});

                }

            })

            .catch((e) => {

                res.json({message: e});

            });

    } catch (e) {

        res.json({message: e});

    }

});

module.exports = router;

Trong bài viết này, tác giả hướng dẫn chúng ta cách làm chi tiết để gọi đến API bằng NodeJs. Tuy nhiên, vẫn còn nhiều cách gọi API khác và bằng nhiều ngôn ngữ khác. Độc giả có thể tìm hiểu thêm tại đây.

2. Frontend

Sau khi đã kết nối hoàn chỉnh đến API OCR ở backend, tác giả sử dụng ReactJS để hiển thị thông tin lên website. Trước hết, chúng ta tạo các thông tin cần lấy từ API OCR trong state. 

OCR

constructor(props) {

  super(props);

  this.state = {

    id: '',

    id_prob: '',

    name: '',

    name_prob: '',

    dob: '',

    dob_prob: '',

    town: '',

    town_prob: '',

    address: '',

    address_prob: '',

Tiếp theo, chúng ta lấy thông tin từ backend và gán giá trị cho các thông tin đã define ở state. 

OCR

axios.post('/api/ocr', {

  data: values.image

})

  .then((response) => {

    this.hideLoader();

    if (response.data.message === "OK") {

      this.setState({

        id: data.id,

        name: data.name,

        dob: data.dob,

        town: data.home,

        address: data.address,

        id_prob: data.id_prob,

        name_prob: data.name_prob,

        dob_prob: data.dob_prob,

        town_prob: data.home_prob,

        address_prob: data.address_prob,

      })

    } else {

      this.toggleDanger();

    }

  })

  .catch((error) => {

    this.toggleDanger();

  });

Hiển thị giá trị lên website, ví dụ với trường thông tin name: 

OCR

Row>

  <Col className="was-validated text-center">

    <Input type="text" className="form-control-warning" name="name"

           onChange={this.handleChange}

           defaultValue={this.state.name}

           data-toggle="tooltip" data-placement="right"

           title={"OCR: " + this.state.name_prob + "%"}

           placeholder={strings.plc_name}

           required/>

  </Col>

</Row>

Kết quả thu được:

OCR        OCR

Chúng ta có thể hoàn toàn kết nối đến API OCR ngay từ ReactJs mà không cần thông qua NodeJs. Nhưng việc này sẽ để lộ endpoint và API_key nếu có người cố tình bắt network. Đối với những API có chứa thông tin quan trọng, tác giả khuyến nghị không nên gọi trực tiếp qua frontend. Cách gọi trực tiếp API bằng ReactJs: 

OCR

fetch('https://api.fpt.ai/vision/idr/vnm', {

  method: 'POST',

  headers: {

    'api_key': '***********'

  },

  body: data

})

  .then(resData => {

    if (resData.data[0]) {

      this.setState({

        id: data.id,

        name: data.name,

        dob: data.dob,

        town: data.home,

        address: data.address,

        id_prob: data.id_prob,

        name_prob: data.name_prob,

        dob_prob: data.dob_prob,

        town_prob: data.home_prob,

        address_prob: data.address_prob,

      })

    } else {

      this.toggleDanger();

    }

  })

FPT.AI là nền tảng Trí tuệ nhân tạo toàn diện cung cấp các giải pháp công nghệ tốt nhất cho doanh nghiệp. Đồng thời, FPT.AI cung cấp miễn phí các API có chất lượng cao như: FPT.AI Conversation, FPT.AI Reader, FPT.AI Speech cho phép các developers có thể dựa trên nguồn dữ liệu mà API cung cấp để phát triển ý tưởng của mình. Ứng dụng của FPT.AI có thể kể đến như trợ lý ảo, chatbot, tổng đài chăm sóc khách hàng, định danh khách hàng,… là chìa khóa giúp doanh nghiệp tự động hóa, tối ưu hóa vận hành, chăm sóc khách hàng và tăng cường hiệu quả kinh doanh. 

Trần Đức Long – FPT Head Office

_____________________________

? Trải nghiệm các sản phẩm khác của #FPT_AI tại: https://fpt.ai/vi

? Địa chỉ: Tầng 7, tháp FPT, số 10 Phạm Văn Bạch, quận Cầu Giấy, Tp. Hà Nội

☎ Hotline: 1900 638 399

? Email: [email protected]