Sử dụng MobileNet trong C# với EmguCV

deep-learning
tutorial

#1

Thông thường các neural network model được triển khai dễ dàng sử dụng python, tuy nhiên với các ứng dụng C#, việc này là chưa được dễ dàng cho lắm. Trong bài này, mình xin giới thiệu một phương pháp áp dụng mạng neural, cụ thể là MobileNet, vào trong ứng dụng C# với EmguCV.

1. Chuẩn bị

  • Trước hết, MobileNet là một mạng neural được đưa ra bởi Google và được thực hiện sử dụng bộ thư viện Tensorflow. Các bạn có thể tham khảo tutorial về phân biệt ảnh các loại hoa để có thể tạo ra một MobileNet retrained model.

  • Cài đặt Tensorflow.

    ***Lưu ý: hiện tại mình gặp lỗi khi build trên Windows 10 nên mình khuyên nên build ở Ubuntu, xử lý phần mạng neural trên Ubuntu sau đó lấy mạng đó sử dụng trong C#.

    Ta cần dùng tool graph_transforms của Tensorflow nên việc build from souce là cần thiết. Các bạn có thể tham khảo cách build from source ở đây.

    Nếu bạn đã cài đặt Tensorflow dùng pip install thì cũng không sao, hãy dừng trước bước Install the package, thay vì build file wheel, hãy chỉ build tool graph_transforms.

    bazel build tensorflow/tools/graph_transforms:transform_graph
  • Tạo một project C# và thêm thư viện EmguCV sử dụng Nuget Package Management. EmguCV là một .Net Wrapper cho OpenCV. Phiên bản mình sử dụng là 3.4.1 có package Dnn hỗ trợ việc sử dụng Deep neural network.

2. Sử dụng MobileNet

  • Biến đổi MobileNet model

    Để sử dụng được MobileNet trong Dnn EmguCV, ta phải thay đổi một chút cấu trúc của mạng. Giả sử ta có một mạng MobileNet sau retrain trong file retrained_mobilenet_1.0_128.pb, độ phân giải ảnh đầu vào là 128x128. Ta thực hiện 2 bước biến đổi sau:

    • Optimize_for_inference

      python ~/tensorflow/tensorflow/python/tools/optimize_for_inference.py \
      --input retrained_mobilenet_1.0_128.pb \
      --output opt_graph.pb \
      --frozen_graph True \
      --input_names input \
      --output_names final_result
      
    • Graph_transforms

      tensorflow/bazel-bin/tensorflow/tools/graph_transforms/transform_graph \
      --in_graph=opt_graph.pb \
      --out_graph=mobilenet_for_dnn.pb \
      --inputs=input \
      --outputs=final_result \
      --transforms="fold_constants remove_nodes(op=Squeeze) remove_nodes(op=PlaceholderWithDefault) strip_unused_nodes(type=float, shape=\"1,128,128,3\") sort_by_execution_order "
      

      Chú ý thay đổi thông số shape cho đúng với độ phân giải ảnh đầu vào của mạng.

  • Sử dụng model trong C#

    • Khai báo sử dụng package

      using Emgu.CV.Dnn;
      
    • Read the model

      Net mobile_net = DnnInvoke.ReadNetFromTensorflow("mobilenet_for_dnn.pb");
      
    • Đọc các nhãn

      List<string> labels = new List<string>();
      using (System.IO.StreamReader fr = new System.IO.StreamReader("labels.txt"))
      {
        string line = "";
        while ((line = fr.ReadLine()) != null)
        {
          labels.Add(line);
        }
      }
      //"label.txt" contains labels for all classes in the model.
      
    • Đọc ảnh đầu vào

      Mat m = new Mat("image_to_classify.jpg");
      Mat blob = DnnInvoke.BlobFromImage(m, 1, new Size(128, 128));
      
    • Đưa ảnh vào mạng

      tensor_net.SetInput(blob, "input");
      Mat detection = tensor_net.Forward("final_result"); 
      
    • Lấy và phân tích dữ liệu ra

      byte[] data = new byte[116];
      detection.CopyTo(data);
      
      List<float> confidence = new List<float>();
      
      for (int i = 0; i < data.Length / 4; i++)
      {
        confidence.Add(BitConverter.ToSingle(data, i * 4));
      }
      //Đầu ra là một mảng byte chứa xác suất của tất cả class, mỗi xác suất 4 byte. 
      //Mạng của mình có 29 class, tương ứng có 4x29=116 byte.
      //BitConverter.ToSingle(data, i * 4) chuyển 4 byte sang float.
      
    • Kết quả dự đoán

      int maxIndex = confidence.IndexOf(confidence.Max());
      float sum = confidence.Sum(); // Chắc chắn tổng các xác suất bằng 1.0
      string prediction = labels[maxIndex];
      
  1. Kết quả

Dưới đây là kết quả.

Còn đây là ứng dụng nhận diện biến số mà mình áp dụng.

Đây là kết quả chạy trên CPU, nếu được xử lý trên GPU tốc độ ứng dụng theo mình nghĩ có thể chạy được ở thời gian thực.

Một vài chi tiết cụ thể hơn các bạn có thể xem trong repo Github của mình.

Vậy là ta có thể sử dụng model neural network trong C#. Chúc các bạn thành công.


Xây dựng mạng CNN với tensorflow và keras
Xây dựng mạng CNN với tensorflow và keras