Skip to content
This repository was archived by the owner on Jul 1, 2024. It is now read-only.

Commit bdc2a49

Browse files
Add addon
1 parent e34e117 commit bdc2a49

10 files changed

+738
-448
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
node_modules/
22
libdarknet*
33
darknet/
4+
include/
5+
build/
46

57
*.js
68
*.d.ts

.npmignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
lib/
22
examples/
3+
build/
34
darknet/
45
libdarknet*
5-
tsconfig.json
6+
tsconfig.json

binding.gyp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
"cflags!": [ "-fno-exceptions" ],
55
"cflags_cc!": [ "-fno-exceptions" ],
66
"sources": [
7-
"cppsrc/main.cpp"
7+
"cppsrc/main.cpp",
8+
"cppsrc/detector.cpp"
89
],
910
'include_dirs': [
10-
"<!@(node -p \"require('node-addon-api').include\")"
11+
"<!@(node -p \"require('node-addon-api').include\")",
12+
"darknet/include/"
13+
],
14+
'libraries': [
15+
"../darknet/libdarknet.a"
1116
],
12-
'libraries': [],
1317
'dependencies': [
1418
"<!(node -p \"require('node-addon-api').gyp\")"
1519
],

cppsrc/detector.cpp

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#include "detector.h"
2+
#include <darknet.h>
3+
#include <napi.h>
4+
#include <vector>
5+
6+
using namespace Napi;
7+
8+
FunctionReference Detector::constructor;
9+
10+
Object Detector::Init(Napi::Env env, Object exports) {
11+
HandleScope scope(env);
12+
13+
Function func = DefineClass(
14+
env, "Detector",
15+
{
16+
InstanceMethod("detectImageBuffer", &Detector::detectImageBuffer),
17+
InstanceMethod("detectImagePath", &Detector::detectImagePath),
18+
});
19+
20+
constructor = Persistent(func);
21+
constructor.SuppressDestruct();
22+
23+
exports.Set("Detector", func);
24+
return exports;
25+
}
26+
27+
Detector::Detector(const CallbackInfo &info) : ObjectWrap<Detector>(info) {
28+
Napi::Env env = info.Env();
29+
HandleScope scope(env);
30+
31+
int length = info.Length();
32+
33+
if (length != 3 || !info[0].IsString() || !info[1].IsString() ||
34+
!info[2].IsString()) {
35+
TypeError::New(env, "Please provide correct config!")
36+
.ThrowAsJavaScriptException();
37+
}
38+
39+
std::string weights = info[0].As<String>();
40+
std::string config = info[1].As<String>();
41+
std::string names = info[2].As<String>();
42+
43+
std::string::size_type pos = 0;
44+
std::string::size_type prev = 0;
45+
while ((pos = names.find("\n", prev)) != std::string::npos) {
46+
this->names.push_back(names.substr(prev, pos - prev));
47+
prev = pos + 1;
48+
}
49+
50+
// To get the last substring (or only, if delimiter is not found)
51+
this->names.push_back(names.substr(prev));
52+
53+
this->weights = const_cast<char *>(weights.c_str());
54+
this->config = const_cast<char *>(config.c_str());
55+
56+
this->classes = this->names.size();
57+
58+
this->net = load_network(this->config, this->weights, 0);
59+
}
60+
61+
Value Detector::detectImagePath(const CallbackInfo &info) {
62+
Napi::Env env = info.Env();
63+
HandleScope scope(env);
64+
65+
int length = info.Length();
66+
67+
if (length != 4 || !info[0].IsString() || !info[1].IsNumber() ||
68+
!info[2].IsNumber() || !info[3].IsNumber()) {
69+
TypeError::New(env, "Please provide correct config!")
70+
.ThrowAsJavaScriptException();
71+
}
72+
73+
float thresh = info[1].ToNumber();
74+
float heir = info[2].ToNumber();
75+
float nms = info[3].ToNumber();
76+
77+
char *imageLocation = const_cast<char *>(
78+
static_cast<std::string>(info[0].As<String>()).c_str());
79+
80+
image loadedImage = load_image_color(imageLocation, 0, 0);
81+
82+
Array det = this->detectImageInternal(env, loadedImage, thresh, heir, nms);
83+
84+
free_image(loadedImage);
85+
86+
return det;
87+
}
88+
89+
Value Detector::detectImageBuffer(const CallbackInfo &info) {
90+
Napi::Env env = info.Env();
91+
HandleScope scope(env);
92+
93+
int length = info.Length();
94+
95+
// buffer, w, h, c, thresh, hier, nms
96+
97+
if (length != 7 || !info[0].IsArrayBuffer() || !info[1].IsNumber() ||
98+
!info[2].IsNumber() || !info[3].IsNumber() || !info[4].IsNumber() ||
99+
!info[5].IsNumber() || !info[6].IsNumber()) {
100+
TypeError::New(env, "Please provide correct config!")
101+
.ThrowAsJavaScriptException();
102+
}
103+
104+
ArrayBuffer buffer = info[0].As<ArrayBuffer>();
105+
106+
float w = info[1].ToNumber();
107+
float h = info[2].ToNumber();
108+
float c = info[3].ToNumber();
109+
110+
image i = float_to_image(w, h, c, static_cast<float *>(buffer.Data()));
111+
112+
float thresh = info[4].ToNumber();
113+
float heir = info[5].ToNumber();
114+
float nms = info[6].ToNumber();
115+
116+
Array det = this->detectImageInternal(env, i, thresh, heir, nms);
117+
118+
return det;
119+
}
120+
121+
Array Detector::detectImageInternal(Napi::Env env, image image, float thresh,
122+
float hier, float nms) {
123+
124+
int total;
125+
126+
network_predict_image(this->net, image);
127+
128+
detection *dets = get_network_boxes(this->net, image.w, image.h, thresh, hier,
129+
NULL, 0, &total);
130+
do_nms_obj(dets, total, this->classes, nms);
131+
132+
Array ret = Array::New(env);
133+
134+
int current = 0;
135+
136+
for (int i = 0; i < total; i++) {
137+
detection a = dets[i];
138+
float *prob = a.prob;
139+
140+
for (int j = 0; j < this->classes; j++) {
141+
if (prob[j] > 0) {
142+
143+
Object bbox = Object::New(env);
144+
145+
bbox.Set("w", Number::New(env, a.bbox.w));
146+
bbox.Set("h", Number::New(env, a.bbox.h));
147+
bbox.Set("x", Number::New(env, a.bbox.x));
148+
bbox.Set("y", Number::New(env, a.bbox.y));
149+
150+
Object detected = Object::New(env);
151+
detected.Set("bbox", bbox);
152+
detected.Set("prob", Number::New(env, prob[j]));
153+
detected.Set("name", String::New(env, this->names[j]));
154+
155+
ret.Set(current++, detected);
156+
}
157+
}
158+
}
159+
160+
free_detections(dets, total);
161+
162+
return ret;
163+
}

