You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mxnet.apache.org by cm...@apache.org on 2019/01/16 22:28:45 UTC

[incubator-mxnet] branch master updated: #13813 examples with opencv4/origami (#13813)

This is an automated email from the ASF dual-hosted git repository.

cmeier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-mxnet.git


The following commit(s) were added to refs/heads/master by this push:
     new 754ff76   #13813 examples with opencv4/origami (#13813)
754ff76 is described below

commit 754ff7669b4b3d481a80d734d79921e0c5d58bce
Author: Nicolas Modrzyk <he...@gmail.com>
AuthorDate: Thu Jan 17 07:28:25 2019 +0900

     #13813 examples with opencv4/origami (#13813)
---
 contrib/clojure-package/examples/gan/.gitignore    |   1 +
 contrib/clojure-package/examples/gan/project.clj   |   7 +-
 .../clojure-package/examples/gan/src/gan/viz.clj   |  56 +++------
 .../examples/infer/objectdetector/.gitignore       |   1 +
 .../examples/infer/objectdetector/README.md        |   3 +
 .../examples/infer/objectdetector/project.clj      |   3 +
 .../infer/objectdetector/src/infer/draw.clj        |  44 +++++++
 .../src/infer/objectdetector_example.clj           |  71 +++++++-----
 .../examples/neural-style/project.clj              |   6 +-
 .../neural-style/src/neural_style/core.clj         | 127 +++++++++------------
 .../neural-style/test/neural_style/vgg_19_test.clj |  11 +-
 .../examples/pre-trained-models/README.md          |  10 ++
 .../examples/pre-trained-models/project.clj        |   5 +-
 .../src/pre_trained_models/predict_image.clj       |  33 +++---
 14 files changed, 201 insertions(+), 177 deletions(-)

diff --git a/contrib/clojure-package/examples/gan/.gitignore b/contrib/clojure-package/examples/gan/.gitignore
index c53038e..ea80131 100644
--- a/contrib/clojure-package/examples/gan/.gitignore
+++ b/contrib/clojure-package/examples/gan/.gitignore
@@ -9,3 +9,4 @@ pom.xml.asc
 /.nrepl-port
 .hgignore
 .hg/
+results
\ No newline at end of file
diff --git a/contrib/clojure-package/examples/gan/project.clj b/contrib/clojure-package/examples/gan/project.clj
index a326f7a..4393987 100644
--- a/contrib/clojure-package/examples/gan/project.clj
+++ b/contrib/clojure-package/examples/gan/project.clj
@@ -15,11 +15,12 @@
 ;; limitations under the License.
 ;;
 
