M

mxnet

Common Lisp interface to https://github.com/dmlc/mxnet

(in-package :cl-user)

(ql:quickload :mxnet-predict)

(ql:quickload :opticl)

;;; cd ~
;;; wget http://data.dmlc.ml/mxnet/models/imagenet/inception-bn.tar.gz
;;; tar xvzf inception-bn.tar.gz
;;; ls ~/model

(defvar *data-dir* "~/model")

(defun file-as-string (path)
  (with-open-file (s path)
    (let* ((len (file-length s))
           (data (make-string len)))
      (values data (read-sequence data s)))))

(defun file-as-bytes (path)
  (with-open-file (s path :element-type 'unsigned-byte)
    (let* ((len (file-length s))
           (data (make-array len :element-type 'unsigned-byte)))
      (values data (read-sequence data s)))))

(defvar *labels*
  (with-open-file (in (format nil "~A/synset.txt" *data-dir*))
    (loop for line = (read-line in nil nil) while line collect line)))

(defvar *json*
  (file-as-string (format nil "~A/Inception_BN-symbol.json" *data-dir*)))

(defvar *params*
  (file-as-bytes (format nil "~A/Inception_BN-0039.params" *data-dir*)))

(defvar *predictor*
  (mxpred:predictor *json* *params* '(("data" 1 3 224 224)) :dev-type :cpu))

(defun identify-image (png-file &optional (top 5))
  (let* ((image (opticl:coerce-image
         (opticl:resize-image (opticl:read-png-file png-file) 224 224)
         'opticl:rgb-image))
     (data (make-array (* 1 3 224 224) :element-type 'single-float
               :initial-contents (loop for c from 0 below 3
                        append (loop for i from c by 3 below (array-total-size image)
                              collect (- (row-major-aref image i) 128.0))))))
    (mxpred:forward *predictor* `(("data" ,data)))
    (subseq (sort (loop for prob in (mxpred:get-output *predictor*)
             for label in *labels*
             collect (cons prob label))
          #'> :key #'car)
        0 top)))

;;; wget http://pngimg.com/upload/cup_PNG2000.png

;; (identify-image "~/cup_PNG2000.png")

;; ((0.44806847 "n07930864 cup")
;;  (0.2880092 "n02823750 beer glass")
;;  (0.09610717 "n07920052 espresso")
;;  (0.036979508 "n02948072 candle, taper, wax light")
;;  (0.023760669 "n07584110 consomme"))

;;; wget http://pngimg.com/upload/small/car_wheel_PNG1079.png

;; (identify-image "~/car_wheel_PNG1079.png")

;; ((0.99627846 "n02974003 car wheel")
;;  (0.0010841467 "n03208938 disk brake, disc brake")
;;  (4.2866074e-4 "n04548280 wall clock")
;;  (3.3683694e-4 "n03777568 Model T")
;;  (1.7127325e-4 "n03065424 coil, spiral, volute, whorl, helix"))

;;; wget http://orig04.deviantart.net/758b/f/2014/068/6/c/elephant_5_png_by_clipartcotttage-d79kjov.png

;; (identify-image "~/elephant_5_png_by_clipartcotttage-d79kjov.png")

;; ((0.31204274 "n02504013 Indian elephant, Elephas maximus")
;;  (0.29726356 "n02504458 African elephant, Loxodonta africana")
;;  (0.11172767 "n01704323 triceratops")
;;  (0.1089943 "n01871265 tusker")
;;  (0.041385192 "n03146219 cuirass"))