cppsrc/detector.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include <darknet.h>
2+
#include <napi.h>
3+
4+
using namespace std;
5+
6+
class Detector : public Napi::ObjectWrap<Detector> {
7+
public:
8+
static Napi::Object Init(Napi::Env env, Napi::Object exports);
9+
Detector(const Napi::CallbackInfo &info);
10+
11+
private:
12+
char *weights;
13+
char *config;
14+
vector<string> names;
15+
16+
int classes;
17+
18+
network *net;
19+
20+
Napi::Array detectImageInternal(
21+
Napi::Env env,
22+
image image,
23+
float thresh,
24+
float heir,
25+
float nms
26+
);
27+
28+
static Napi::FunctionReference constructor;
29+
Napi::Value
30+
detectImageBuffer(const Napi::CallbackInfo &info); // wrapped add function
31+
Napi::Value
32+
detectImagePath(const Napi::CallbackInfo &info); // wrapped add function
33+
};
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
/* cppsrc/main.cpp */
22
#include <napi.h>
33

4+
#include "detector.h"
5+
46
Napi::Object InitAll(Napi::Env env, Napi::Object exports) {
5-
return exports;
7+
return Detector::Init(env, exports);
68
}
79

8-
NODE_API_MODULE(testaddon, InitAll)
10+
NODE_API_MODULE(darknet, InitAll)

install-script.sh

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#!/usr/bin/env bash
22
if [ ! -d darknet ]; then
3-
git clone https://github.com/pjreddie/darknet;
3+
git clone https://github.com/pjreddie/darknet;
44

5-
if [ $? -ne 0 ]; then
6-
echo "Could not clone darknet repo";
7-
exit 1;
8-
fi
5+
if [ $? -ne 0 ]; then
6+
echo "Could not clone darknet repo";
7+
exit 1;
8+
fi
99
fi
1010

1111
# dive in the darknet folder and make
@@ -18,23 +18,23 @@ OPENCV="${DARKNET_BUILD_WITH_OPENCV:-0}";
1818
OPENMP="${DARKNET_BUILD_WITH_OPENMP:-0}";
1919

2020
case "$GPU" in
21-
1|0);;
22-
*) echo "Interpreting DARKNET_BUILD_WITH_GPU=$GPU as 0"; GPU=0;;
21+
1|0);;
22+
*) echo "Interpreting DARKNET_BUILD_WITH_GPU=$GPU as 0"; GPU=0;;
2323
esac
2424

2525
case "$CUDNN" in
26-
1|0);;
27-
*) echo "Interpreting DARKNET_BUILD_WITH_CUDNN=$CUDNN as 0"; CUDNN=0;;
26+
1|0);;
27+
*) echo "Interpreting DARKNET_BUILD_WITH_CUDNN=$CUDNN as 0"; CUDNN=0;;
2828
esac
2929

3030
case "$OPENCV" in
31-
1|0);;
32-
*) echo "Interpreting DARKNET_BUILD_WITH_OPENCV=$OPENCV as 0"; OPENCV=0;;
31+
1|0);;
32+
*) echo "Interpreting DARKNET_BUILD_WITH_OPENCV=$OPENCV as 0"; OPENCV=0;;
3333
esac
3434

3535
case "$OPENMP" in
36-
1|0);;
37-
*) echo "Interpreting DARKNET_BUILD_WITH_OPENMP=$OPENMP as 0"; OPENMP=0;;
36+
1|0);;
37+
*) echo "Interpreting DARKNET_BUILD_WITH_OPENMP=$OPENMP as 0"; OPENMP=0;;
3838
esac
3939

4040
sed -i -e "s/GPU=[01]/GPU=${GPU}/g" ./Makefile
@@ -45,17 +45,18 @@ sed -i -e "s/OPENMP=[01]/OPENMP=${OPENMP}/g" ./Makefile
4545
make
4646

4747
if [ $? -ne 0 ]; then
48-
echo "Could not compile darknet";
49-
exit 2;
48+
echo "Could not compile darknet";
49+
exit 2;
5050
fi
5151

5252
# copy lib
5353
cp libdarknet* ..
54+
cp -r include/ ..
5455

5556
# dive out
5657
cd ..
5758

5859
# if macos make .dylib symlink
5960
if [[ "$OSTYPE" == "darwin"* ]]; then
60-
ln -s libdarknet.so libdarknet.dylib
61+
ln -s libdarknet.so libdarknet.dylib
6162
fi

0 commit comments

Comments
 (0)