-(defproject gan "0.1.0-SNAPSHOT"
+(defproject gan-origami "0.1.0-SNAPSHOT"
   :description "GAN MNIST with MXNet"
   :plugins [[lein-cljfmt "0.5.7"]]
+  :repositories [["vendredi" {:url "https://repository.hellonico.info/repository/hellonico/"}]]
   :dependencies [[org.clojure/clojure "1.9.0"]
                  [org.apache.mxnet.contrib.clojure/clojure-mxnet "1.5.0-SNAPSHOT"]
-                 [org.openpnp/opencv "3.4.2-1"]
+                 [origami "4.0.0-3"]
                  ]
-  :main gan.gan-mnist)
+  :main gan.gan-mnist)
\ No newline at end of file
diff --git a/contrib/clojure-package/examples/gan/src/gan/viz.clj b/contrib/clojure-package/examples/gan/src/gan/viz.clj
index 67f7880..08da53c 100644
--- a/contrib/clojure-package/examples/gan/src/gan/viz.clj
+++ b/contrib/clojure-package/examples/gan/src/gan/viz.clj
@@ -18,14 +18,9 @@
 (ns gan.viz
   (:require [org.apache.clojure-mxnet.ndarray :as ndarray]
             [org.apache.clojure-mxnet.shape :as mx-shape]
-            [org.apache.clojure-mxnet.io :as mx-io])
-  (:import (nu.pattern OpenCV)
-           (org.opencv.core Core CvType Mat Size)
-           (org.opencv.imgproc Imgproc)
-           (org.opencv.imgcodecs Imgcodecs)))
-
-;;; Viz stuff
-(OpenCV/loadShared)
+            [org.apache.clojure-mxnet.io :as mx-io]
+            [opencv4.utils :as cvu]
+            [opencv4.core :as cv :refer [CV_8UC1 new-matofbyte flip! imwrite new-size hconcat! vconcat! new-mat merge!]]))
 
 (defn clip [x]
   (->> x
@@ -37,29 +32,11 @@
        (mapv #(.byteValue %))))
 
 (defn get-img [raw-data channels height width flip]
-  (let [totals (* height width)
-        img (if (> channels 1)
-              ;; rgb image
-              (let [[ra ga ba] (byte-array (partition totals raw-data))
-                    rr (new Mat height width (CvType/CV_8U))
-                    gg (new Mat height width (CvType/CV_8U))
-                    bb (new Mat height width (CvType/CV_8U))
-                    result (new Mat)]
-                (.put rr (int 0) (int 0) ra)
-                (.put gg (int 0) (int 0) ga)
-                (.put bb (int 0) (int 0) ba)
-                (Core/merge (java.util.ArrayList. [bb gg rr]) result)
-                result)
+  (let [img (if (> channels 1)
+              (throw (Exception. "Image with 3 channels (RGB) not supported"))
               ;; gray image
-              (let [result (new Mat height width (CvType/CV_8U))
-                    _ (.put result (int 0) (int 0) (byte-array raw-data))]
-                result))]
-    (do
-      (if flip
-        (let [result (new Mat)
-              _ (Core/flip img result (int 0))]
-          result)
-        img))))
+              (cv/>> (new-mat height width CV_8UC1) (byte-array raw-data)))]
+    (if flip (flip! img 0) img)))
 
 (defn im-sav [{:keys [title output-path x flip]
                :or {flip false} :as g-mod}]
@@ -73,15 +50,10 @@
         line-arrs (into [] (partition (* col c totals) raw-data))
         line-mats (mapv (fn [line]
                           (let [img-arr (into [] (partition (* c totals) line))
-                                col-mats (new Mat)
-                                src (mapv (fn [arr] (get-img (into [] arr) c h w flip)) img-arr)
-                                _ (Core/hconcat (java.util.ArrayList. src) col-mats)]
-                            col-mats))
-                        line-arrs)
-        result (new Mat)
-        resized-img (new Mat)
-        _ (Core/vconcat (java.util.ArrayList. line-mats) result)]
-    (do
-      (Imgproc/resize result resized-img (new Size (* (.width result) 1.5) (* (.height result) 1.5)))
-      (Imgcodecs/imwrite (str output-path title ".jpg") resized-img)
-      (Thread/sleep 1000))))
+                                src (mapv (fn [arr] (get-img (into [] arr) c h w flip)) img-arr)]
+                            (hconcat! src)))
+                        line-arrs)]
+    (-> line-mats
+        (vconcat!)
+        (cvu/resize-by 1.5)
+        (imwrite (str output-path title ".jpg")))))
\ No newline at end of file
diff --git a/contrib/clojure-package/examples/infer/objectdetector/.gitignore b/contrib/clojure-package/examples/infer/objectdetector/.gitignore
index 35491f1..a1f0468 100644
--- a/contrib/clojure-package/examples/infer/objectdetector/.gitignore
+++ b/contrib/clojure-package/examples/infer/objectdetector/.gitignore
@@ -10,3 +10,4 @@ pom.xml.asc
 /.nrepl-port
 .hgignore
 .hg/
+results
\ No newline at end of file
diff --git a/contrib/clojure-package/examples/infer/objectdetector/README.md b/contrib/clojure-package/examples/infer/objectdetector/README.md
index 921c53e..ec092a2 100644
--- a/contrib/clojure-package/examples/infer/objectdetector/README.md
+++ b/contrib/clojure-package/examples/infer/objectdetector/README.md
@@ -16,6 +16,9 @@ $ ./scripts/get_ssd_data.sh
 $
 $ lein run -- --help
 $ lein run -- -m models/resnet50_ssd/resnet50_ssd_model -i images/dog.jpg -d images/
