From 488843ee575e02ebf752bdfdc8891e14490994ee Mon Sep 17 00:00:00 2001 From: gigasquid Date: Fri, 11 Jan 2019 14:24:57 -0500 Subject: [PATCH 01/11] change object detection prediction to be a map --- .../src/org/apache/clojure_mxnet/infer.clj | 36 +++++++++----- .../infer/objectdetector_test.clj | 49 +++++++++++++------ 2 files changed, 57 insertions(+), 28 deletions(-) diff --git a/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj b/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj index 224a39275dac..bc5090fbca13 100644 --- a/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj +++ b/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj @@ -103,6 +103,12 @@ (s/def ::nil-or-int (s/nilable int?)) +(defn- format-predictions [predictions] + (mapv (fn [[c p]] + (let [[prob xmin ymin xmax ymax] (mapv float p)] + {:class c :prob prob :x-min xmin :y-min ymin :x-max xmax :y-max ymax})) + predictions)) + (extend-protocol AClassifier WrappedClassifier (classify @@ -206,10 +212,12 @@ "Invalid object detector") (util/validate! ::image image "Invalid image") (util/validate! ::nil-or-int topk "Invalid top-K") - (util/coerce-return-recursive - (.imageObjectDetect (:object-detector wrapped-detector) - image - (util/->int-option topk))))) + (->> (.imageObjectDetect (:object-detector wrapped-detector) + image + (util/->int-option topk)) + (util/coerce-return-recursive) + (first) + (format-predictions)))) (detect-objects-batch ([wrapped-detector images] (detect-objects-batch wrapped-detector images nil)) @@ -217,10 +225,12 @@ (util/validate! ::wrapped-detector wrapped-detector "Invalid object detector") (util/validate! ::nil-or-int topk "Invalid top-K") - (util/coerce-return-recursive - (.imageBatchObjectDetect (:object-detector wrapped-detector) - images - (util/->int-option topk))))) + (->> (.imageBatchObjectDetect (:object-detector wrapped-detector) + images + (util/->int-option topk)) + (util/coerce-return-recursive) + (first) + (format-predictions)))) (detect-objects-with-ndarrays ([wrapped-detector input-arrays] (detect-objects-with-ndarrays wrapped-detector input-arrays nil)) @@ -230,10 +240,12 @@ (util/validate! ::vec-of-ndarrays input-arrays "Invalid inputs") (util/validate! ::nil-or-int topk "Invalid top-K") - (util/coerce-return-recursive - (.objectDetectWithNDArray (:object-detector wrapped-detector) - (util/vec->indexed-seq input-arrays) - (util/->int-option topk)))))) + (->> (.objectDetectWithNDArray (:object-detector wrapped-detector) + (util/vec->indexed-seq input-arrays) + (util/->int-option topk)) + (util/coerce-return-recursive) + (first) + (format-predictions))))) (defprotocol AInferenceFactory (create-predictor [factory] [factory opts]) diff --git a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/objectdetector_test.clj b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/objectdetector_test.clj index 3a0e3d30a1d9..91d4f0e75170 100644 --- a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/objectdetector_test.clj +++ b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/objectdetector_test.clj @@ -17,11 +17,13 @@ (ns org.apache.clojure-mxnet.infer.objectdetector-test (: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] [clojure.java.shell :refer [sh]] - [clojure.test :refer :all])) + [clojure.test :refer :all] + [org.apache.clojure-mxnet.ndarray :as ndarray])) (def model-dir "data/") (def model-path-prefix (str model-dir "resnet50_ssd/resnet50_ssd_model")) @@ -40,28 +42,43 @@ (deftest test-single-detection (let [detector (create-detector) image (infer/load-image-from-file "test/test-images/kitten.jpg") - [predictions-all] (infer/detect-objects detector image) - [predictions] (infer/detect-objects detector image 5)] + predictions-all (infer/detect-objects detector image) + predictions (infer/detect-objects detector image 5) + {:keys [class prob x-min x-max y-min y-max] :as pred} (first predictions)] (is (some? predictions)) (is (= 5 (count predictions))) (is (= 13 (count predictions-all))) - (is (every? #(= 2 (count %)) predictions)) - (is (every? #(string? (first %)) predictions)) - (is (every? #(= 5 (count (second %))) predictions)) - (is (every? #(< 0 (first (second %)) 1) predictions)) - (is (= "cat" (first (first predictions)))))) + (is (= "cat" class)) + (is (< 0.8 prob)) + (every? #(< 0 % 1) [x-min x-max y-min y-max]))) (deftest test-batch-detection (let [detector (create-detector) image-batch (infer/load-image-paths ["test/test-images/kitten.jpg" "test/test-images/Pug-Cookie.jpg"]) batch-predictions-all (infer/detect-objects-batch detector image-batch) - batch-predictions (infer/detect-objects-batch detector image-batch 5) - predictions (first batch-predictions)] - (is (some? batch-predictions)) - (is (= 13 (count (first batch-predictions-all)))) + predictions (infer/detect-objects-batch detector image-batch 5) + {:keys [class prob x-min x-max y-min y-max] :as pred} (first predictions)] + (is (some? predictions)) + (is (= 13 (count batch-predictions-all))) (is (= 5 (count predictions))) - (is (every? #(= 2 (count %)) predictions)) - (is (every? #(string? (first %)) predictions)) - (is (every? #(= 5 (count (second %))) predictions)) - (is (every? #(< 0 (first (second %)) 1) predictions)))) + (is (= "cat" class)) + (is (< 0.8 prob)) + (every? #(< 0 % 1) [x-min x-max y-min y-max]))) + +(deftest test-detection-with-ndarrays + (let [detector (create-detector) + image (-> (image/read-image "test/test-images/kitten.jpg" {:to-rbg true}) + (image/resize-image 512 512) + (ndarray/transpose) + (ndarray/expand-dims 0) + (ndarray/cast dtype/FLOAT32)) + predictions-all (infer/detect-objects-with-ndarrays detector [image]) + predictions (infer/detect-objects-with-ndarrays detector [image] 1) + {:keys [class prob x-min x-max y-min y-max] :as pred} (first predictions)] + (is (some? predictions-all)) + (is (= 1 (count predictions))) + (is (= "cat" class)) + (is (< 0.8 prob)) + (every? #(< 0 % 1) [x-min x-max y-min y-max]))) + From e8e55a90b11686219f260b7ef62e0792b5e79c2c Mon Sep 17 00:00:00 2001 From: gigasquid Date: Fri, 11 Jan 2019 16:00:20 -0500 Subject: [PATCH 02/11] change predictions to a map for image-classifiers --- .../src/org/apache/clojure_mxnet/infer.clj | 35 +++++++++++-------- .../infer/imageclassifier_test.clj | 34 ++++++------------ 2 files changed, 32 insertions(+), 37 deletions(-) diff --git a/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj b/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj index bc5090fbca13..801c717e8a95 100644 --- a/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj +++ b/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj @@ -103,12 +103,15 @@ (s/def ::nil-or-int (s/nilable int?)) -(defn- format-predictions [predictions] +(defn- format-detection-predictions [predictions] (mapv (fn [[c p]] (let [[prob xmin ymin xmax ymax] (mapv float p)] {:class c :prob prob :x-min xmin :y-min ymin :x-max xmax :y-max ymax})) predictions)) +(defn- format-classification-predictions [predictions] + (mapv (fn [[c p]] {:class c :prob p}) predictions)) + (extend-protocol AClassifier WrappedClassifier (classify @@ -181,11 +184,13 @@ (util/validate! ::image image "Invalid image") (util/validate! ::nil-or-int topk "Invalid top-K") (util/validate! ::dtype dtype "Invalid dtype") - (util/coerce-return-recursive - (.classifyImage (:image-classifier wrapped-image-classifier) - image - (util/->int-option topk) - dtype)))) + (-> (.classifyImage (:image-classifier wrapped-image-classifier) + image + (util/->int-option topk) + dtype) + (util/coerce-return-recursive) + (first) + (format-classification-predictions)))) (classify-image-batch ([wrapped-image-classifier images] (classify-image-batch wrapped-image-classifier images nil dtype/FLOAT32)) @@ -196,11 +201,13 @@ "Invalid classifier") (util/validate! ::nil-or-int topk "Invalid top-K") (util/validate! ::dtype dtype "Invalid dtype") - (util/coerce-return-recursive - (.classifyImageBatch (:image-classifier wrapped-image-classifier) - images - (util/->int-option topk) - dtype))))) + (-> (.classifyImageBatch (:image-classifier wrapped-image-classifier) + images + (util/->int-option topk) + dtype) + (util/coerce-return-recursive) + (first) + (format-classification-predictions))))) (extend-protocol AObjectDetector WrappedObjectDetector @@ -217,7 +224,7 @@ (util/->int-option topk)) (util/coerce-return-recursive) (first) - (format-predictions)))) + (format-detection-predictions)))) (detect-objects-batch ([wrapped-detector images] (detect-objects-batch wrapped-detector images nil)) @@ -230,7 +237,7 @@ (util/->int-option topk)) (util/coerce-return-recursive) (first) - (format-predictions)))) + (format-detection-predictions)))) (detect-objects-with-ndarrays ([wrapped-detector input-arrays] (detect-objects-with-ndarrays wrapped-detector input-arrays nil)) @@ -245,7 +252,7 @@ (util/->int-option topk)) (util/coerce-return-recursive) (first) - (format-predictions))))) + (format-detection-predictions))))) (defprotocol AInferenceFactory (create-predictor [factory] [factory opts]) diff --git a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/imageclassifier_test.clj b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/imageclassifier_test.clj index b459b06132b2..448a52fc7ab0 100644 --- a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/imageclassifier_test.clj +++ b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/imageclassifier_test.clj @@ -40,23 +40,15 @@ (deftest test-single-classification (let [classifier (create-classifier) image (infer/load-image-from-file "test/test-images/kitten.jpg") - [predictions-all] (infer/classify-image classifier image) - [predictions-with-default-dtype] (infer/classify-image classifier image 10) - [predictions] (infer/classify-image classifier image 5 dtype/FLOAT32)] + predictions-all (infer/classify-image classifier image) + predictions-with-default-dtype (infer/classify-image classifier image 10) + predictions (infer/classify-image classifier image 5 dtype/FLOAT32)] + predictions (is (= 1000 (count predictions-all))) (is (= 10 (count predictions-with-default-dtype))) - (is (some? predictions)) (is (= 5 (count predictions))) - (is (every? #(= 2 (count %)) predictions)) - (is (every? #(string? (first %)) predictions)) - (is (every? #(float? (second %)) predictions)) - (is (every? #(< 0 (second %) 1) predictions)) - (is (= ["n02123159 tiger cat" - "n02124075 Egyptian cat" - "n02123045 tabby, tabby cat" - "n02127052 lynx, catamount" - "n02128757 snow leopard, ounce, Panthera uncia"] - (map first predictions))))) + (is (= "n02123159 tiger cat" (:class (first predictions)))) + (is (= (< 0 (:prob (first predictions)) 1))))) (deftest test-batch-classification (let [classifier (create-classifier) @@ -64,13 +56,9 @@ "test/test-images/Pug-Cookie.jpg"]) batch-predictions-all (infer/classify-image-batch classifier image-batch) batch-predictions-with-default-dtype (infer/classify-image-batch classifier image-batch 10) - batch-predictions (infer/classify-image-batch classifier image-batch 5 dtype/FLOAT32) - predictions (first batch-predictions)] - (is (= 1000 (count (first batch-predictions-all)))) - (is (= 10 (count (first batch-predictions-with-default-dtype)))) - (is (some? batch-predictions)) + predictions (infer/classify-image-batch classifier image-batch 5 dtype/FLOAT32)] + (is (= 1000 (count batch-predictions-all))) + (is (= 10 (count batch-predictions-with-default-dtype))) (is (= 5 (count predictions))) - (is (every? #(= 2 (count %)) predictions)) - (is (every? #(string? (first %)) predictions)) - (is (every? #(float? (second %)) predictions)) - (is (every? #(< 0 (second %) 1) predictions)))) + (is (= "n02123159 tiger cat" (:class (first predictions)))) + (is (= (< 0 (:prob (first predictions)) 1))))) From 3ec28174192abf37893ea26f96ef83dc8c8d3e74 Mon Sep 17 00:00:00 2001 From: gigasquid Date: Fri, 11 Jan 2019 17:21:31 -0500 Subject: [PATCH 03/11] change return types of the classifiers to be a map - add tests for base classifier and with-ndarray as well --- .../src/org/apache/clojure_mxnet/infer.clj | 85 ++++++++++++------- .../infer/imageclassifier_test.clj | 65 ++++++++++++++ .../infer/objectdetector_test.clj | 10 +-- 3 files changed, 123 insertions(+), 37 deletions(-) diff --git a/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj b/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj index 801c717e8a95..ced8f105b4b1 100644 --- a/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj +++ b/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj @@ -22,7 +22,8 @@ [org.apache.clojure-mxnet.io :as mx-io] [org.apache.clojure-mxnet.shape :as shape] [org.apache.clojure-mxnet.util :as util] - [clojure.spec.alpha :as s]) + [clojure.spec.alpha :as s] + [org.apache.clojure-mxnet.shape :as mx-shape]) (:import (java.awt.image BufferedImage) (org.apache.mxnet NDArray) (org.apache.mxnet.infer Classifier ImageClassifier @@ -39,15 +40,26 @@ (defrecord WrappedObjectDetector [object-detector]) (s/def ::ndarray #(instance? NDArray %)) -(s/def ::float-array (s/and #(.isArray (class %)) #(every? float? %))) -(s/def ::vec-of-float-arrays (s/coll-of ::float-array :kind vector?)) +(s/def ::number-array (s/coll-of number? :kind vector?)) +(s/def ::vvec-of-numbers (s/coll-of ::number-array :kind vector?)) (s/def ::vec-of-ndarrays (s/coll-of ::ndarray :kind vector?)) +(s/def ::image #(instance? BufferedImage %)) +(s/def ::batch-images (s/coll-of ::image :kind vector?)) (s/def ::wrapped-predictor (s/keys :req-un [::predictor])) (s/def ::wrapped-classifier (s/keys :req-un [::classifier])) (s/def ::wrapped-image-classifier (s/keys :req-un [::image-classifier])) (s/def ::wrapped-detector (s/keys :req-un [::object-detector])) +(defn- format-detection-predictions [predictions] + (mapv (fn [[c p]] + (let [[prob xmin ymin xmax ymax] (mapv float p)] + {:class c :prob prob :x-min xmin :y-min ymin :x-max xmax :y-max ymax})) + predictions)) + +(defn- format-classification-predictions [predictions] + (mapv (fn [[c p]] {:class c :prob p}) predictions)) + (defprotocol APredictor (predict [wrapped-predictor inputs]) (predict-with-ndarray [wrapped-predictor input-arrays])) @@ -103,15 +115,6 @@ (s/def ::nil-or-int (s/nilable int?)) -(defn- format-detection-predictions [predictions] - (mapv (fn [[c p]] - (let [[prob xmin ymin xmax ymax] (mapv float p)] - {:class c :prob prob :x-min xmin :y-min ymin :x-max xmax :y-max ymax})) - predictions)) - -(defn- format-classification-predictions [predictions] - (mapv (fn [[c p]] {:class c :prob p}) predictions)) - (extend-protocol AClassifier WrappedClassifier (classify @@ -120,13 +123,14 @@ ([wrapped-classifier inputs topk] (util/validate! ::wrapped-classifier wrapped-classifier "Invalid classifier") - (util/validate! ::vec-of-float-arrays inputs + (util/validate! ::vvec-of-numbers inputs "Invalid inputs") (util/validate! ::nil-or-int topk "Invalid top-K") - (util/coerce-return-recursive - (.classify (:classifier wrapped-classifier) - (util/vec->indexed-seq inputs) - (util/->int-option topk))))) + (-> (.classify (:classifier wrapped-classifier) + (util/vec->indexed-seq [(float-array (first inputs))]) + (util/->int-option topk)) + (util/coerce-return-recursive) + (format-classification-predictions)))) (classify-with-ndarray ([wrapped-classifier inputs] (classify-with-ndarray wrapped-classifier inputs nil)) @@ -136,10 +140,13 @@ (util/validate! ::vec-of-ndarrays inputs "Invalid inputs") (util/validate! ::nil-or-int topk "Invalid top-K") - (util/coerce-return-recursive + (-> (.classifyWithNDArray (:classifier wrapped-classifier) (util/vec->indexed-seq inputs) - (util/->int-option topk))))) + (util/->int-option topk)) + (util/coerce-return-recursive) + (first) + (format-classification-predictions)))) WrappedImageClassifier (classify ([wrapped-image-classifier inputs] @@ -147,13 +154,14 @@ ([wrapped-image-classifier inputs topk] (util/validate! ::wrapped-image-classifier wrapped-image-classifier "Invalid classifier") - (util/validate! ::vec-of-float-arrays inputs + (util/validate! ::vvec-of-numbers inputs "Invalid inputs") (util/validate! ::nil-or-int topk "Invalid top-K") - (util/coerce-return-recursive - (.classify (:image-classifier wrapped-image-classifier) - (util/vec->indexed-seq inputs) - (util/->int-option topk))))) + (-> (.classify (:image-classifier wrapped-image-classifier) + (util/vec->indexed-seq [(float-array (first inputs))]) + (util/->int-option topk)) + (util/coerce-return-recursive) + (format-classification-predictions)))) (classify-with-ndarray ([wrapped-image-classifier inputs] (classify-with-ndarray wrapped-image-classifier inputs nil)) @@ -163,10 +171,12 @@ (util/validate! ::vec-of-ndarrays inputs "Invalid inputs") (util/validate! ::nil-or-int topk "Invalid top-K") - (util/coerce-return-recursive - (.classifyWithNDArray (:image-classifier wrapped-image-classifier) - (util/vec->indexed-seq inputs) - (util/->int-option topk)))))) + (-> (.classifyWithNDArray (:image-classifier wrapped-image-classifier) + (util/vec->indexed-seq inputs) + (util/->int-option topk)) + (util/coerce-return-recursive) + (first) + (format-classification-predictions))))) (s/def ::image #(instance? BufferedImage %)) (s/def ::dtype #{dtype/UINT8 dtype/INT32 dtype/FLOAT16 dtype/FLOAT32 dtype/FLOAT64}) @@ -199,10 +209,11 @@ ([wrapped-image-classifier images topk dtype] (util/validate! ::wrapped-image-classifier wrapped-image-classifier "Invalid classifier") + (util/validate! ::batch-images images "Invalid Batch Images") (util/validate! ::nil-or-int topk "Invalid top-K") (util/validate! ::dtype dtype "Invalid dtype") (-> (.classifyImageBatch (:image-classifier wrapped-image-classifier) - images + (util/vec->indexed-seq images) (util/->int-option topk) dtype) (util/coerce-return-recursive) @@ -232,8 +243,9 @@ (util/validate! ::wrapped-detector wrapped-detector "Invalid object detector") (util/validate! ::nil-or-int topk "Invalid top-K") + (util/validate! ::batch-images images "Invalid Batch Images") (->> (.imageBatchObjectDetect (:object-detector wrapped-detector) - images + (util/vec->indexed-seq images) (util/->int-option topk)) (util/coerce-return-recursive) (first) @@ -361,4 +373,15 @@ "Loads images from a list of file names" [image-paths] (util/validate! ::image-paths image-paths "Invalid image paths") - (ImageClassifier/loadInputBatch (util/convert-vector image-paths))) + (util/scala-vector->vec + (ImageClassifier/loadInputBatch (util/convert-vector image-paths)))) + +(defn reshape-image + "Reshapes a buffered image" + [buffered-image width height] + (ImageClassifier/reshapeImage buffered-image (int width) (int height))) + +(defn buffered-image-to-pixels + "Turns the buffered image into a ndarray allowing to specify shape and type" + [buffered-image shape-vec dtype] + (ImageClassifier/bufferedImageToPixels buffered-image (mx-shape/->shape shape-vec) dtype)) diff --git a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/imageclassifier_test.clj b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/imageclassifier_test.clj index 448a52fc7ab0..567ebc07f3cc 100644 --- a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/imageclassifier_test.clj +++ b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/imageclassifier_test.clj @@ -19,6 +19,7 @@ [org.apache.clojure-mxnet.dtype :as dtype] [org.apache.clojure-mxnet.infer :as infer] [org.apache.clojure-mxnet.layout :as layout] + [org.apache.clojure-mxnet.ndarray :as ndarray] [clojure.java.io :as io] [clojure.java.shell :refer [sh]] [clojure.test :refer :all])) @@ -62,3 +63,67 @@ (is (= 5 (count predictions))) (is (= "n02123159 tiger cat" (:class (first predictions)))) (is (= (< 0 (:prob (first predictions)) 1))))) + +(deftest test-single-classification-with-ndarray + (let [classifier (create-classifier) + image (-> (infer/load-image-from-file "test/test-images/kitten.jpg") + (infer/reshape-image 224 224) + (infer/buffered-image-to-pixels [3 224 224] dtype/FLOAT32) + (ndarray/expand-dims 0)) + predictions-all (infer/classify-with-ndarray classifier [image]) + predictions (infer/classify-with-ndarray classifier [image] 5)] + (is (= 1000 (count predictions-all))) + (is (= 5 (count predictions))) + (is (= "n02123159 tiger cat" (:class (first predictions)))) + (is (= (< 0 (:prob (first predictions)) 1))))) + +(deftest test-single-classify + (let [classifier (create-classifier) + image (-> (infer/load-image-from-file "test/test-images/kitten.jpg") + (infer/reshape-image 224 224) + (infer/buffered-image-to-pixels [3 224 224] dtype/FLOAT32) + (ndarray/expand-dims 0)) + predictions-all (infer/classify classifier [(ndarray/->vec image)]) + predictions (infer/classify classifier [(ndarray/->vec image)] 5)] + (is (= 1000 (count predictions-all))) + (is (= 5 (count predictions))) + (is (= "n02123159 tiger cat" (:class (first predictions)))) + (is (= (< 0 (:prob (first predictions)) 1))))) + +(deftest test-base-classification-with-ndarray + (let [descriptors [{:name "data" + :shape [1 3 224 224] + :layout layout/NCHW + :dtype dtype/FLOAT32}] + factory (infer/model-factory model-path-prefix descriptors) + classifier (infer/create-classifier factory) + image (-> (infer/load-image-from-file "test/test-images/kitten.jpg") + (infer/reshape-image 224 224) + (infer/buffered-image-to-pixels [3 224 224] dtype/FLOAT32) + (ndarray/expand-dims 0)) + predictions-all (infer/classify-with-ndarray classifier [image]) + predictions (infer/classify-with-ndarray classifier [image] 5)] + (is (= 1000 (count predictions-all))) + (is (= 5 (count predictions))) + (is (= "n02123159 tiger cat" (:class (first predictions)))) + (is (= (< 0 (:prob (first predictions)) 1))))) + +(deftest test-base-single-classify + (let [descriptors [{:name "data" + :shape [1 3 224 224] + :layout layout/NCHW + :dtype dtype/FLOAT32}] + factory (infer/model-factory model-path-prefix descriptors) + classifier (infer/create-classifier factory) + image (-> (infer/load-image-from-file "test/test-images/kitten.jpg") + (infer/reshape-image 224 224) + (infer/buffered-image-to-pixels [3 224 224] dtype/FLOAT32) + (ndarray/expand-dims 0)) + predictions-all (infer/classify classifier [(ndarray/->vec image)]) + predictions (infer/classify classifier [(ndarray/->vec image)] 5)] + (is (= 1000 (count predictions-all))) + (is (= 5 (count predictions))) + (is (= "n02123159 tiger cat" (:class (first predictions)))) + (is (= (< 0 (:prob (first predictions)) 1))))) + + diff --git a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/objectdetector_test.clj b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/objectdetector_test.clj index 91d4f0e75170..76acbfc9d543 100644 --- a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/objectdetector_test.clj +++ b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/objectdetector_test.clj @@ -17,7 +17,6 @@ (ns org.apache.clojure-mxnet.infer.objectdetector-test (: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] @@ -68,11 +67,10 @@ (deftest test-detection-with-ndarrays (let [detector (create-detector) - image (-> (image/read-image "test/test-images/kitten.jpg" {:to-rbg true}) - (image/resize-image 512 512) - (ndarray/transpose) - (ndarray/expand-dims 0) - (ndarray/cast dtype/FLOAT32)) + image (-> (infer/load-image-from-file "test/test-images/kitten.jpg") + (infer/reshape-image 512 512) + (infer/buffered-image-to-pixels [3 512 512] dtype/FLOAT32) + (ndarray/expand-dims 0)) predictions-all (infer/detect-objects-with-ndarrays detector [image]) predictions (infer/detect-objects-with-ndarrays detector [image] 1) {:keys [class prob x-min x-max y-min y-max] :as pred} (first predictions)] From c265ab11a35c91c08029e6a089244ae8cbc058ba Mon Sep 17 00:00:00 2001 From: gigasquid Date: Fri, 11 Jan 2019 17:45:38 -0500 Subject: [PATCH 04/11] tweak return types and inputs for predict - add test for plain predict --- .../src/org/apache/clojure_mxnet/infer.clj | 37 ++++++++----------- .../clojure_mxnet/infer/predictor_test.clj | 21 ++++++++++- 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj b/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj index ced8f105b4b1..2dd7966a779b 100644 --- a/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj +++ b/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj @@ -99,19 +99,22 @@ [wrapped-predictor inputs] (util/validate! ::wrapped-predictor wrapped-predictor "Invalid predictor") - (util/validate! ::vec-of-float-arrays inputs + (util/validate! ::vvec-of-numbers inputs "Invalid inputs") - (util/coerce-return-recursive - (.predict (:predictor wrapped-predictor) - (util/vec->indexed-seq inputs)))) + (->> (.predict (:predictor wrapped-predictor) + (util/vec->indexed-seq [(float-array (first inputs))])) + (util/coerce-return-recursive) + (first) + (mapv float))) (predict-with-ndarray [wrapped-predictor input-arrays] (util/validate! ::wrapped-predictor wrapped-predictor "Invalid predictor") (util/validate! ::vec-of-ndarrays input-arrays "Invalid input arrays") - (util/coerce-return-recursive - (.predictWithNDArray (:predictor wrapped-predictor) - (util/vec->indexed-seq input-arrays))))) + (-> (.predictWithNDArray (:predictor wrapped-predictor) + (util/vec->indexed-seq input-arrays)) + (util/coerce-return-recursive) + (first)))) (s/def ::nil-or-int (s/nilable int?)) @@ -355,10 +358,12 @@ (defn buffered-image-to-pixels "Convert input BufferedImage to NDArray of input shape" - [image input-shape-vec] - (util/validate! ::image image "Invalid image") - (util/validate! (s/coll-of int?) input-shape-vec "Invalid shape vector") - (ImageClassifier/bufferedImageToPixels image (shape/->shape input-shape-vec) dtype/FLOAT32)) + ([image input-shape-vec] + (buffered-image-to-pixels image input-shape-vec dtype/FLOAT32)) + ([image input-shape-vec dtype] + (util/validate! ::image image "Invalid image") + (util/validate! (s/coll-of int?) input-shape-vec "Invalid shape vector") + (ImageClassifier/bufferedImageToPixels image (shape/->shape input-shape-vec) dtype/FLOAT32))) (s/def ::image-path string?) (s/def ::image-paths (s/coll-of ::image-path)) @@ -375,13 +380,3 @@ (util/validate! ::image-paths image-paths "Invalid image paths") (util/scala-vector->vec (ImageClassifier/loadInputBatch (util/convert-vector image-paths)))) - -(defn reshape-image - "Reshapes a buffered image" - [buffered-image width height] - (ImageClassifier/reshapeImage buffered-image (int width) (int height))) - -(defn buffered-image-to-pixels - "Turns the buffered image into a ndarray allowing to specify shape and type" - [buffered-image shape-vec dtype] - (ImageClassifier/bufferedImageToPixels buffered-image (mx-shape/->shape shape-vec) dtype)) diff --git a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/predictor_test.clj b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/predictor_test.clj index 0e7532bc2258..4d021b59433c 100644 --- a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/predictor_test.clj +++ b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/predictor_test.clj @@ -42,14 +42,14 @@ factory (infer/model-factory model-path-prefix descriptors)] (infer/create-predictor factory))) -(deftest predictor-test +(deftest predictor-test-with-ndarray (let [predictor (create-predictor) image-ndarray (-> "test/test-images/kitten.jpg" infer/load-image-from-file (infer/reshape-image width height) (infer/buffered-image-to-pixels [3 width height]) (ndarray/expand-dims 0)) - [predictions] (infer/predict-with-ndarray predictor [image-ndarray]) + predictions (infer/predict-with-ndarray predictor [image-ndarray]) synset-file (-> (io/file model-path-prefix) (.getParent) (io/file "synset.txt")) @@ -57,3 +57,20 @@ [best-index] (ndarray/->int-vec (ndarray/argmax predictions 1)) best-prediction (synset-names best-index)] (is (= "n02123159 tiger cat" best-prediction)))) + +(deftest predictor-test + (let [predictor (create-predictor) + image-ndarray (-> "test/test-images/kitten.jpg" + infer/load-image-from-file + (infer/reshape-image width height) + (infer/buffered-image-to-pixels [3 width height]) + (ndarray/expand-dims 0)) + predictions (infer/predict predictor [(ndarray/->vec image-ndarray)]) + synset-file (-> (io/file model-path-prefix) + (.getParent) + (io/file "synset.txt")) + synset-names (split (slurp synset-file) #"\n") + ndarray-preds (ndarray/array predictions [1 1000]) + [best-index] (ndarray/->int-vec (ndarray/argmax ndarray-preds 1)) + best-prediction (synset-names best-index)] + (is (= "n02123159 tiger cat" best-prediction)))) From 14b9c99ec40c39b5d5c401e365ae48aa76112329 Mon Sep 17 00:00:00 2001 From: gigasquid Date: Sat, 12 Jan 2019 10:54:03 -0500 Subject: [PATCH 05/11] updated infer-classify examples --- .../src/infer/imageclassifier_example.clj | 16 +++++++-------- .../infer/imageclassifier_example_test.clj | 20 ++++++------------- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/contrib/clojure-package/examples/infer/imageclassifier/src/infer/imageclassifier_example.clj b/contrib/clojure-package/examples/infer/imageclassifier/src/infer/imageclassifier_example.clj index 4ec7ff7f1490..edd47f2db216 100644 --- a/contrib/clojure-package/examples/infer/imageclassifier/src/infer/imageclassifier_example.clj +++ b/contrib/clojure-package/examples/infer/imageclassifier/src/infer/imageclassifier_example.clj @@ -55,8 +55,8 @@ "Print image classifier predictions for the given input file" [predictions] (println (apply str (repeat 80 "="))) - (doseq [[label probability] predictions] - (println (format "Class: %s Probability=%.8f" label probability))) + (doseq [p predictions] + (println p)) (println (apply str (repeat 80 "=")))) (defn classify-single-image @@ -64,7 +64,7 @@ [classifier input-image] (let [image (infer/load-image-from-file input-image) topk 5 - [predictions] (infer/classify-image classifier image topk)] + predictions (infer/classify-image classifier image topk)] predictions)) (defn classify-images-in-dir @@ -78,12 +78,10 @@ (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/classify-image-batch classifier image-batch topk)))))) + (for [image-files image-file-batches] + (let [image-batch (infer/load-image-paths image-files) + topk 5] + (infer/classify-image-batch classifier image-batch topk))))) (defn run-classifier "Runs an image classifier based on options provided" diff --git a/contrib/clojure-package/examples/infer/imageclassifier/test/infer/imageclassifier_example_test.clj b/contrib/clojure-package/examples/infer/imageclassifier/test/infer/imageclassifier_example_test.clj index 5b3e08d134f8..b63067427909 100644 --- a/contrib/clojure-package/examples/infer/imageclassifier/test/infer/imageclassifier_example_test.clj +++ b/contrib/clojure-package/examples/infer/imageclassifier/test/infer/imageclassifier_example_test.clj @@ -46,16 +46,9 @@ predictions (classify-single-image classifier image-file)] (is (some? predictions)) (is (= 5 (count predictions))) - (is (every? #(= 2 (count %)) predictions)) - (is (every? #(string? (first %)) predictions)) - (is (every? #(float? (second %)) predictions)) - (is (every? #(< 0 (second %) 1) predictions)) - (is (= ["n02123159 tiger cat" - "n02124075 Egyptian cat" - "n02123045 tabby, tabby cat" - "n02127052 lynx, catamount" - "n02128757 snow leopard, ounce, Panthera uncia"] - (map first predictions))))) + (is (= 5 (count predictions))) + (is (= "n02123159 tiger cat" (:class (first predictions)))) + (is (= (< 0 (:prob (first predictions)) 1))))) (deftest test-batch-classification (let [classifier (create-classifier) @@ -63,7 +56,6 @@ predictions (first batch-predictions)] (is (some? batch-predictions)) (is (= 5 (count predictions))) - (is (every? #(= 2 (count %)) predictions)) - (is (every? #(string? (first %)) predictions)) - (is (every? #(float? (second %)) predictions)) - (is (every? #(< 0 (second %) 1) predictions)))) + (is (= 5 (count predictions))) + (is (= "n02123159 tiger cat" (:class (first predictions)))) + (is (= (< 0 (:prob (first predictions)) 1))))) From a3369109b694144d31b4bcaa380decfeee14f367 Mon Sep 17 00:00:00 2001 From: gigasquid Date: Sat, 12 Jan 2019 11:10:24 -0500 Subject: [PATCH 06/11] adjust the infer/object detections tests --- .../src/infer/imageclassifier_example.clj | 1 + .../src/infer/objectdetector_example.clj | 24 +++++++------------ .../infer/objectdetector_example_test.clj | 24 +++++++++---------- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/contrib/clojure-package/examples/infer/imageclassifier/src/infer/imageclassifier_example.clj b/contrib/clojure-package/examples/infer/imageclassifier/src/infer/imageclassifier_example.clj index edd47f2db216..5db07f8537ad 100644 --- a/contrib/clojure-package/examples/infer/imageclassifier/src/infer/imageclassifier_example.clj +++ b/contrib/clojure-package/examples/infer/imageclassifier/src/infer/imageclassifier_example.clj @@ -96,6 +96,7 @@ factory {:contexts [(context/default-context)]})] (println "Classifying a single image") (print-predictions (classify-single-image classifier input-image)) + (println "\n") (println "Classifying images in a directory") (doseq [predictions (classify-images-in-dir classifier input-dir)] (print-predictions predictions)))) 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 53172f0c8cad..104662633977 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 @@ -54,15 +54,8 @@ "Print image detector predictions for the given input file" [predictions width height] (println (apply str (repeat 80 "="))) - (doseq [[label prob-and-bounds] predictions] - (println (format - "Class: %s Prob=%.5f Coords=(%.3f, %.3f, %.3f, %.3f)" - label - (aget prob-and-bounds 0) - (* (aget prob-and-bounds 1) width) - (* (aget prob-and-bounds 2) height) - (* (aget prob-and-bounds 3) width) - (* (aget prob-and-bounds 4) height)))) + (doseq [p predictions] + (println p)) (println (apply str (repeat 80 "=")))) (defn detect-single-image @@ -70,7 +63,7 @@ [detector input-image] (let [image (infer/load-image-from-file input-image) topk 5 - [predictions] (infer/detect-objects detector image topk)] + predictions (infer/detect-objects detector image topk)] predictions)) (defn detect-images-in-dir @@ -84,12 +77,10 @@ (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)))))) + (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))))) (defn run-detector "Runs an image detector based on options provided" @@ -107,6 +98,7 @@ {:contexts [(context/default-context)]})] (println "Object detection on a single image") (print-predictions (detect-single-image detector input-image) width height) + (println "\n") (println "Object detection on images in a directory") (doseq [predictions (detect-images-in-dir detector input-dir)] (print-predictions predictions width height)))) diff --git a/contrib/clojure-package/examples/infer/objectdetector/test/infer/objectdetector_example_test.clj b/contrib/clojure-package/examples/infer/objectdetector/test/infer/objectdetector_example_test.clj index 90ed02f67a73..1ca9d5d7c0fe 100644 --- a/contrib/clojure-package/examples/infer/objectdetector/test/infer/objectdetector_example_test.clj +++ b/contrib/clojure-package/examples/infer/objectdetector/test/infer/objectdetector_example_test.clj @@ -43,23 +43,23 @@ (deftest test-single-detection (let [detector (create-detector) - predictions (detect-single-image detector image-file)] + predictions (detect-single-image detector image-file) + {:keys [class prob x-min x-max y-min y-max] :as pred} (first predictions)] (is (some? predictions)) (is (= 5 (count predictions))) - (is (every? #(= 2 (count %)) predictions)) - (is (every? #(string? (first %)) predictions)) - (is (every? #(= 5 (count (second %))) predictions)) - (is (every? #(< 0 (first (second %)) 1) predictions)) - (is (= ["car" "bicycle" "dog" "bicycle" "person"] - (map first predictions))))) + (is (string? class)) + (is (< 0.8 prob)) + (every? #(< 0 % 1) [x-min x-max y-min y-max]) + (is (= #{"dog" "person" "bicycle" "car"} (set (mapv :class predictions)))))) (deftest test-batch-detection (let [detector (create-detector) batch-predictions (detect-images-in-dir detector image-dir) - predictions (first batch-predictions)] + predictions (first batch-predictions) + {:keys [class prob x-min x-max y-min y-max] :as pred} (first predictions)] (is (some? batch-predictions)) (is (= 5 (count predictions))) - (is (every? #(= 2 (count %)) predictions)) - (is (every? #(string? (first %)) predictions)) - (is (every? #(= 5 (count (second %))) predictions)) - (is (every? #(< 0 (first (second %)) 1) predictions)))) + (is (string? class)) + (is (< 0.8 prob)) + (every? #(< 0 % 1) [x-min x-max y-min y-max]) + (is (= #{"dog" "person" "bicycle" "car"} (set (mapv :class predictions)))))) From 455c6fcb060ae0576678fcff9fdecfef19d19766 Mon Sep 17 00:00:00 2001 From: gigasquid Date: Sat, 12 Jan 2019 11:39:12 -0500 Subject: [PATCH 07/11] tweak predictor test --- .../examples/infer/predictor/src/infer/predictor_example.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/clojure-package/examples/infer/predictor/src/infer/predictor_example.clj b/contrib/clojure-package/examples/infer/predictor/src/infer/predictor_example.clj index 498964128dd8..b763fb2880d1 100644 --- a/contrib/clojure-package/examples/infer/predictor/src/infer/predictor_example.clj +++ b/contrib/clojure-package/examples/infer/predictor/src/infer/predictor_example.clj @@ -59,7 +59,7 @@ (defn do-inference "Run inference using given predictor" [predictor image] - (let [[predictions] (infer/predict-with-ndarray predictor [image])] + (let [predictions (infer/predict-with-ndarray predictor [image])] predictions)) (defn postprocess From 8fe433c3c93ac465a7192bcec7bd4d1d3fd69d5a Mon Sep 17 00:00:00 2001 From: gigasquid Date: Sat, 12 Jan 2019 13:03:14 -0500 Subject: [PATCH 08/11] Feedback from @kedarbellare review --- .../test/infer/imageclassifier_example_test.clj | 7 ++----- .../test/infer/objectdetector_example_test.clj | 2 +- .../clojure-package/src/org/apache/clojure_mxnet/infer.clj | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/contrib/clojure-package/examples/infer/imageclassifier/test/infer/imageclassifier_example_test.clj b/contrib/clojure-package/examples/infer/imageclassifier/test/infer/imageclassifier_example_test.clj index b63067427909..b969380bb2a5 100644 --- a/contrib/clojure-package/examples/infer/imageclassifier/test/infer/imageclassifier_example_test.clj +++ b/contrib/clojure-package/examples/infer/imageclassifier/test/infer/imageclassifier_example_test.clj @@ -46,16 +46,13 @@ predictions (classify-single-image classifier image-file)] (is (some? predictions)) (is (= 5 (count predictions))) - (is (= 5 (count predictions))) (is (= "n02123159 tiger cat" (:class (first predictions)))) (is (= (< 0 (:prob (first predictions)) 1))))) (deftest test-batch-classification (let [classifier (create-classifier) - batch-predictions (classify-images-in-dir classifier image-dir) - predictions (first batch-predictions)] - (is (some? batch-predictions)) - (is (= 5 (count predictions))) + predictions (first (classify-images-in-dir classifier image-dir))] + (is (some? predictions)) (is (= 5 (count predictions))) (is (= "n02123159 tiger cat" (:class (first predictions)))) (is (= (< 0 (:prob (first predictions)) 1))))) diff --git a/contrib/clojure-package/examples/infer/objectdetector/test/infer/objectdetector_example_test.clj b/contrib/clojure-package/examples/infer/objectdetector/test/infer/objectdetector_example_test.clj index 1ca9d5d7c0fe..2b8ad951ae22 100644 --- a/contrib/clojure-package/examples/infer/objectdetector/test/infer/objectdetector_example_test.clj +++ b/contrib/clojure-package/examples/infer/objectdetector/test/infer/objectdetector_example_test.clj @@ -49,7 +49,7 @@ (is (= 5 (count predictions))) (is (string? class)) (is (< 0.8 prob)) - (every? #(< 0 % 1) [x-min x-max y-min y-max]) + (is (every? #(< 0 % 1) [x-min x-max y-min y-max])) (is (= #{"dog" "person" "bicycle" "car"} (set (mapv :class predictions)))))) (deftest test-batch-detection diff --git a/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj b/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj index 2dd7966a779b..47c9c8af8ce4 100644 --- a/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj +++ b/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj @@ -363,7 +363,7 @@ ([image input-shape-vec dtype] (util/validate! ::image image "Invalid image") (util/validate! (s/coll-of int?) input-shape-vec "Invalid shape vector") - (ImageClassifier/bufferedImageToPixels image (shape/->shape input-shape-vec) dtype/FLOAT32))) + (ImageClassifier/bufferedImageToPixels image (shape/->shape input-shape-vec) dtype))) (s/def ::image-path string?) (s/def ::image-paths (s/coll-of ::image-path)) From 563ee1e3b5e14fe15aceb9f1ba95750481502a42 Mon Sep 17 00:00:00 2001 From: gigasquid Date: Sat, 12 Jan 2019 14:27:17 -0500 Subject: [PATCH 09/11] put scaling back in --- .../src/infer/objectdetector_example.clj | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) 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 104662633977..c630985a0fd9 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 @@ -54,8 +54,15 @@ "Print image detector predictions for the given input file" [predictions width height] (println (apply str (repeat 80 "="))) - (doseq [p predictions] - (println p)) + (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 detect-single-image From 676f3132fe1a3a2030aee66caed466f95fba4ddf Mon Sep 17 00:00:00 2001 From: gigasquid Date: Sat, 12 Jan 2019 16:08:39 -0500 Subject: [PATCH 10/11] put back predict so it can handle multiple inputs --- .../predictor/src/infer/predictor_example.clj | 2 +- .../src/org/apache/clojure_mxnet/infer.clj | 10 ++++------ .../apache/clojure_mxnet/infer/predictor_test.clj | 15 ++++++++------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/contrib/clojure-package/examples/infer/predictor/src/infer/predictor_example.clj b/contrib/clojure-package/examples/infer/predictor/src/infer/predictor_example.clj index b763fb2880d1..05eb0add3138 100644 --- a/contrib/clojure-package/examples/infer/predictor/src/infer/predictor_example.clj +++ b/contrib/clojure-package/examples/infer/predictor/src/infer/predictor_example.clj @@ -60,7 +60,7 @@ "Run inference using given predictor" [predictor image] (let [predictions (infer/predict-with-ndarray predictor [image])] - predictions)) + (first predictions))) (defn postprocess [model-path-prefix predictions] diff --git a/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj b/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj index 47c9c8af8ce4..7aa071f38dfb 100644 --- a/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj +++ b/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj @@ -102,10 +102,9 @@ (util/validate! ::vvec-of-numbers inputs "Invalid inputs") (->> (.predict (:predictor wrapped-predictor) - (util/vec->indexed-seq [(float-array (first inputs))])) - (util/coerce-return-recursive) - (first) - (mapv float))) + (util/vec->indexed-seq (mapv float-array inputs))) + (util/coerce-return-recursive) + (mapv #(mapv float %)))) (predict-with-ndarray [wrapped-predictor input-arrays] (util/validate! ::wrapped-predictor wrapped-predictor "Invalid predictor") @@ -113,8 +112,7 @@ "Invalid input arrays") (-> (.predictWithNDArray (:predictor wrapped-predictor) (util/vec->indexed-seq input-arrays)) - (util/coerce-return-recursive) - (first)))) + (util/coerce-return-recursive)))) (s/def ::nil-or-int (s/nilable int?)) diff --git a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/predictor_test.clj b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/predictor_test.clj index 4d021b59433c..e1526be61fbf 100644 --- a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/predictor_test.clj +++ b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/predictor_test.clj @@ -24,7 +24,8 @@ [clojure.java.io :as io] [clojure.java.shell :refer [sh]] [clojure.string :refer [split]] - [clojure.test :refer :all])) + [clojure.test :refer :all] + [org.apache.clojure-mxnet.util :as util])) (def model-dir "data/") (def model-path-prefix (str model-dir "resnet-18/resnet-18")) @@ -45,16 +46,16 @@ (deftest predictor-test-with-ndarray (let [predictor (create-predictor) image-ndarray (-> "test/test-images/kitten.jpg" - infer/load-image-from-file - (infer/reshape-image width height) - (infer/buffered-image-to-pixels [3 width height]) - (ndarray/expand-dims 0)) + infer/load-image-from-file + (infer/reshape-image width height) + (infer/buffered-image-to-pixels [3 width height]) + (ndarray/expand-dims 0)) predictions (infer/predict-with-ndarray predictor [image-ndarray]) synset-file (-> (io/file model-path-prefix) (.getParent) (io/file "synset.txt")) synset-names (split (slurp synset-file) #"\n") - [best-index] (ndarray/->int-vec (ndarray/argmax predictions 1)) + [best-index] (ndarray/->int-vec (ndarray/argmax (first predictions) 1)) best-prediction (synset-names best-index)] (is (= "n02123159 tiger cat" best-prediction)))) @@ -70,7 +71,7 @@ (.getParent) (io/file "synset.txt")) synset-names (split (slurp synset-file) #"\n") - ndarray-preds (ndarray/array predictions [1 1000]) + ndarray-preds (ndarray/array (first predictions) [1 1000]) [best-index] (ndarray/->int-vec (ndarray/argmax ndarray-preds 1)) best-prediction (synset-names best-index)] (is (= "n02123159 tiger cat" best-prediction)))) From dab1641e647b67e7d6d7e3582dd7ea3388f8cc8e Mon Sep 17 00:00:00 2001 From: gigasquid Date: Sat, 12 Jan 2019 17:05:52 -0500 Subject: [PATCH 11/11] restore original functions signatures (remove first) --- .../src/infer/imageclassifier_example.clj | 10 +-- .../infer/imageclassifier_example_test.clj | 2 +- .../src/infer/objectdetector_example.clj | 10 +-- .../src/org/apache/clojure_mxnet/infer.clj | 64 ++++++++----------- .../infer/imageclassifier_test.clj | 21 +++--- .../infer/objectdetector_test.clj | 12 ++-- 6 files changed, 55 insertions(+), 64 deletions(-) diff --git a/contrib/clojure-package/examples/infer/imageclassifier/src/infer/imageclassifier_example.clj b/contrib/clojure-package/examples/infer/imageclassifier/src/infer/imageclassifier_example.clj index 5db07f8537ad..6994b4fadc26 100644 --- a/contrib/clojure-package/examples/infer/imageclassifier/src/infer/imageclassifier_example.clj +++ b/contrib/clojure-package/examples/infer/imageclassifier/src/infer/imageclassifier_example.clj @@ -65,7 +65,7 @@ (let [image (infer/load-image-from-file input-image) topk 5 predictions (infer/classify-image classifier image topk)] - predictions)) + [predictions])) (defn classify-images-in-dir "Classify all jpg images in the directory" @@ -78,10 +78,10 @@ (filter #(re-matches #".*\.jpg$" (.getPath %))) (mapv #(.getPath %)) (partition-all batch-size))] - (for [image-files image-file-batches] - (let [image-batch (infer/load-image-paths image-files) - topk 5] - (infer/classify-image-batch classifier image-batch topk))))) + (apply concat (for [image-files image-file-batches] + (let [image-batch (infer/load-image-paths image-files) + topk 5] + (infer/classify-image-batch classifier image-batch topk)))))) (defn run-classifier "Runs an image classifier based on options provided" diff --git a/contrib/clojure-package/examples/infer/imageclassifier/test/infer/imageclassifier_example_test.clj b/contrib/clojure-package/examples/infer/imageclassifier/test/infer/imageclassifier_example_test.clj index b969380bb2a5..4b71f845dd5f 100644 --- a/contrib/clojure-package/examples/infer/imageclassifier/test/infer/imageclassifier_example_test.clj +++ b/contrib/clojure-package/examples/infer/imageclassifier/test/infer/imageclassifier_example_test.clj @@ -43,7 +43,7 @@ (deftest test-single-classification (let [classifier (create-classifier) - predictions (classify-single-image classifier image-file)] + [[predictions]] (classify-single-image classifier image-file)] (is (some? predictions)) (is (= 5 (count predictions))) (is (= "n02123159 tiger cat" (:class (first predictions)))) 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 c630985a0fd9..5c30e5db63fe 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 @@ -70,7 +70,7 @@ [detector input-image] (let [image (infer/load-image-from-file input-image) topk 5 - predictions (infer/detect-objects detector image topk)] + [predictions] (infer/detect-objects detector image topk)] predictions)) (defn detect-images-in-dir @@ -84,10 +84,10 @@ (filter #(re-matches #".*\.jpg$" (.getPath %))) (mapv #(.getPath %)) (partition-all batch-size))] - (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))))) + (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)))))) (defn run-detector "Runs an image detector based on options provided" diff --git a/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj b/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj index 7aa071f38dfb..09edf15b4288 100644 --- a/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj +++ b/contrib/clojure-package/src/org/apache/clojure_mxnet/infer.clj @@ -127,11 +127,11 @@ (util/validate! ::vvec-of-numbers inputs "Invalid inputs") (util/validate! ::nil-or-int topk "Invalid top-K") - (-> (.classify (:classifier wrapped-classifier) - (util/vec->indexed-seq [(float-array (first inputs))]) - (util/->int-option topk)) - (util/coerce-return-recursive) - (format-classification-predictions)))) + (->> (.classify (:classifier wrapped-classifier) + (util/vec->indexed-seq (mapv float-array inputs)) + (util/->int-option topk)) + (util/coerce-return-recursive) + (format-classification-predictions)))) (classify-with-ndarray ([wrapped-classifier inputs] (classify-with-ndarray wrapped-classifier inputs nil)) @@ -141,13 +141,11 @@ (util/validate! ::vec-of-ndarrays inputs "Invalid inputs") (util/validate! ::nil-or-int topk "Invalid top-K") - (-> - (.classifyWithNDArray (:classifier wrapped-classifier) - (util/vec->indexed-seq inputs) - (util/->int-option topk)) - (util/coerce-return-recursive) - (first) - (format-classification-predictions)))) + (->> (.classifyWithNDArray (:classifier wrapped-classifier) + (util/vec->indexed-seq inputs) + (util/->int-option topk)) + (util/coerce-return-recursive) + (mapv format-classification-predictions)))) WrappedImageClassifier (classify ([wrapped-image-classifier inputs] @@ -158,11 +156,11 @@ (util/validate! ::vvec-of-numbers inputs "Invalid inputs") (util/validate! ::nil-or-int topk "Invalid top-K") - (-> (.classify (:image-classifier wrapped-image-classifier) - (util/vec->indexed-seq [(float-array (first inputs))]) - (util/->int-option topk)) - (util/coerce-return-recursive) - (format-classification-predictions)))) + (->> (.classify (:image-classifier wrapped-image-classifier) + (util/vec->indexed-seq (mapv float-array inputs)) + (util/->int-option topk)) + (util/coerce-return-recursive) + (format-classification-predictions)))) (classify-with-ndarray ([wrapped-image-classifier inputs] (classify-with-ndarray wrapped-image-classifier inputs nil)) @@ -172,12 +170,11 @@ (util/validate! ::vec-of-ndarrays inputs "Invalid inputs") (util/validate! ::nil-or-int topk "Invalid top-K") - (-> (.classifyWithNDArray (:image-classifier wrapped-image-classifier) - (util/vec->indexed-seq inputs) - (util/->int-option topk)) - (util/coerce-return-recursive) - (first) - (format-classification-predictions))))) + (->> (.classifyWithNDArray (:image-classifier wrapped-image-classifier) + (util/vec->indexed-seq inputs) + (util/->int-option topk)) + (util/coerce-return-recursive) + (mapv format-classification-predictions))))) (s/def ::image #(instance? BufferedImage %)) (s/def ::dtype #{dtype/UINT8 dtype/INT32 dtype/FLOAT16 dtype/FLOAT32 dtype/FLOAT64}) @@ -195,13 +192,12 @@ (util/validate! ::image image "Invalid image") (util/validate! ::nil-or-int topk "Invalid top-K") (util/validate! ::dtype dtype "Invalid dtype") - (-> (.classifyImage (:image-classifier wrapped-image-classifier) + (->> (.classifyImage (:image-classifier wrapped-image-classifier) image (util/->int-option topk) dtype) - (util/coerce-return-recursive) - (first) - (format-classification-predictions)))) + (util/coerce-return-recursive) + (mapv format-classification-predictions)))) (classify-image-batch ([wrapped-image-classifier images] (classify-image-batch wrapped-image-classifier images nil dtype/FLOAT32)) @@ -213,13 +209,12 @@ (util/validate! ::batch-images images "Invalid Batch Images") (util/validate! ::nil-or-int topk "Invalid top-K") (util/validate! ::dtype dtype "Invalid dtype") - (-> (.classifyImageBatch (:image-classifier wrapped-image-classifier) + (->> (.classifyImageBatch (:image-classifier wrapped-image-classifier) (util/vec->indexed-seq images) (util/->int-option topk) dtype) (util/coerce-return-recursive) - (first) - (format-classification-predictions))))) + (mapv format-classification-predictions))))) (extend-protocol AObjectDetector WrappedObjectDetector @@ -235,8 +230,7 @@ image (util/->int-option topk)) (util/coerce-return-recursive) - (first) - (format-detection-predictions)))) + (mapv format-detection-predictions)))) (detect-objects-batch ([wrapped-detector images] (detect-objects-batch wrapped-detector images nil)) @@ -249,8 +243,7 @@ (util/vec->indexed-seq images) (util/->int-option topk)) (util/coerce-return-recursive) - (first) - (format-detection-predictions)))) + (mapv format-detection-predictions)))) (detect-objects-with-ndarrays ([wrapped-detector input-arrays] (detect-objects-with-ndarrays wrapped-detector input-arrays nil)) @@ -264,8 +257,7 @@ (util/vec->indexed-seq input-arrays) (util/->int-option topk)) (util/coerce-return-recursive) - (first) - (format-detection-predictions))))) + (mapv format-detection-predictions))))) (defprotocol AInferenceFactory (create-predictor [factory] [factory opts]) diff --git a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/imageclassifier_test.clj b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/imageclassifier_test.clj index 567ebc07f3cc..e3935c31e342 100644 --- a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/imageclassifier_test.clj +++ b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/imageclassifier_test.clj @@ -41,10 +41,9 @@ (deftest test-single-classification (let [classifier (create-classifier) image (infer/load-image-from-file "test/test-images/kitten.jpg") - predictions-all (infer/classify-image classifier image) - predictions-with-default-dtype (infer/classify-image classifier image 10) - predictions (infer/classify-image classifier image 5 dtype/FLOAT32)] - predictions + [predictions-all] (infer/classify-image classifier image) + [predictions-with-default-dtype] (infer/classify-image classifier image 10) + [predictions] (infer/classify-image classifier image 5 dtype/FLOAT32)] (is (= 1000 (count predictions-all))) (is (= 10 (count predictions-with-default-dtype))) (is (= 5 (count predictions))) @@ -55,9 +54,9 @@ (let [classifier (create-classifier) image-batch (infer/load-image-paths ["test/test-images/kitten.jpg" "test/test-images/Pug-Cookie.jpg"]) - batch-predictions-all (infer/classify-image-batch classifier image-batch) - batch-predictions-with-default-dtype (infer/classify-image-batch classifier image-batch 10) - predictions (infer/classify-image-batch classifier image-batch 5 dtype/FLOAT32)] + [batch-predictions-all] (infer/classify-image-batch classifier image-batch) + [batch-predictions-with-default-dtype] (infer/classify-image-batch classifier image-batch 10) + [predictions] (infer/classify-image-batch classifier image-batch 5 dtype/FLOAT32)] (is (= 1000 (count batch-predictions-all))) (is (= 10 (count batch-predictions-with-default-dtype))) (is (= 5 (count predictions))) @@ -70,8 +69,8 @@ (infer/reshape-image 224 224) (infer/buffered-image-to-pixels [3 224 224] dtype/FLOAT32) (ndarray/expand-dims 0)) - predictions-all (infer/classify-with-ndarray classifier [image]) - predictions (infer/classify-with-ndarray classifier [image] 5)] + [predictions-all] (infer/classify-with-ndarray classifier [image]) + [predictions] (infer/classify-with-ndarray classifier [image] 5)] (is (= 1000 (count predictions-all))) (is (= 5 (count predictions))) (is (= "n02123159 tiger cat" (:class (first predictions)))) @@ -101,8 +100,8 @@ (infer/reshape-image 224 224) (infer/buffered-image-to-pixels [3 224 224] dtype/FLOAT32) (ndarray/expand-dims 0)) - predictions-all (infer/classify-with-ndarray classifier [image]) - predictions (infer/classify-with-ndarray classifier [image] 5)] + [predictions-all] (infer/classify-with-ndarray classifier [image]) + [predictions] (infer/classify-with-ndarray classifier [image] 5)] (is (= 1000 (count predictions-all))) (is (= 5 (count predictions))) (is (= "n02123159 tiger cat" (:class (first predictions)))) diff --git a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/objectdetector_test.clj b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/objectdetector_test.clj index 76acbfc9d543..e2b9579c7000 100644 --- a/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/objectdetector_test.clj +++ b/contrib/clojure-package/test/org/apache/clojure_mxnet/infer/objectdetector_test.clj @@ -41,8 +41,8 @@ (deftest test-single-detection (let [detector (create-detector) image (infer/load-image-from-file "test/test-images/kitten.jpg") - predictions-all (infer/detect-objects detector image) - predictions (infer/detect-objects detector image 5) + [predictions-all] (infer/detect-objects detector image) + [predictions] (infer/detect-objects detector image 5) {:keys [class prob x-min x-max y-min y-max] :as pred} (first predictions)] (is (some? predictions)) (is (= 5 (count predictions))) @@ -55,8 +55,8 @@ (let [detector (create-detector) image-batch (infer/load-image-paths ["test/test-images/kitten.jpg" "test/test-images/Pug-Cookie.jpg"]) - batch-predictions-all (infer/detect-objects-batch detector image-batch) - predictions (infer/detect-objects-batch detector image-batch 5) + [batch-predictions-all] (infer/detect-objects-batch detector image-batch) + [predictions] (infer/detect-objects-batch detector image-batch 5) {:keys [class prob x-min x-max y-min y-max] :as pred} (first predictions)] (is (some? predictions)) (is (= 13 (count batch-predictions-all))) @@ -71,8 +71,8 @@ (infer/reshape-image 512 512) (infer/buffered-image-to-pixels [3 512 512] dtype/FLOAT32) (ndarray/expand-dims 0)) - predictions-all (infer/detect-objects-with-ndarrays detector [image]) - predictions (infer/detect-objects-with-ndarrays detector [image] 1) + [predictions-all] (infer/detect-objects-with-ndarrays detector [image]) + [predictions] (infer/detect-objects-with-ndarrays detector [image] 1) {:keys [class prob x-min x-max y-min y-max] :as pred} (first predictions)] (is (some? predictions-all)) (is (= 1 (count predictions)))