@@ -63,35 +63,91 @@ std::unique_ptr<ITensorAccessor> get_accessor(const std::string &path, const std
6363 }
6464}
6565
66+ /* * Generates appropriate input accessor according to the specified ppm_path
67+ *
68+ * @note If ppm_path is empty will generate a DummyAccessor else will generate a PPMAccessor
69+ *
70+ * @param[in] ppm_path Path to PPM file
71+ * @param[in] mean_r Red mean value to be subtracted from red channel
72+ * @param[in] mean_g Green mean value to be subtracted from green channel
73+ * @param[in] mean_b Blue mean value to be subtracted from blue channel
74+ *
75+ * @return An appropriate tensor accessor
76+ */
77+ std::unique_ptr<ITensorAccessor> get_input_accessor (const std::string &ppm_path, float mean_r, float mean_g, float mean_b)
78+ {
79+ if (ppm_path.empty ())
80+ {
81+ return arm_compute::support::cpp14::make_unique<DummyAccessor>();
82+ }
83+ else
84+ {
85+ return arm_compute::support::cpp14::make_unique<PPMAccessor>(ppm_path, true , mean_r, mean_g, mean_b);
86+ }
87+ }
88+
89+ /* * Generates appropriate output accessor according to the specified labels_path
90+ *
91+ * @note If labels_path is empty will generate a DummyAccessor else will generate a TopNPredictionsAccessor
92+ *
93+ * @param[in] labels_path Path to labels text file
94+ * @param[in] top_n (Optional) Number of output classes to print
95+ * @param[out] output_stream (Optional) Output stream
96+ *
97+ * @return An appropriate tensor accessor
98+ */
99+ std::unique_ptr<ITensorAccessor> get_output_accessor (const std::string &labels_path, size_t top_n = 5 , std::ostream &output_stream = std::cout)
100+ {
101+ if (labels_path.empty ())
102+ {
103+ return arm_compute::support::cpp14::make_unique<DummyAccessor>();
104+ }
105+ else
106+ {
107+ return arm_compute::support::cpp14::make_unique<TopNPredictionsAccessor>(labels_path, top_n, output_stream);
108+ }
109+ }
110+
66111/* * Example demonstrating how to implement AlexNet's network using the Compute Library's graph API
67112 *
68113 * @param[in] argc Number of arguments
69- * @param[in] argv Arguments ( [optional] Path to the weights folder, [optional] batches )
114+ * @param[in] argv Arguments ( [optional] Path to the weights folder, [optional] image, [optional] labels )
70115 */
71116void main_graph_alexnet (int argc, const char **argv)
72117{
73- std::string data_path; /* * Path to the trainable data */
74- unsigned int batches = 4 ; /* * Number of batches */
118+ std::string data_path; /* Path to the trainable data */
119+ std::string image; /* Image data */
120+ std::string label; /* Label data */
121+
122+ constexpr float mean_r = 122 .68f ; /* Mean value to subtract from red channel */
123+ constexpr float mean_g = 116 .67f ; /* Mean value to subtract from green channel */
124+ constexpr float mean_b = 104 .01f ; /* Mean value to subtract from blue channel */
75125
76126 // Parse arguments
77127 if (argc < 2 )
78128 {
79129 // Print help
80- std::cout << " Usage: " << argv[0 ] << " [path_to_data] [batches ]\n\n " ;
130+ std::cout << " Usage: " << argv[0 ] << " [path_to_data] [image] [labels ]\n\n " ;
81131 std::cout << " No data folder provided: using random values\n\n " ;
82132 }
83133 else if (argc == 2 )
84134 {
85- // Do something with argv[1]
86135 data_path = argv[1 ];
87- std::cout << " Usage: " << argv[0 ] << " [path_to_data] [batches]\n\n " ;
88- std::cout << " No number of batches where specified, thus will use the default : " << batches << " \n\n " ;
136+ std::cout << " Usage: " << argv[0 ] << " " << argv[1 ] << " [image] [labels]\n\n " ;
137+ std::cout << " No image provided: using random values\n\n " ;
138+ }
139+ else if (argc == 3 )
140+ {
141+ data_path = argv[1 ];
142+ image = argv[2 ];
143+ std::cout << " Usage: " << argv[0 ] << " " << argv[1 ] << " " << argv[2 ] << " [labels]\n\n " ;
144+ std::cout << " No text file with labels provided: skipping output accessor\n\n " ;
89145 }
90146 else
91147 {
92- // Do something with argv[1] and argv[2]
93148 data_path = argv[1 ];
94- batches = std::strtol (argv[2 ], nullptr , 0 );
149+ image = argv[2 ];
150+ label = argv[3 ];
95151 }
96152
97153 // Check if OpenCL is available and initialize the scheduler
@@ -106,7 +162,8 @@ void main_graph_alexnet(int argc, const char **argv)
106162 arm_compute::Logger::get ().set_logger (std::cout, arm_compute::LoggerVerbosity::INFO);
107163
108164 graph << hint
109- << Tensor (TensorInfo (TensorShape (227U , 227U , 3U , batches), 1 , DataType::F32), DummyAccessor ())
165+ << Tensor (TensorInfo (TensorShape (227U , 227U , 3U , 1U ), 1 , DataType::F32),
166+ get_input_accessor (image, mean_r, mean_g, mean_b))
110167 // Layer 1
111168 << ConvolutionLayer (
112169 11U , 11U , 96U ,
@@ -167,7 +224,7 @@ void main_graph_alexnet(int argc, const char **argv)
167224 get_accessor (data_path, " /cnn_data/alexnet_model/fc8_b.npy" ))
168225 // Softmax
169226 << SoftmaxLayer ()
170- << Tensor (DummyAccessor ( ));
227+ << Tensor (get_output_accessor (label, 5 ));
171228
172229 // Run graph
173230 graph.run ();
@@ -176,7 +233,7 @@ void main_graph_alexnet(int argc, const char **argv)
176233/* * Main program for AlexNet
177234 *
178235 * @param[in] argc Number of arguments
179- * @param[in] argv Arguments ( [optional] Path to the weights folder, [optional] batches )
236+ * @param[in] argv Arguments ( [optional] Path to the weights folder, [optional] image, [optional] labels )
180237 */
181238int main (int argc, const char **argv)
182239{
0 commit comments