20#include <opencv2/imgproc/imgproc.hpp>
21#include <darknet-nnpack/src/classifier.h>
22#include <darknet-nnpack/src/option_list.h>
23#include <darknet-nnpack/src/data.h>
24#include <darknet-nnpack/src/network.h>
29 jevois::Component(instance), net(nullptr), names(nullptr), classes(0), itsReady(false),
30 itsShowDetailParams(show_detail_params), itsNeedReload(false)
40 dataroot::freeze(
true);
41 datacfg::freeze(
true);
42 cfgfile::freeze(
true);
43 weightfile::freeze(
true);
44 namefile::freeze(
true);
64 dataroot::freeze(
false);
65 datacfg::freeze(
false);
66 cfgfile::freeze(
false);
67 weightfile::freeze(
false);
68 namefile::freeze(
false);
73 case dknet::Net::Reference:
75 datacfg::set(
"cfg/imagenet1k.data");
76 cfgfile::set(
"cfg/darknet.cfg");
77 weightfile::set(
"weights/darknet.weights");
81 case dknet::Net::Tiny:
83 datacfg::set(
"cfg/imagenet1k.data");
84 cfgfile::set(
"cfg/tiny.cfg");
85 weightfile::set(
"weights/tiny.weights");
92 dataroot::freeze(
true);
93 datacfg::freeze(
true);
94 cfgfile::freeze(
true);
95 weightfile::freeze(
true);
96 namefile::freeze(
true);
120 if (
itsReadyFut.wait_for(std::chrono::milliseconds(5)) == std::future_status::ready)
123 throw std::logic_error(
"Loading already in progress. Attempt to load again rejected");
133 if (
net &&
net->threadpool) pthreadpool_destroy(
net->threadpool);
135 if (
net) { free_network(*
net); free(
net);
net =
nullptr; }
140 std::string root = dataroot::get();
if (root.empty() ==
false) root +=
'/';
143 std::string
const datacf =
absolutePath(root + datacfg::get());
144 std::string
const cfgfil =
absolutePath(root + cfgfile::get());
145 std::string
const weightfil =
absolutePath(root + weightfile::get());
147 list * options = read_data_cfg(
const_cast<char *
>(datacf.c_str()));
148 std::string name_list = namefile::get();
149 if (name_list.empty()) name_list =
absolutePath(root + option_find_str(options,
"names",
"data/names.list"));
152 LINFO(
"Using data config from " << datacf);
153 LINFO(
"Using cfg from " << cfgfil);
154 LINFO(
"Using weights from " << weightfil);
155 LINFO(
"Using names from " << name_list);
157 LINFO(
"Getting labels...");
158 names = get_labels(
const_cast<char *
>(name_list.c_str()));
159 LINFO(
"Parsing network and loading weights...");
161 net = load_network(
const_cast<char *
>(cfgfil.c_str()),
const_cast<char *
>(weightfil.c_str()), 0);
164 { free_list(options);
LFATAL(
"Failed to load darknet network and/or weights -- ABORT"); }
166 classes = option_find_int(options,
"classes", 2);
168 set_batch_network(
net, 1);
172 net->threadpool = pthreadpool_create(threads::get());
174 LINFO(
"Darknet network ready");
191 if (
net->threadpool) pthreadpool_destroy(
net->threadpool);
205 if (
itsReady.load() ==
false)
throw std::logic_error(
"not ready yet...");
206 if (cvimg.type() != CV_8UC3)
LFATAL(
"cvimg must have type CV_8UC3 and RGB pixels");
209 int const w = cvimg.cols;
210 int const h = cvimg.rows;
211 image im = make_image(w,
h, c);
212 for (
int k = 0; k < c; ++k)
213 for (
int j = 0; j <
h; ++j)
214 for (
int i = 0; i < w; ++i)
216 int const dst_index = i + w*j + w*
h*k;
217 int const src_index = k + c*i + c*w*j;
218 im.data[dst_index] = float(cvimg.data[src_index]) * (1.0F / 255.0F);
221 float predtime =
predict(im, results);
232 if (
itsReady.load() ==
false)
throw std::logic_error(
"not ready yet...");
233 int const topn = top::get();
234 float const th = thresh::get();
238 resize_network(
net, im.w, im.h);
241 struct timeval start, stop;
242 gettimeofday(&start, 0);
243 float * predictions = network_predict(*
net, im.data);
244 gettimeofday(&stop, 0);
246 float predtime = (stop.tv_sec * 1000 + stop.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
248 if (
net->hierarchy) hierarchy_predictions(predictions,
net->outputs,
net->hierarchy, 1);
252 top_k(predictions,
net->outputs, topn, indexes);
254 for (
int i = 0; i < topn; ++i)
256 int const index = indexes[i];
257 float const score = float(predictions[index] * 100);
258 if (score >= th) results.push_back( { score, std::string(
names[index]) } );
269 if (
itsReady.load() ==
false)
throw std::logic_error(
"not ready yet...");
270 resize_network(
net, w,
h);
277 if (
itsReady.load() ==
false)
throw std::logic_error(
"not ready yet...");
#define JEVOIS_SHARE_PATH
#define JEVOIS_WAIT_GET_FUTURE(f)
void postInit() override
Initialize, configure and load the network in a thread.
float predict(cv::Mat const &cvimg, std::vector< jevois::ObjReco > &results)
Processing function, results are stored internally in the underlying Darknet network object.
std::future< void > itsReadyFut
void onParamChange(dknet::netw const ¶m, dknet::Net const &newval) override
void getInDims(int &w, int &h, int &c)
Get input width, height, channels.
bool const itsShowDetailParams
std::atomic< bool > itsNeedReload
virtual ~Darknet()
Virtual destructor for safe inheritance.
std::atomic< bool > itsReady
void postUninit() override
Un-initialize and free resources.
void resizeInDims(int w, int h)
Resize the network's input image dims.
Darknet(std::string const &instance, bool show_detail_params=false)
Constructor.
std::filesystem::path absolutePath(std::filesystem::path const &path="")
std::future< std::invoke_result_t< std::decay_t< Function >, std::decay_t< Args >... > > async(Function &&f, Args &&... args)