13 Commits

Author SHA1 Message Date
Dimitrii Lopanov
b8f4ad6d57 Merge pull request #16 from LdDl/issue-15
Issue 15
2021-02-01 08:07:24 +03:00
Dimitrii
40df8cce91 free_network_ptr instead of free_network 2021-01-30 13:57:21 +03:00
Dimitrii
13a0697585 remove sleep 2021-01-28 14:26:52 +03:00
Dimitrii
29e4d0d8bb clean 2021-01-28 14:20:38 +03:00
Dimitrii
165e59aaf3 remove defer for image 2021-01-28 14:20:08 +03:00
Dimitrii
81223ac67d start solving issue 2021-01-28 13:43:35 +03:00
Dimitrii Lopanov
7cbe2f50a7 load file 2020-10-16 13:20:22 +03:00
Dimitrii Lopanov
6a381223fa provide example picture 2020-10-16 13:18:39 +03:00
Dimitrii Lopanov
a039e75b22 Merge pull request #14 from LdDl/examples
Examples
2020-10-16 12:55:53 +03:00
Dimitrii Lopanov
7f94c3bdcc readme and minor 2020-10-16 12:52:56 +03:00
Dimitrii Lopanov
e5d170ef8b inital rest example 2020-10-16 12:14:06 +03:00
Dimitrii Lopanov
85730b925c move base example to its own folder 2020-10-16 11:02:59 +03:00
Dimitrii Lopanov
55221029de Merge pull request #13 from LdDl/install-darknet
makefile and minor
2020-10-16 10:58:46 +03:00
10 changed files with 374 additions and 12 deletions

1
.gitignore vendored
View File

@@ -1,5 +1,4 @@
example/main
example/sample.jpg
example/coco.names
example/yolov3.cfg
example/yolov3.weights

View File

@@ -2,7 +2,7 @@
.PHONY: download build clean
# Latest battletested AlexeyAB version of Darknet commit
LATEST_COMMIT?=d65909fbea471d06e52a2e4a41132380dc2edaa6
LATEST_COMMIT?=f056fc3b6a11528fa0522a468eca1e909b7004b7
# Temporary folder for building Darknet
TMP_DIR?=/tmp/

View File

@@ -50,7 +50,7 @@ Building and running program:
* Navigate to [example] folder
```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)).
@@ -145,5 +145,5 @@ go-darknet follows [Darknet]'s [license].
[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
[example]: /example
[example]: /example/base_example
[GoDoc]: https://godoc.org/github.com/LdDl/go-darknet

View File

@@ -8,12 +8,12 @@ This is an example Go application which uses go-darknet.
Navigate to example folder:
```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).
```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)
So last rows in yolov3.cfg file will look like:

View File

@@ -9,7 +9,6 @@ import (
"log"
"math"
"os"
darknet "github.com/LdDl/go-darknet"
"github.com/disintegration/imaging"
)
@@ -61,13 +60,13 @@ func main() {
if err != nil {
panic(err.Error())
}
defer imgDarknet.Close()
dr, err := n.Detect(imgDarknet)
if err != nil {
printError(err)
return
}
imgDarknet.Close()
log.Println("Network-only time taken:", dr.NetworkOnlyTimeTaken)
log.Println("Overall time taken:", dr.OverallTimeTaken, len(dr.Detections))
@@ -92,6 +91,8 @@ func main() {
// }
}
}
n.Close()
}
func imageToBytes(img image.Image) ([]byte, error) {

View 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
}
}
]
}
```

View 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))
}
}

BIN
example/sample.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

View File

@@ -14,7 +14,8 @@ struct network_box_result perform_network_detect(network *n, image *img, int cla
sized = resize_image(*img, n->w, n->h);
}
struct network_box_result result = { NULL };
network_predict(*n, sized.data);
// mleak at network_predict(), get_network_boxes() and network_predict_ptr()?
network_predict_ptr(n, sized.data);
int nboxes = 0;
result.detections = get_network_boxes(n, img->w, img->h, thresh, hier_thresh, 0, 1, &result.detections_len, letter_box);
if (nms) {

View File

@@ -58,7 +58,7 @@ func (n *YOLONetwork) Close() error {
if n.cNet == nil {
return errNetworkNotInit
}
C.free_network(*n.cNet)
C.free_network_ptr(n.cNet)
n.cNet = nil
return nil
}
@@ -80,4 +80,4 @@ func (n *YOLONetwork) Detect(img *DarknetImage) (*DetectionResult, error) {
OverallTimeTaken: endTimeOverall.Sub(startTime),
}
return &out, nil
}
}