+$ 
+$ # or the available lein alias
+$ lein run-detector
 $
 $ lein uberjar
 $ java -jar target/objectdetector-0.1.0-SNAPSHOT-standalone.jar --help
diff --git a/contrib/clojure-package/examples/infer/objectdetector/project.clj b/contrib/clojure-package/examples/infer/objectdetector/project.clj
index 4501f14..cdd9a89 100644
--- a/contrib/clojure-package/examples/infer/objectdetector/project.clj
+++ b/contrib/clojure-package/examples/infer/objectdetector/project.clj
@@ -17,9 +17,12 @@
 
 (defproject objectdetector "0.1.0-SNAPSHOT"
   :description "Object detection using infer with MXNet"
+  :repositories [["vendredi" "https://repository.hellonico.info/repository/hellonico/"]]
   :plugins [[lein-cljfmt "0.5.7"]]
+  :aliases {"run-detector" ["run" "--" "-m" "models/resnet50_ssd/resnet50_ssd_model" "-i" "images/dog.jpg" "-d" "images/"]}
   :dependencies [[org.clojure/clojure "1.9.0"]
                  [org.clojure/tools.cli "0.4.1"]
+                 [origami "4.0.0-3"]
                  [org.apache.mxnet.contrib.clojure/clojure-mxnet "1.5.0-SNAPSHOT"]]
   :main ^:skip-aot infer.objectdetector-example
   :profiles {:uberjar {:aot :all}})
diff --git a/contrib/clojure-package/examples/infer/objectdetector/src/infer/draw.clj b/contrib/clojure-package/examples/infer/objectdetector/src/infer/draw.clj
new file mode 100644
index 0000000..d29b34b
--- /dev/null
+++ b/contrib/clojure-package/examples/infer/objectdetector/src/infer/draw.clj
@@ -0,0 +1,44 @@
+;; Licensed to the Apache Software Foundation (ASF) under one or more
+;; contributor license agreements.  See the NOTICE file distributed with
+;; this work for additional information regarding copyright ownership.
+;; The ASF licenses this file to You under the Apache License, Version 2.0
+;; (the "License"); you may not use this file except in compliance with
+;; the License.  You may obtain a copy of the License at
+;;
+;;    http://www.apache.org/licenses/LICENSE-2.0
+;;
+;; Unless required by applicable law or agreed to in writing, software
+;; distributed under the License is distributed on an "AS IS" BASIS,
+;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+;; See the License for the specific language governing permissions and
+;; limitations under the License.
+;;
+
+(ns infer.draw
+  (:require
+   [opencv4.colors.rgb :as rgb]
+   [opencv4.core :refer [FONT_HERSHEY_PLAIN imread imwrite new-point put-text! rectangle]]))
+
+(defn black-boxes! [img results]
+  (doseq [{confidence :confidence label :label top-left :top-left bottom-right :bottom-right} results]
+    (let [w (.width img)
+          h (.height img)
+          top-left-p (new-point (int (* w (first top-left))) (int (* h (second top-left))))
+          bottom-right-p (new-point (int (* w (first bottom-right))) (int (* h (second bottom-right))))]
+      (if (< 15 confidence)
+        (do
+          (rectangle img top-left-p bottom-right-p rgb/white 1)
+          (put-text! img
+                     (str label "[" confidence "% ]")
+                     top-left-p
+                     FONT_HERSHEY_PLAIN
+                     1.0
+                     rgb/white 1)))))
+  img)
+
+(defn draw-bounds [image results output-dir]
+  (let [out-file (str output-dir "/" (.getName (clojure.java.io/as-file image)))]
+    (-> image
+        (imread)
+        (black-boxes! results)
+        (imwrite out-file))))
\ No newline at end of file
diff --git a/contrib/clojure-package/examples/infer/objectdetector/src/infer/objectdetector_example.clj b/contrib/clojure-package/examples/infer/objectdetector/src/infer/objectdetector_example.clj
index 5c30e5d..6010ddc 100644
--- a/contrib/clojure-package/examples/infer/objectdetector/src/infer/objectdetector_example.clj
+++ b/contrib/clojure-package/examples/infer/objectdetector/src/infer/objectdetector_example.clj
@@ -20,6 +20,7 @@
             [org.apache.clojure-mxnet.infer :as infer]
             [org.apache.clojure-mxnet.layout :as layout]
             [clojure.java.io :as io]
