mirror of
				https://github.com/LdDl/go-darknet.git
				synced 2025-10-31 02:56:26 +08:00 
			
		
		
		
	Compare commits
	
		
			16 Commits
		
	
	
		
			add-licens
			...
			issue-15
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 40df8cce91 | ||
|   | 13a0697585 | ||
|   | 29e4d0d8bb | ||
|   | 165e59aaf3 | ||
|   | 81223ac67d | ||
|   | 7cbe2f50a7 | ||
|   | 6a381223fa | ||
|   | a039e75b22 | ||
|   | 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. | ||||
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,4 @@ | ||||
| example/main | ||||
| example/sample.jpg | ||||
| example/coco.names | ||||
| example/yolov3.cfg | ||||
| example/yolov3.weights | ||||
|   | ||||
							
								
								
									
										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?=f056fc3b6a11528fa0522a468eca1e909b7004b7 | ||||
|  | ||||
| # 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 | ||||
							
								
								
									
										43
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								README.md
									
									
									
									
									
								
							| @@ -3,7 +3,6 @@ | ||||
| [](https://goreportcard.com/report/github.com/LdDl/go-darknet) | ||||
| [](https://github.com/LdDl/go-darknet/releases) | ||||
|  | ||||
|  | ||||
| # 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]. | ||||
|  | ||||
| @@ -23,29 +22,20 @@ | ||||
|  | ||||
| ## 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 | ||||
| the following locations: | ||||
| Use provided [Makefile](Makefile). | ||||
|  | ||||
| * /usr/lib | ||||
| * /usr/local/lib | ||||
|  | ||||
| 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: | ||||
| * For CPU-based instalattion: | ||||
|     ```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 | ||||
|     make install | ||||
|     ``` | ||||
| Note: do not forget to set LIBSO=1 in Makefile before executing 'make': | ||||
| ```Makefile | ||||
| LIBSO=1 | ||||
| * 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)) | ||||
|  | ||||
| ## Installation | ||||
|  | ||||
| ```shell | ||||
| @@ -58,19 +48,19 @@ Example Go program is provided in the [example] directory. Please refer to the c | ||||
|  | ||||
| Building and running program: | ||||
|  | ||||
| Navigate to [example] folder | ||||
| * 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)). | ||||
| * Download dataset (sample of image, coco.names, yolov4.cfg (or v3), yolov4.weights(or v3)). | ||||
|     ```shell | ||||
|     #for yolo v4 | ||||
|     ./download_data.sh | ||||
|     #for yolo v3 | ||||
|     ./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: | ||||
|     ```bash | ||||
|     ...... | ||||
| @@ -82,7 +72,8 @@ beta_nms=0.6 | ||||
|  | ||||
|     names = coco.names # this is path to coco.names file | ||||
|     ``` | ||||
| Also do not forget change batch and subdivisions sizes from: | ||||
|  | ||||
| * Also do not forget change batch and subdivisions sizes from: | ||||
|     ```shell | ||||
|     batch=64 | ||||
|     subdivisions=8 | ||||
| @@ -95,7 +86,7 @@ subdivisions=1 | ||||
|     It will reduce amount of VRAM used for detector test. | ||||
|  | ||||
|  | ||||
| Build and run program | ||||
| * Build and run program | ||||
|     Yolo V4: | ||||
|     ```shell | ||||
|     go build main.go && ./main --configFile=yolov4.cfg --weightsFile=yolov4.weights --imageFile=sample.jpg | ||||
| @@ -154,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: | ||||
| @@ -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) { | ||||
							
								
								
									
										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)) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								example/sample.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								example/sample.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 134 KiB | 
| @@ -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) { | ||||
|   | ||||
| @@ -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 | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user