Skip to content

Commit

Permalink
apache#13813 examples with opencv4/origami
Browse files Browse the repository at this point in the history
  • Loading branch information
hellonico committed Jan 13, 2019
1 parent 0e57930 commit e027290
Show file tree
Hide file tree
Showing 14 changed files with 201 additions and 177 deletions.
1 change: 1 addition & 0 deletions contrib/clojure-package/examples/gan/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ pom.xml.asc
/.nrepl-port
.hgignore
.hg/
results
7 changes: 4 additions & 3 deletions contrib/clojure-package/examples/gan/project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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-2"]
]
:main gan.gan-mnist)
:main gan.gan-mnist)
56 changes: 14 additions & 42 deletions contrib/clojure-package/examples/gan/src/gan/viz.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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}]
Expand All @@ -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")))))
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ pom.xml.asc
/.nrepl-port
.hgignore
.hg/
results
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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-2"]
[org.apache.mxnet.contrib.clojure/clojure-mxnet "1.5.0-SNAPSHOT"]]
:main ^:skip-aot infer.objectdetector-example
:profiles {:uberjar {:aot :all}})
Original file line number Diff line number Diff line change
@@ -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))))
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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
Expand All @@ -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"
Expand All @@ -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]
Expand Down
6 changes: 3 additions & 3 deletions contrib/clojure-package/examples/neural-style/project.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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-2"]]
:main neural-style.core)
Loading

0 comments on commit e027290

Please sign in to comment.