+            [infer.draw :as draw]
             [clojure.string :refer [join]]
             [clojure.tools.cli :refer [parse-opts]])
   (:gen-class))
@@ -45,37 +46,49 @@
    ["-i" "--input-image IMAGE" "Input image"
     :default "images/dog.jpg"
     :validate [check-valid-file "Input file not found"]]
+   ["-o" "--output-dir IMAGE_DIR" "Output directory. Defaults to results"
+    :default "results/"
+    :validate [check-valid-dir "Output directory not found"]]
    ["-d" "--input-dir IMAGE_DIR" "Input directory"
     :default "images/"
     :validate [check-valid-dir "Input directory not found"]]
    ["-h" "--help"]])
 
-(defn print-predictions
-  "Print image detector predictions for the given input file"
-  [predictions width height]
-  (println (apply str (repeat 80 "=")))
-  (doseq [{:keys [class prob x-min y-min x-max y-max]} predictions]
-    (println (format
-              "Class: %s Prob=%.5f Coords=(%.3f, %.3f, %.3f, %.3f)"
-              class
-              prob
-              (* x-min width)
-              (* y-min height)
-              (* x-max width)
-              (* y-max height))))
-  (println (apply str (repeat 80 "="))))
+(defn result->map [{:keys [class prob x-min y-min x-max y-max]}]
+  (hash-map
+   :label class
+   :confidence (int (* 100 prob))
+   :top-left [x-min y-min]
+   :bottom-right [x-max y-max]))
+
+(defn print-results [results]
+  (doseq [_r results]
+    (println (format "Class: %s Confidence=%s Coords=(%s, %s)"
+                     (_r :label)
+                     (_r :confidence)
+                     (_r :top-left)
+                     (_r :bottom-right)))))
+
+(defn process-results [images results output-dir]
+  (dotimes [i (count images)]
+    (let [image (nth images i) _results (map result->map (nth results i))]
+      (println "processing: " image)
+      (print-results _results)
+      (draw/draw-bounds image _results output-dir))))
 
 (defn detect-single-image
   "Detect objects in a single image and print top-5 predictions"
-  [detector input-image]
+  [detector input-image output-dir]
   (let [image (infer/load-image-from-file input-image)
-        topk 5
-        [predictions] (infer/detect-objects detector image topk)]
-    predictions))
+        topk 5]
+    (process-results
+     [input-image]
+     (infer/detect-objects detector image topk)
+     output-dir)))
 
 (defn detect-images-in-dir
   "Detect objects in all jpg images in the directory"
-  [detector input-dir]
+  [detector input-dir output-dir]
   (let [batch-size 20
         image-file-batches (->> input-dir
                                 io/file
@@ -84,15 +97,18 @@
                                 (filter #(re-matches #".*\.jpg$" (.getPath %)))
                                 (mapv #(.getPath %))
                                 (partition-all batch-size))]
-    (apply concat (for [image-files image-file-batches]
-                    (let [image-batch (infer/load-image-paths image-files)
-                          topk 5]
-                      (infer/detect-objects-batch detector image-batch topk))))))
+    (doall
+     (for [image-files image-file-batches]
+       (let [image-batch (infer/load-image-paths image-files) topk 5]
+         (process-results
+          image-files
+          (infer/detect-objects-batch detector image-batch topk)
+          output-dir))))))
 
 (defn run-detector
   "Runs an image detector based on options provided"
   [options]
-  (let [{:keys [model-path-prefix input-image input-dir
+  (let [{:keys [model-path-prefix input-image input-dir output-dir
                 device device-id]} options
         width 512 height 512
         descriptors [{:name "data"
@@ -103,12 +119,11 @@
         detector (infer/create-object-detector
                   factory
                   {:contexts [(context/default-context)]})]
+    (println "Output results to:" output-dir ":" (.mkdir (io/file output-dir)))
     (println "Object detection on a single image")
-    (print-predictions (detect-single-image detector input-image) width height)
-    (println "\n")
+    (detect-single-image detector input-image output-dir)
     (println "Object detection on images in a directory")
-    (doseq [predictions (detect-images-in-dir detector input-dir)]
-      (print-predictions predictions width height))))
+    (detect-images-in-dir detector input-dir output-dir)))
 
 (defn -main
   [& args]
diff --git a/contrib/clojure-package/examples/neural-style/project.clj b/contrib/clojure-package/examples/neural-style/project.clj
index b6d29f7..2614a69 100644
--- a/contrib/clojure-package/examples/neural-style/project.clj
+++ b/contrib/clojure-package/examples/neural-style/project.clj
@@ -18,8 +18,8 @@
 (defproject neural-style "0.1.0-SNAPSHOT"
   :description "Neural Style Transfer with MXNet"
   :plugins [[lein-cljfmt "0.5.7"]]
+  :repositories [["vendredi" {:url "https://repository.hellonico.info/repository/hellonico/"}]]
   :dependencies [[org.clojure/clojure "1.9.0"]
                  [org.apache.mxnet.contrib.clojure/clojure-mxnet "1.5.0-SNAPSHOT"]
-                 [net.mikera/imagez "0.12.0"]
-                 [thinktopic/think.image "0.4.16"]]
-  :main neural-style.core)
+                 [origami "4.0.0-3"]]
+  :main neural-style.core)
\ No newline at end of file
diff --git a/contrib/clojure-package/examples/neural-style/src/neural_style/core.clj b/contrib/clojure-package/examples/neural-style/src/neural_style/core.clj
index ac1f537..aa4c447 100644
--- a/contrib/clojure-package/examples/neural-style/src/neural_style/core.clj
+++ b/contrib/clojure-package/examples/neural-style/src/neural_style/core.clj
@@ -26,9 +26,8 @@
             [org.apache.clojure-mxnet.symbol :as sym]
             [clojure.java.io :as io]
             [clojure.java.shell :refer [sh]]
-            [mikera.image.core :as img]
-            [mikera.image.filters :as img-filter]
-            [think.image.pixel :as pixel]
+            [opencv4.core :as cv]
+            [opencv4.utils :as cvu]
             [neural-style.model-vgg-19 :as model-vgg-19])
   (:gen-class));; An Implementation of the paper A Neural Algorithm of Artistic Style
  ;;by Leon A. Gatys, Alexander S. Ecker, and Matthias Bethge
@@ -41,63 +40,63 @@
 (def model-path "model/vgg19.params")
 (def max-long-edge 600) ;; resize the content image
 (def style-weight 1) ;; the weight for the style image
-(def content-weight 5) ;; the weight for the content image
-(def blur-radius 1) ;; the blur filter radius
+(def content-weight 3) ;; the weight for the content image
+(def blur-radius 5) ;; the blur filter radius
 (def output-dir "output")
 (def lr 10.0) ;; the learning rate
 (def tv-weight 0.01) ;; the magnitude on the tv loss
 (def num-epochs 1000)
-(def num-channels 3)
 
-(defn image->ndarray [simg]
-  (let [h (img/height simg)
-        w (img/width simg)
-        pixels (img/get-pixels simg)
-        ;; normalize the pixels for vgg19
-        rgb-pixels (reduce (fn [result pixel]
-                             (let [[rs gs bs] result
-                                   [r g b _] (pixel/unpack-pixel pixel)]
-                               [(conj rs (- r 123.68))
-                                (conj gs (- g 116.779))
-                                (conj bs (- b 103.939))]))
-                           [[] [] []]
-                           pixels)]
-    (println "The resized image is size " {:height h :width w})
-    (-> rgb-pixels
-        (flatten)
-        (ndarray/array [1 num-channels h w]))))
+;;;;
+; IMAGE MANIPULATION
+;;;;
+
+(defn image->ndarray 
+  "normalize the pixels for vgg19"
+  [simg]
+  (let [h (.height simg) w (.width simg)]
+    (println "The nd image size is:" {:height h :width w})
+    (-> simg 
+      (cv/convert-to! cv/CV_8SC3 0.5) 
+      (cv/add! (cv/new-scalar -103.939 -116.779 -123.68) ) 
+      (cvu/mat->flat-rgb-array)
+      (ndarray/array [1 (.channels simg) h w]))))
+
+(defn ndarray->image [img]
+  (let [nd (ndarray/->vec img)
+        [_ _ h w] (mx-shape/->vec (ndarray/shape img))
+        to-cv1 (fn [bytes h w] (cv/>> (cv/new-mat h w cv/CV_8S) (byte-array bytes)))
+        byte-arrays (reverse (partition (* h w) nd))
+        mats (map #(to-cv1 % h w) byte-arrays)]
+    (-> mats
+        (cv/merge! (cv/new-mat h w cv/CV_8SC3))
+        (cv/add! (cv/new-scalar 103.939 116.779 123.68))
+        (cv/convert-to! cv/CV_8UC3 2))))
 
 (defn preprocess-content-image [path short-edge]
-  (let [simg (img/load-image path)
-        _ (println "The content image is size " {:height (img/height simg) :width (img/width simg)})
-        factor (/ short-edge (img/width simg))
-        resized-img (img/resize simg (* (img/width simg) factor) (* (img/height simg) factor))
-        new-height (img/height resized-img)
-        new-width (img/width resized-img)]
-    (image->ndarray resized-img)))
+  (-> path 
+    (cv/imread)
+    (#(cvu/resize-by % (/ short-edge (.width %))))
+    (image->ndarray)))
 
 (defn preprocess-style-image [path shape-vec]
-  (let [[_ _ h w] shape-vec
-        simg (img/load-image path)
-        _ (println "The image is size " {:height (img/height simg) :width (img/width simg)})
-        resized-img (img/resize simg w h)]
-    (image->ndarray resized-img)))
+  (let [[_ _ h w] shape-vec]
+    (println "The style image is size " {:height h :width w})
+    (-> path 
+      (cv/imread)
+      (cv/resize! (cv/new-size w h))
+      (image->ndarray))))
 
-(defn postprocess-image [img]
-  (let [datas (ndarray/->vec img)
-        image-shape (mx-shape/->vec (ndarray/shape img))
-        spatial-size (* (get image-shape 2) (get image-shape 3))
-        [rs gs bs] (doall (partition spatial-size datas))
-        pixels  (mapv (fn [r g b]
-                        (pixel/pack-pixel
-                         (int (+ r 123.68))
-                         (int (+ g 116.779))
-                         (int (+ b 103.939))
-                         (int 255)))
-                      rs gs bs)
-        new-image (img/new-image (get image-shape 3) (get image-shape 2))
-        _  (img/set-pixels new-image (int-array pixels))]
-    new-image))
+(defn save-image [img filename radius blur?]
+  (println "Saving image:" filename)
+  (-> img 
+    (ndarray->image)
+    (#(if blur? (cv/blur! % (cv/new-size blur-radius blur-radius)) %))
+    (cv/imwrite filename)))
+
+;;;;
+; TRAINING
+;;;;
 
 (defn style-gram-symbol [input-size style]
   (let [[_ output-shape _] (sym/infer-shape style {:data [1 3 (first input-size) (second input-size)]})
@@ -125,27 +124,6 @@
         content-loss (sym/sum (sym/square (sym/- cvar content)))]
     {:style-loss (sym/group gram-loss) :content-loss content-loss}))
 
-(defn old-clip [v]
-  (mapv (fn [a] (cond
-                  (neg? a) 0
-                  (> a 255) 255
-                  :else a))
-        v))
-
-(defn clip [a]
-  (cond
-    (neg? a) 0
-    (> a 255) 255
-    :else a))
-
-(defn save-image [img filename radius blur?]
-  (let [filtered-image (if blur?
-                         ((img-filter/box-blur blur-radius blur-radius) (postprocess-image img))
-                         (postprocess-image img))]
-    (do
-      ;(img/show filtered-image) ;; Uncomment to have the image display 
-      (img/write filtered-image filename "png"))))
-
 (defn get-tv-grad-executor [img ctx tv-weight]
   (when (pos? tv-weight)
     (let [img-shape (mx-shape/->vec (ndarray/shape img))
@@ -163,7 +141,7 @@
       (sym/bind out ctx {"img" img "kernel" kernel}))))
 
 (defn train 
-  ([devs] (train devs 20)) 
+  ([devs] (train devs 30)) 
   ([devs n-epochs]
     (let [dev (first devs)
         content-np (preprocess-content-image content-image max-long-edge)
@@ -244,9 +222,8 @@
         (when (zero? (mod i 2))
           (save-image (ndarray/copy img) (str output-dir "/out_" i ".png") blur-radius true)))
       (ndarray/set old-img img))
-    ; (save-image (ndarray/copy img) (str output-dir "/final.png") 0 false)
-    ; (postprocess-image img)
-    )))
+    (save-image (ndarray/copy img) (str output-dir "/final.png") 0 false)
+    (ndarray->image img))))
 
 (defn -main [& args]
   ;;; Note this only works on cpu right now
diff --git a/contrib/clojure-package/examples/neural-style/test/neural_style/vgg_19_test.clj b/contrib/clojure-package/examples/neural-style/test/neural_style/vgg_19_test.clj
index a7c9786..83be4a8 100644
--- a/contrib/clojure-package/examples/neural-style/test/neural_style/vgg_19_test.clj
+++ b/contrib/clojure-package/examples/neural-style/test/neural_style/vgg_19_test.clj
@@ -18,7 +18,7 @@
 (ns neural-style.vgg-19-test
 	(:require 
 		[clojure.test :refer :all]
-		[mikera.image.core :as img]
+		[opencv4.core :as cv]
 		[clojure.java.io :as io]
 		[org.apache.clojure-mxnet.ndarray :as ndarray]
 		[org.apache.clojure-mxnet.context :as context]
@@ -26,9 +26,8 @@
 
 (defn pic-to-ndarray-vec[path]
 	(-> path 
-		img/load-image 
-	 	neural/image->ndarray
-	 	ndarray/->vec))
+		cv/imread
+	 	neural/image->ndarray))
 
 (defn last-modified-check[x]
 	(let [t (- (System/currentTimeMillis) (.lastModified x)) ]
@@ -48,6 +47,4 @@
 
 (deftest vgg-19-test
 	(neural/train [(context/cpu)] 3)
-    (is (not (nil? (latest-pic-to-ndarray-vec "output")))))
-; generated file different depending on the platform :/ 
-; (pic-to-ndarray-vec "test/ref_out_2.png"))))
\ No newline at end of file
+    (is (not (nil? (latest-pic-to-ndarray-vec "output")))))
\ No newline at end of file
diff --git a/contrib/clojure-package/examples/pre-trained-models/README.md b/contrib/clojure-package/examples/pre-trained-models/README.md
index 751109f..b0996da 100644
--- a/contrib/clojure-package/examples/pre-trained-models/README.md
+++ b/contrib/clojure-package/examples/pre-trained-models/README.md
@@ -13,6 +13,16 @@ The `predict-image.clj` file loads up the pre-trained resnet-152 model and uses
 
 *To use run download-reset-152.sh to get the model params and json *
 
