Merge pull request #14 from LdDl/examples

Examples
This commit is contained in:
Dimitrii Lopanov
2020-10-16 12:55:53 +03:00
committed by GitHub
5 changed files with 365 additions and 4 deletions

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

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