mirror of
https://github.com/LdDl/go-darknet.git
synced 2025-10-01 14:02:12 +08:00
Compare commits
8 Commits
add-licens
...
examples
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7f94c3bdcc | ||
![]() |
e5d170ef8b | ||
![]() |
85730b925c | ||
![]() |
55221029de | ||
![]() |
e0a6735667 | ||
![]() |
c9bbd3eee4 | ||
![]() |
5539377f1c | ||
![]() |
10cd5f6e1a |
26
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
26
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: "[BUG]"
|
||||||
|
labels: bug, help wanted
|
||||||
|
assignees: LdDl
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Describe the solution you'd like and provide pseudocode examples if you can**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: "[FEATURE REQUEST]"
|
||||||
|
labels: enhancement
|
||||||
|
assignees: LdDl
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is.
|
||||||
|
|
||||||
|
**Describe the solution you'd like and provide pseudocode examples if you can**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered and provide pseudocode examples if you can**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
55
Makefile
Normal file
55
Makefile
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
.ONESHELL:
|
||||||
|
.PHONY: download build clean
|
||||||
|
|
||||||
|
# Latest battletested AlexeyAB version of Darknet commit
|
||||||
|
LATEST_COMMIT?=d65909fbea471d06e52a2e4a41132380dc2edaa6
|
||||||
|
|
||||||
|
# Temporary folder for building Darknet
|
||||||
|
TMP_DIR?=/tmp/
|
||||||
|
|
||||||
|
# Download AlexeyAB version of Darknet
|
||||||
|
download:
|
||||||
|
rm -rf $(TMP_DIR)install_darknet
|
||||||
|
mkdir $(TMP_DIR)install_darknet
|
||||||
|
git clone https://github.com/AlexeyAB/darknet.git $(TMP_DIR)install_darknet
|
||||||
|
cd $(TMP_DIR)install_darknet
|
||||||
|
git checkout $(LATEST_COMMIT)
|
||||||
|
cd -
|
||||||
|
|
||||||
|
# Build AlexeyAB version of Darknet for usage with CPU only.
|
||||||
|
build:
|
||||||
|
cd $(TMP_DIR)install_darknet
|
||||||
|
sed -i -e 's/GPU=1/GPU=0/g' Makefile
|
||||||
|
sed -i -e 's/CUDNN=1/CUDNN=0/g' Makefile
|
||||||
|
sed -i -e 's/LIBSO=0/LIBSO=1/g' Makefile
|
||||||
|
$(MAKE) -j $(shell nproc --all)
|
||||||
|
$(MAKE) preinstall
|
||||||
|
cd -
|
||||||
|
|
||||||
|
# Build AlexeyAB version of Darknet for usage with both CPU and GPU (CUDA by NVIDIA).
|
||||||
|
build_gpu:
|
||||||
|
cd $(TMP_DIR)install_darknet
|
||||||
|
sed -i -e 's/GPU=0/GPU=1/g' Makefile
|
||||||
|
sed -i -e 's/CUDNN=0/CUDNN=1/g' Makefile
|
||||||
|
sed -i -e 's/LIBSO=0/LIBSO=1/g' Makefile
|
||||||
|
$(MAKE) -j $(shell nproc --all)
|
||||||
|
$(MAKE) preinstall
|
||||||
|
cd -
|
||||||
|
|
||||||
|
# Install system wide.
|
||||||
|
sudo_install:
|
||||||
|
cd $(TMP_DIR)install_darknet
|
||||||
|
sudo cp libdarknet.so /usr/lib/libdarknet.so
|
||||||
|
sudo cp include/darknet.h /usr/include/darknet.h
|
||||||
|
sudo ldconfig
|
||||||
|
cd -
|
||||||
|
|
||||||
|
# Cleanup temporary files for building process
|
||||||
|
clean:
|
||||||
|
rm -rf $(TMP_DIR)install_darknet
|
||||||
|
|
||||||
|
# Do every step for CPU-based only build.
|
||||||
|
install: download build sudo_install clean
|
||||||
|
|
||||||
|
# Do every step for both CPU and GPU-based build.
|
||||||
|
install_gpu: download build_gpu sudo_install clean
|
183
README.md
183
README.md
@@ -3,7 +3,6 @@
|
|||||||
[](https://goreportcard.com/report/github.com/LdDl/go-darknet)
|
[](https://goreportcard.com/report/github.com/LdDl/go-darknet)
|
||||||
[](https://github.com/LdDl/go-darknet/releases)
|
[](https://github.com/LdDl/go-darknet/releases)
|
||||||
|
|
||||||
|
|
||||||
# go-darknet: Go bindings for Darknet (Yolo V4, Yolo V3)
|
# go-darknet: Go bindings for Darknet (Yolo V4, Yolo V3)
|
||||||
### go-darknet is a Go package, which uses Cgo to enable Go applications to use YOLO V4/V3 in [Darknet].
|
### go-darknet is a Go package, which uses Cgo to enable Go applications to use YOLO V4/V3 in [Darknet].
|
||||||
|
|
||||||
@@ -23,29 +22,20 @@
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
For proper codebase please use fork of [darknet](https://github.com/AlexeyAB/darknet). Latest commit I've tested [here](https://github.com/AlexeyAB/darknet/commit/9dc897d2c77d5ef43a6b237b717437375765b527)
|
You need to install fork of [darknet](https://github.com/AlexeyAB/darknet). Latest commit I've tested is [here](https://github.com/AlexeyAB/darknet/commit/d65909fbea471d06e52a2e4a41132380dc2edaa6)
|
||||||
|
|
||||||
In order to use go-darknet, `libdarknet.so` should be available in one of
|
Use provided [Makefile](Makefile).
|
||||||
the following locations:
|
|
||||||
|
|
||||||
* /usr/lib
|
* For CPU-based instalattion:
|
||||||
* /usr/local/lib
|
```shell
|
||||||
|
make install
|
||||||
|
```
|
||||||
|
* For both CPU and GPU-based instalattion:
|
||||||
|
```shell
|
||||||
|
make install_gpu
|
||||||
|
```
|
||||||
|
Note: If you want to have GPU-acceleration before running command above install [CUDA](https://developer.nvidia.com/cuda-downloads) and [cuDNN](https://developer.nvidia.com/cudnn) (Latest CUDA version I've tested is [10.2](https://developer.nvidia.com/cuda-10.2-download-archive) and cuDNN is [7.6.5](https://developer.nvidia.com/rdp/cudnn-archive#a-collapse765-102))
|
||||||
|
|
||||||
Also, [darknet.h] should be available in one of the following locations:
|
|
||||||
|
|
||||||
* /usr/include
|
|
||||||
* /usr/local/include
|
|
||||||
|
|
||||||
To achieve it, after Darknet compilation (via make) execute following command:
|
|
||||||
```shell
|
|
||||||
# Copy *.so to /usr/lib + /usr/include (or /usr/local/lib + /usr/local/include)
|
|
||||||
sudo cp libdarknet.so /usr/lib/libdarknet.so && sudo cp include/darknet.h /usr/include/darknet.h
|
|
||||||
# sudo cp libdarknet.so /usr/local/lib/libdarknet.so && sudo cp include/darknet.h /usr/local/include/darknet.h
|
|
||||||
```
|
|
||||||
Note: do not forget to set LIBSO=1 in Makefile before executing 'make':
|
|
||||||
```Makefile
|
|
||||||
LIBSO=1
|
|
||||||
```
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
@@ -58,87 +48,88 @@ Example Go program is provided in the [example] directory. Please refer to the c
|
|||||||
|
|
||||||
Building and running program:
|
Building and running program:
|
||||||
|
|
||||||
Navigate to [example] folder
|
* Navigate to [example] folder
|
||||||
```shell
|
```shell
|
||||||
cd $GOPATH/github.com/LdDl/go-darknet/example
|
cd $GOPATH/github.com/LdDl/go-darknet/example/base_example
|
||||||
```
|
```
|
||||||
|
|
||||||
Download dataset (sample of image, coco.names, yolov4.cfg (or v3), yolov4.weights(or v3)).
|
* Download dataset (sample of image, coco.names, yolov4.cfg (or v3), yolov4.weights(or v3)).
|
||||||
```shell
|
```shell
|
||||||
#for yolo v4
|
#for yolo v4
|
||||||
./download_data.sh
|
./download_data.sh
|
||||||
#for yolo v3
|
#for yolo v3
|
||||||
./download_data_v3.sh
|
./download_data_v3.sh
|
||||||
```
|
```
|
||||||
Note: you don't need *coco.data* file anymore, because sh-script above does insert *coco.names* into 'names' field in *yolov4.cfg* file (so AlexeyAB's fork can deal with it properly)
|
* Note: you don't need *coco.data* file anymore, because sh-script above does insert *coco.names* into 'names' field in *yolov4.cfg* file (so AlexeyAB's fork can deal with it properly)
|
||||||
So last rows in yolov4.cfg file will look like:
|
So last rows in yolov4.cfg file will look like:
|
||||||
```bash
|
```bash
|
||||||
......
|
......
|
||||||
[yolo]
|
[yolo]
|
||||||
.....
|
.....
|
||||||
iou_loss=ciou
|
iou_loss=ciou
|
||||||
nms_kind=greedynms
|
nms_kind=greedynms
|
||||||
beta_nms=0.6
|
beta_nms=0.6
|
||||||
|
|
||||||
names = coco.names # this is path to coco.names file
|
names = coco.names # this is path to coco.names file
|
||||||
```
|
```
|
||||||
Also do not forget change batch and subdivisions sizes from:
|
|
||||||
```shell
|
* Also do not forget change batch and subdivisions sizes from:
|
||||||
batch=64
|
```shell
|
||||||
subdivisions=8
|
batch=64
|
||||||
```
|
subdivisions=8
|
||||||
to
|
```
|
||||||
```shell
|
to
|
||||||
batch=1
|
```shell
|
||||||
subdivisions=1
|
batch=1
|
||||||
```
|
subdivisions=1
|
||||||
It will reduce amount of VRAM used for detector test.
|
```
|
||||||
|
It will reduce amount of VRAM used for detector test.
|
||||||
|
|
||||||
|
|
||||||
Build and run program
|
* Build and run program
|
||||||
Yolo V4:
|
Yolo V4:
|
||||||
```shell
|
```shell
|
||||||
go build main.go && ./main --configFile=yolov4.cfg --weightsFile=yolov4.weights --imageFile=sample.jpg
|
go build main.go && ./main --configFile=yolov4.cfg --weightsFile=yolov4.weights --imageFile=sample.jpg
|
||||||
```
|
```
|
||||||
|
|
||||||
Output should be something like this:
|
Output should be something like this:
|
||||||
```shell
|
```shell
|
||||||
traffic light (9): 73.5039% | start point: (238,73) | end point: (251, 106)
|
traffic light (9): 73.5039% | start point: (238,73) | end point: (251, 106)
|
||||||
truck (7): 96.6401% | start point: (95,79) | end point: (233, 287)
|
truck (7): 96.6401% | start point: (95,79) | end point: (233, 287)
|
||||||
truck (7): 96.4774% | start point: (662,158) | end point: (800, 321)
|
truck (7): 96.4774% | start point: (662,158) | end point: (800, 321)
|
||||||
truck (7): 96.1841% | start point: (0,77) | end point: (86, 333)
|
truck (7): 96.1841% | start point: (0,77) | end point: (86, 333)
|
||||||
truck (7): 46.8695% | start point: (434,173) | end point: (559, 216)
|
truck (7): 46.8695% | start point: (434,173) | end point: (559, 216)
|
||||||
car (2): 99.7370% | start point: (512,188) | end point: (741, 329)
|
car (2): 99.7370% | start point: (512,188) | end point: (741, 329)
|
||||||
car (2): 99.2533% | start point: (260,191) | end point: (422, 322)
|
car (2): 99.2533% | start point: (260,191) | end point: (422, 322)
|
||||||
car (2): 99.0333% | start point: (425,201) | end point: (547, 309)
|
car (2): 99.0333% | start point: (425,201) | end point: (547, 309)
|
||||||
car (2): 83.3919% | start point: (386,210) | end point: (437, 287)
|
car (2): 83.3919% | start point: (386,210) | end point: (437, 287)
|
||||||
car (2): 75.8621% | start point: (73,199) | end point: (102, 274)
|
car (2): 75.8621% | start point: (73,199) | end point: (102, 274)
|
||||||
car (2): 39.1925% | start point: (386,206) | end point: (442, 240)
|
car (2): 39.1925% | start point: (386,206) | end point: (442, 240)
|
||||||
bicycle (1): 76.3121% | start point: (189,298) | end point: (253, 402)
|
bicycle (1): 76.3121% | start point: (189,298) | end point: (253, 402)
|
||||||
person (0): 97.7213% | start point: (141,129) | end point: (283, 362)
|
person (0): 97.7213% | start point: (141,129) | end point: (283, 362)
|
||||||
```
|
```
|
||||||
|
|
||||||
Yolo V3:
|
Yolo V3:
|
||||||
```
|
```
|
||||||
go build main.go && ./main --configFile=yolov3.cfg --weightsFile=yolov3.weights --imageFile=sample.jpg
|
go build main.go && ./main --configFile=yolov3.cfg --weightsFile=yolov3.weights --imageFile=sample.jpg
|
||||||
```
|
```
|
||||||
|
|
||||||
Output should be something like this:
|
Output should be something like this:
|
||||||
```shell
|
```shell
|
||||||
truck (7): 49.5197% | start point: (0,136) | end point: (85, 311)
|
truck (7): 49.5197% | start point: (0,136) | end point: (85, 311)
|
||||||
car (2): 36.3747% | start point: (95,152) | end point: (186, 283)
|
car (2): 36.3747% | start point: (95,152) | end point: (186, 283)
|
||||||
truck (7): 48.4384% | start point: (95,152) | end point: (186, 283)
|
truck (7): 48.4384% | start point: (95,152) | end point: (186, 283)
|
||||||
truck (7): 45.6590% | start point: (694,178) | end point: (798, 310)
|
truck (7): 45.6590% | start point: (694,178) | end point: (798, 310)
|
||||||
car (2): 76.8379% | start point: (1,145) | end point: (84, 324)
|
car (2): 76.8379% | start point: (1,145) | end point: (84, 324)
|
||||||
truck (7): 25.5731% | start point: (107,89) | end point: (215, 263)
|
truck (7): 25.5731% | start point: (107,89) | end point: (215, 263)
|
||||||
car (2): 99.8783% | start point: (511,185) | end point: (748, 328)
|
car (2): 99.8783% | start point: (511,185) | end point: (748, 328)
|
||||||
car (2): 99.8194% | start point: (261,189) | end point: (427, 322)
|
car (2): 99.8194% | start point: (261,189) | end point: (427, 322)
|
||||||
car (2): 99.6408% | start point: (426,197) | end point: (539, 311)
|
car (2): 99.6408% | start point: (426,197) | end point: (539, 311)
|
||||||
car (2): 74.5610% | start point: (692,186) | end point: (796, 316)
|
car (2): 74.5610% | start point: (692,186) | end point: (796, 316)
|
||||||
car (2): 72.8053% | start point: (388,206) | end point: (437, 276)
|
car (2): 72.8053% | start point: (388,206) | end point: (437, 276)
|
||||||
bicycle (1): 72.2932% | start point: (178,270) | end point: (268, 406)
|
bicycle (1): 72.2932% | start point: (178,270) | end point: (268, 406)
|
||||||
person (0): 97.3026% | start point: (143,135) | end point: (268, 343)
|
person (0): 97.3026% | start point: (143,135) | end point: (268, 343)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
@@ -154,5 +145,5 @@ go-darknet follows [Darknet]'s [license].
|
|||||||
[darknet.h]: https://github.com/AlexeyAB/darknet/blob/master/include/darknet.h
|
[darknet.h]: https://github.com/AlexeyAB/darknet/blob/master/include/darknet.h
|
||||||
[include/darknet.h]: https://github.com/AlexeyAB/darknet/blob/master/include/darknet.h
|
[include/darknet.h]: https://github.com/AlexeyAB/darknet/blob/master/include/darknet.h
|
||||||
[Makefile]: https://github.com/alexeyab/darknet/blob/master/Makefile
|
[Makefile]: https://github.com/alexeyab/darknet/blob/master/Makefile
|
||||||
[example]: /example
|
[example]: /example/base_example
|
||||||
[GoDoc]: https://godoc.org/github.com/LdDl/go-darknet
|
[GoDoc]: https://godoc.org/github.com/LdDl/go-darknet
|
||||||
|
@@ -8,12 +8,12 @@ This is an example Go application which uses go-darknet.
|
|||||||
Navigate to example folder:
|
Navigate to example folder:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
cd $GOPATH/github.com/LdDl/go-darknet/example
|
cd $GOPATH/github.com/LdDl/go-darknet/example/base_example
|
||||||
```
|
```
|
||||||
|
|
||||||
Download dataset (sample of image, coco.names, yolov3.cfg, yolov3.weights).
|
Download dataset (sample of image, coco.names, yolov3.cfg, yolov3.weights).
|
||||||
```shell
|
```shell
|
||||||
./download_data.sh
|
./download_data_v3.sh
|
||||||
```
|
```
|
||||||
Note: you don't need *coco.data* file anymore, because script below does insert *coco.names* into 'names' filed in *yolov3.cfg* file (so AlexeyAB's fork can deal with it properly)
|
Note: you don't need *coco.data* file anymore, because script below does insert *coco.names* into 'names' filed in *yolov3.cfg* file (so AlexeyAB's fork can deal with it properly)
|
||||||
So last rows in yolov3.cfg file will look like:
|
So last rows in yolov3.cfg file will look like:
|
221
example/rest_example/README.md
Normal file
221
example/rest_example/README.md
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
# Example Go application using go-darknet and REST
|
||||||
|
|
||||||
|
This is an example Go server application (in terms of REST) which uses go-darknet.
|
||||||
|
|
||||||
|
## Run
|
||||||
|
|
||||||
|
Navigate to example folder:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
cd $GOPATH/github.com/LdDl/go-darknet/example/rest_example
|
||||||
|
```
|
||||||
|
|
||||||
|
Download dataset (sample of image, coco.names, yolov3.cfg, yolov3.weights).
|
||||||
|
```shell
|
||||||
|
./download_data_v3.sh
|
||||||
|
```
|
||||||
|
Note: you don't need *coco.data* file anymore, because script below does insert *coco.names* into 'names' filed in *yolov3.cfg* file (so AlexeyAB's fork can deal with it properly)
|
||||||
|
So last rows in yolov3.cfg file will look like:
|
||||||
|
```bash
|
||||||
|
......
|
||||||
|
[yolo]
|
||||||
|
mask = 0,1,2
|
||||||
|
anchors = 10,13, 16,30, 33,23, 30,61, 62,45, 59,119, 116,90, 156,198, 373,326
|
||||||
|
classes=80
|
||||||
|
num=9
|
||||||
|
jitter=.3
|
||||||
|
ignore_thresh = .7
|
||||||
|
truth_thresh = 1
|
||||||
|
random=1
|
||||||
|
names = coco.names # this is path to coco.names file
|
||||||
|
```
|
||||||
|
|
||||||
|
Build and run program
|
||||||
|
```
|
||||||
|
go build main.go && ./main --configFile=yolov3.cfg --weightsFile=yolov3.weights --port 8090
|
||||||
|
```
|
||||||
|
|
||||||
|
After server started check if REST-requests works. We provide cURL-based example
|
||||||
|
```shell
|
||||||
|
curl -F 'image=@sample.jpg' 'http://localhost:8090/detect_objects'
|
||||||
|
```
|
||||||
|
|
||||||
|
Servers response should be something like this:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"net_time": "43.269289ms",
|
||||||
|
"overall_time": "43.551604ms",
|
||||||
|
"num_detections": 44,
|
||||||
|
"detections": [
|
||||||
|
{
|
||||||
|
"class_id": 7,
|
||||||
|
"class_name": "truck",
|
||||||
|
"probability": 49.51231,
|
||||||
|
"start_point": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 136
|
||||||
|
},
|
||||||
|
"end_point": {
|
||||||
|
"x": 85,
|
||||||
|
"y": 311
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_id": 2,
|
||||||
|
"class_name": "car",
|
||||||
|
"probability": 36.36933,
|
||||||
|
"start_point": {
|
||||||
|
"x": 95,
|
||||||
|
"y": 152
|
||||||
|
},
|
||||||
|
"end_point": {
|
||||||
|
"x": 186,
|
||||||
|
"y": 283
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_id": 7,
|
||||||
|
"class_name": "truck",
|
||||||
|
"probability": 48.417683,
|
||||||
|
"start_point": {
|
||||||
|
"x": 95,
|
||||||
|
"y": 152
|
||||||
|
},
|
||||||
|
"end_point": {
|
||||||
|
"x": 186,
|
||||||
|
"y": 283
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_id": 7,
|
||||||
|
"class_name": "truck",
|
||||||
|
"probability": 45.652023,
|
||||||
|
"start_point": {
|
||||||
|
"x": 694,
|
||||||
|
"y": 178
|
||||||
|
},
|
||||||
|
"end_point": {
|
||||||
|
"x": 798,
|
||||||
|
"y": 310
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_id": 2,
|
||||||
|
"class_name": "car",
|
||||||
|
"probability": 76.8402,
|
||||||
|
"start_point": {
|
||||||
|
"x": 1,
|
||||||
|
"y": 145
|
||||||
|
},
|
||||||
|
"end_point": {
|
||||||
|
"x": 84,
|
||||||
|
"y": 324
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_id": 7,
|
||||||
|
"class_name": "truck",
|
||||||
|
"probability": 25.592052,
|
||||||
|
"start_point": {
|
||||||
|
"x": 107,
|
||||||
|
"y": 89
|
||||||
|
},
|
||||||
|
"end_point": {
|
||||||
|
"x": 215,
|
||||||
|
"y": 263
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_id": 2,
|
||||||
|
"class_name": "car",
|
||||||
|
"probability": 99.87823,
|
||||||
|
"start_point": {
|
||||||
|
"x": 511,
|
||||||
|
"y": 185
|
||||||
|
},
|
||||||
|
"end_point": {
|
||||||
|
"x": 748,
|
||||||
|
"y": 328
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_id": 2,
|
||||||
|
"class_name": "car",
|
||||||
|
"probability": 99.819336,
|
||||||
|
"start_point": {
|
||||||
|
"x": 261,
|
||||||
|
"y": 189
|
||||||
|
},
|
||||||
|
"end_point": {
|
||||||
|
"x": 427,
|
||||||
|
"y": 322
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_id": 2,
|
||||||
|
"class_name": "car",
|
||||||
|
"probability": 99.64055,
|
||||||
|
"start_point": {
|
||||||
|
"x": 426,
|
||||||
|
"y": 197
|
||||||
|
},
|
||||||
|
"end_point": {
|
||||||
|
"x": 539,
|
||||||
|
"y": 311
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_id": 2,
|
||||||
|
"class_name": "car",
|
||||||
|
"probability": 74.56263,
|
||||||
|
"start_point": {
|
||||||
|
"x": 692,
|
||||||
|
"y": 186
|
||||||
|
},
|
||||||
|
"end_point": {
|
||||||
|
"x": 796,
|
||||||
|
"y": 316
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_id": 2,
|
||||||
|
"class_name": "car",
|
||||||
|
"probability": 72.79756,
|
||||||
|
"start_point": {
|
||||||
|
"x": 388,
|
||||||
|
"y": 206
|
||||||
|
},
|
||||||
|
"end_point": {
|
||||||
|
"x": 437,
|
||||||
|
"y": 276
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_id": 1,
|
||||||
|
"class_name": "bicycle",
|
||||||
|
"probability": 72.27595,
|
||||||
|
"start_point": {
|
||||||
|
"x": 178,
|
||||||
|
"y": 270
|
||||||
|
},
|
||||||
|
"end_point": {
|
||||||
|
"x": 268,
|
||||||
|
"y": 406
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"class_id": 0,
|
||||||
|
"class_name": "person",
|
||||||
|
"probability": 97.30075,
|
||||||
|
"start_point": {
|
||||||
|
"x": 143,
|
||||||
|
"y": 135
|
||||||
|
},
|
||||||
|
"end_point": {
|
||||||
|
"x": 268,
|
||||||
|
"y": 343
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
140
example/rest_example/main.go
Normal file
140
example/rest_example/main.go
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
_ "image/jpeg"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/LdDl/go-darknet"
|
||||||
|
)
|
||||||
|
|
||||||
|
var configFile = flag.String("configFile", "",
|
||||||
|
"Path to network layer configuration file. Example: cfg/yolov3.cfg")
|
||||||
|
var weightsFile = flag.String("weightsFile", "",
|
||||||
|
"Path to weights file. Example: yolov3.weights")
|
||||||
|
var serverPort = flag.Int("port", 8090,
|
||||||
|
"Listening port")
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if *configFile == "" || *weightsFile == "" {
|
||||||
|
flag.Usage()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
n := darknet.YOLONetwork{
|
||||||
|
GPUDeviceIndex: 0,
|
||||||
|
NetworkConfigurationFile: *configFile,
|
||||||
|
WeightsFile: *weightsFile,
|
||||||
|
Threshold: .25,
|
||||||
|
}
|
||||||
|
if err := n.Init(); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer n.Close()
|
||||||
|
|
||||||
|
http.HandleFunc("/detect_objects", detectObjects(&n))
|
||||||
|
http.ListenAndServe(fmt.Sprintf(":%d", *serverPort), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DarknetResp Response
|
||||||
|
type DarknetResp struct {
|
||||||
|
NetTime string `json:"net_time"`
|
||||||
|
OverallTime string `json:"overall_time"`
|
||||||
|
Detections []*DarknetDetection `json:"detections"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DarknetDetection Information about single detection
|
||||||
|
type DarknetDetection struct {
|
||||||
|
ClassID int `json:"class_id"`
|
||||||
|
ClassName string `json:"class_name"`
|
||||||
|
Probability float32 `json:"probability"`
|
||||||
|
StartPoint *DarknetPoint `json:"start_point"`
|
||||||
|
EndPoint *DarknetPoint `json:"end_point"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DarknetPoint image.Image point
|
||||||
|
type DarknetPoint struct {
|
||||||
|
X int `json:"x"`
|
||||||
|
Y int `json:"y"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func detectObjects(n *darknet.YOLONetwork) func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
return func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
// Restrict file size up to 10mb
|
||||||
|
req.ParseMultipartForm(10 << 20)
|
||||||
|
|
||||||
|
file, _, err := req.FormFile("image")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(w, fmt.Sprintf("Error reading FormFile: %s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
fileBytes, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(w, fmt.Sprintf("Error reading bytes: %s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
imgSrc, _, err := image.Decode(bytes.NewReader(fileBytes))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(w, fmt.Sprintf("Error decoding bytes to image: %s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
imgDarknet, err := darknet.Image2Float32(imgSrc)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(w, fmt.Sprintf("Error converting image.Image to darknet.DarknetImage: %s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer imgDarknet.Close()
|
||||||
|
|
||||||
|
dr, err := n.Detect(imgDarknet)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(w, fmt.Sprintf("Error detecting objects: %s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := DarknetResp{
|
||||||
|
NetTime: fmt.Sprintf("%v", dr.NetworkOnlyTimeTaken),
|
||||||
|
OverallTime: fmt.Sprintf("%v", dr.OverallTimeTaken),
|
||||||
|
Detections: []*DarknetDetection{},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, d := range dr.Detections {
|
||||||
|
for i := range d.ClassIDs {
|
||||||
|
bBox := d.BoundingBox
|
||||||
|
resp.Detections = append(resp.Detections, &DarknetDetection{
|
||||||
|
ClassID: d.ClassIDs[i],
|
||||||
|
ClassName: d.ClassNames[i],
|
||||||
|
Probability: d.Probabilities[i],
|
||||||
|
StartPoint: &DarknetPoint{
|
||||||
|
X: bBox.StartPoint.X,
|
||||||
|
Y: bBox.StartPoint.Y,
|
||||||
|
},
|
||||||
|
EndPoint: &DarknetPoint{
|
||||||
|
X: bBox.EndPoint.X,
|
||||||
|
Y: bBox.EndPoint.Y,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
respBytes, err := json.Marshal(resp)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(w, fmt.Sprintf("Error encoding response: %s", err.Error()))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(w, string(respBytes))
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user