+Run the example with the available leiningen alias:
+
+```
+$ lein predict-image
+#
+# or with your own image:
+#
+$ lein predict-image <url_or_path_to_image>
+```
+
 
 ## Fine Tune from pretrained models
 
diff --git a/contrib/clojure-package/examples/pre-trained-models/project.clj b/contrib/clojure-package/examples/pre-trained-models/project.clj
index 11e0025..e4f6939 100644
--- a/contrib/clojure-package/examples/pre-trained-models/project.clj
+++ b/contrib/clojure-package/examples/pre-trained-models/project.clj
@@ -18,8 +18,9 @@
 (defproject pre-trained-models "0.1.0-SNAPSHOT"
   :description "Example of using pre-trained models with MXNet"
   :plugins [[lein-cljfmt "0.5.7"]]
+  :repositories [["vendredi" {:url "https://repository.hellonico.info/repository/hellonico/"}]]
+  :aliases {"predict-image" ["run" "-m" "pre-trained-models.predict-image" ]}
   :dependencies [[org.clojure/clojure "1.9.0"]
                  [org.apache.mxnet.contrib.clojure/clojure-mxnet "1.5.0-SNAPSHOT"]
-                 [net.mikera/imagez "0.12.0"]
-                 [thinktopic/think.image "0.4.16"]]
+                 [origami "4.0.0-3"]]
   :main pre-trained-models.fine-tune)
