Skip to content
This repository has been archived by the owner on Nov 17, 2023. It is now read-only.

[Clojure] enhance draw bounding box #14567

Merged
merged 4 commits into from
Apr 11, 2019
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
: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"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

[org.apache.mxnet.contrib.clojure/clojure-mxnet "1.5.0-SNAPSHOT"]]
:main ^:skip-aot infer.objectdetector-example
:profiles {:uberjar {:aot :all}})

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
(ns infer.objectdetector-example
(:require [org.apache.clojure-mxnet.context :as context]
[org.apache.clojure-mxnet.dtype :as dtype]
[org.apache.clojure-mxnet.image :as image]
[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.string :as string]
[clojure.tools.cli :refer [parse-opts]])
(:gen-class))
(:gen-class)
(:import (javax.imageio ImageIO)
(java.io File)))

(defn check-valid-dir
"Check that the input directory exists"
Expand Down Expand Up @@ -54,27 +56,30 @@
:validate [check-valid-dir "Input directory not found"]]
["-h" "--help"]])

(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))))
(mapv (fn [image-path result]
gigasquid marked this conversation as resolved.
Show resolved Hide resolved
(println "looking at image" image-path)
(println "result: " result)
(let [buf (ImageIO/read (new File image-path))
width (.getWidth buf)
height (.getHeight buf)
names (mapv :class result)
coords (mapv (fn [result]
(-> result
(update :x-min #(* width %))
(update :x-max #(* width %))
(update :y-min #(* height %))
(update :y-max #(* height %))))
result)
gigasquid marked this conversation as resolved.
Show resolved Hide resolved
new-img (-> (ImageIO/read (new File image-path))
(image/draw-bounding-box! coords
{:stroke 2
:names (mapv #(str (:class %) "-" (:prob %))
result)
:transparency 0.5
:font-size-mult 1.0}))]
(ImageIO/write new-img "jpg" (io/file output-dir (last (string/split image-path #"\/"))))))
gigasquid marked this conversation as resolved.
Show resolved Hide resolved
images results))

(defn detect-single-image
"Detect objects in a single image and print top-5 predictions"
Expand Down Expand Up @@ -109,7 +114,7 @@
(apply concat
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a concat here? Cant we use a doseq instead of for to force the lazy computation?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, but it's also used in the example test to verify the results.

(for [image-files image-file-batches]
(let [image-batch (infer/load-image-paths image-files)
topk 5
topk 5
res (infer/detect-objects-batch detector image-batch topk) ]
(process-results
image-files
Expand Down Expand Up @@ -143,5 +148,5 @@
(parse-opts args cli-options)]
(cond
(:help options) (println summary)
(some? errors) (println (join "\n" errors))
(some? errors) (println (string/join "\n" errors))
:else (run-detector options))))
2 changes: 1 addition & 1 deletion contrib/clojure-package/integration-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ lein install
# then run through the examples
EXAMPLES_HOME=${MXNET_HOME}/contrib/clojure-package/examples
# use AWK pattern for blacklisting
TEST_CASES=`find ${EXAMPLES_HOME} -name test | awk '!/dontselect1|cnn-text-classification|gan|neural-style|infer|pre-trained-models/'`
TEST_CASES=`find ${EXAMPLES_HOME} -name test | awk '!/dontselect1|cnn-text-classification|gan|neural-style|pre-trained-models/'`
for i in $TEST_CASES ; do
cd ${i} && lein test
done
26 changes: 13 additions & 13 deletions contrib/clojure-package/src/org/apache/clojure_mxnet/image.clj
Original file line number Diff line number Diff line change
Expand Up @@ -202,11 +202,11 @@
(Image/toImage input))

(s/def ::buffered-image #(instance? BufferedImage %))
(s/def ::xmin integer?)
(s/def ::xmax integer?)
(s/def ::ymin integer?)
(s/def ::ymax integer?)
(s/def ::coordinate (s/keys :req-un [::xmin ::xmax ::ymin ::ymax]))
(s/def ::x-min number?)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for improving this!

(s/def ::x-max number?)
(s/def ::y-min number?)
(s/def ::y-max number?)
(s/def ::coordinate (s/keys :req-un [::x-min ::x-max ::y-min ::y-max]))
(s/def ::coordinates (s/coll-of ::coordinate))
(s/def ::names (s/nilable (s/coll-of string?)))
(s/def ::stroke (s/and integer? pos?))
Expand All @@ -217,11 +217,11 @@

(defn- convert-coordinate
"Convert bounding box coordinate to Scala correct types."
[{:keys [xmin xmax ymin ymax]}]
{:xmin (int xmin)
:xmax (int xmax)
:ymin (int ymin)
:ymax (int ymax)})
[{:keys [x-min x-max y-min y-max]}]
{:xmin (int x-min)
:xmax (int x-max)
:ymin (int y-min)
:ymax (int y-max)})

(defn draw-bounding-box!
"Draw bounding boxes on `buffered-image` and Mutate the input image.
Expand All @@ -233,9 +233,9 @@
`transparency`: float in (0.0, 1.0) - Transparency of the bounding box
returns: Modified `buffered-image`
Ex:
(draw-bounding-box! img [{:xmin 0 :xmax 100 :ymin 0 :ymax 100}])
(draw-bounding-box! [{:xmin 190 :xmax 850 :ymin 50 :ymax 450}
{:xmin 200 :xmax 350 :ymin 440 :ymax 530}]
(draw-bounding-box! img [{:x-min 0 :x-max 100 :y-min 0 :y-max 100}])
(draw-bounding-box! [{:x-min 190 :x-max 850 :y-min 50 :y-max 450}
{:x-min 200 :x-max 350 :y-min 440 :y-max 530}]
{:stroke 2
:names [\"pug\" \"cookie\"]
:transparency 0.8
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
[org.apache.clojure-mxnet.ndarray :as ndarray]
[clojure.java.io :as io]
[clojure.test :refer :all])
(:import (javax.imageio ImageIO)))
(:import (javax.imageio ImageIO)
(java.io File)))

(def tmp-dir (System/getProperty "java.io.tmpdir"))
(def image-path (.getAbsolutePath (io/file tmp-dir "Pug-Cookie.jpg")))
Expand Down Expand Up @@ -76,4 +77,14 @@
(let [img-arr (image/read-image image-path)
resized-arr (image/resize-image img-arr 224 224)
new-img (image/to-image resized-arr)]
(is (= true (ImageIO/write new-img "png" (io/file tmp-dir "out.png"))))))
(is (true? (ImageIO/write new-img "png" (io/file tmp-dir "out.png"))))))
gigasquid marked this conversation as resolved.
Show resolved Hide resolved

(deftest test-draw-bounding-box!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you so much for adding this test!

(let [new-img (-> (ImageIO/read (new File image-path))
(image/draw-bounding-box! [{:x-min 190 :x-max 850 :y-min 50 :y-max 450}
{:x-min 200 :x-max 350 :y-min 440 :y-max 530}]
{:stroke 2
:names ["pug" "cookie"]
:transparency 0.8
:font-size-mult 2.0}))]
(is (true? (ImageIO/write new-img "png" (io/file tmp-dir "out.png"))))))
gigasquid marked this conversation as resolved.
Show resolved Hide resolved