mirror of
https://github.com/LdDl/go-darknet.git
synced 2025-09-27 03:56:18 +08:00
@@ -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
|
||||
|
@@ -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:
|
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