diff --git a/contrib/clojure-package/examples/pre-trained-models/src/pre_trained_models/predict_image.clj b/contrib/clojure-package/examples/pre-trained-models/src/pre_trained_models/predict_image.clj
index 71202bc..4df641d 100644
--- a/contrib/clojure-package/examples/pre-trained-models/src/pre_trained_models/predict_image.clj
+++ b/contrib/clojure-package/examples/pre-trained-models/src/pre_trained_models/predict_image.clj
@@ -22,8 +22,8 @@
             [org.apache.clojure-mxnet.ndarray :as ndarray]
             [org.apache.clojure-mxnet.shape :as mx-shape]
             [org.apache.clojure-mxnet.symbol :as sym]
-            [mikera.image.core :as img]
-            [think.image.pixel :as pixel]))
+            [opencv4.core :as cv]
+            [opencv4.utils :as cvu]))
 
 ;; based on https://mxnet.incubator.apache.org/tutorials/python/predict_image.html
 
@@ -40,21 +40,13 @@
     (io/copy in out)))
 
 (defn get-image [url show?]
-  (let [fname "test-image.jpg"
-        _ (download url fname)
-        image (-> (img/load-image fname)
-                  (img/resize h w))
-        pixels (img/get-pixels image)
-        rgb-pixels (reduce (fn [result pixel]
-                             (let [[rs gs bs] result
-                                   [r g b _] (pixel/unpack-pixel pixel)]
-                               [(conj rs r) (conj gs g) (conj bs b)]))
-                           [[] [] []]
-                           pixels)]
-    (when show? (img/show image))
-    (-> rgb-pixels
-        (flatten)
-        (ndarray/array [1 num-channels h w]))))
+  (-> url
+      (cvu/mat-from-url)
+      (cv/resize! (cv/new-size h w))
+      (#(do (if show? (cvu/imshow %)) %))
+      (cv/convert-to! cv/CV_8SC3 0.5) 
+      (cvu/mat->flat-rgb-array)
+      (ndarray/array [1 num-channels h w])))
 
 (defn predict [img-url show?]
   (let [mod (m/load-checkpoint {:prefix (str model-dir "/resnet-152") :epoch 0})
@@ -90,6 +82,13 @@
         (ndarray/shape)
         (mx-shape/->vec))))
 
+(defn -main [& args]
+  (println 
+   (predict 
+    (or (first args)
+        "https://raw.githubusercontent.com/dmlc/web-data/master/mxnet/doc/tutorials/python/predict_image/cat.jpg" )
+        true)))
+
 (comment
 
   (predict "https://raw.githubusercontent.com/dmlc/web-data/master/mxnet/doc/tutorials/python/predict_image/cat.jpg" true)