mirror of
https://github.com/LdDl/go-darknet.git
synced 2025-09-26 19:51:27 +08:00
need to deal with image
This commit is contained in:
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"detection.h": "c",
|
||||
"network.h": "c"
|
||||
}
|
||||
}
|
8
classes.c
Normal file
8
classes.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
char * get_class_name(char **names, int index, int names_len) {
|
||||
if (index >= names_len) {
|
||||
return NULL;
|
||||
}
|
||||
return names[index];
|
||||
}
|
15
classes.go
Normal file
15
classes.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package darknet
|
||||
|
||||
// #include <stdlib.h>
|
||||
// #include "classes.h"
|
||||
import "C"
|
||||
|
||||
func makeClassNames(names **C.char, classes int) []string {
|
||||
out := make([]string, classes)
|
||||
for i := 0; i < classes; i++ {
|
||||
n := C.get_class_name(names, C.int(i), C.int(classes))
|
||||
s := C.GoString(n)
|
||||
out[i] = s
|
||||
}
|
||||
return out
|
||||
}
|
3
classes.h
Normal file
3
classes.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
extern char * get_class_name(char **names, int index, int names_len);
|
@@ -1,5 +1,5 @@
|
||||
package darknet
|
||||
|
||||
// #cgo CFLAGS: -I/usr/local/include -I/usr/local/cuda/include
|
||||
// #cgo LDFLAGS: -L./lib -ldark -lm
|
||||
// #cgo LDFLAGS: -L./lib -ldarknet -lm
|
||||
import "C"
|
||||
|
5
data/names.list
Normal file
5
data/names.list
Normal file
@@ -0,0 +1,5 @@
|
||||
person
|
||||
car
|
||||
motorcycle
|
||||
bus
|
||||
truck
|
22
detection.c
Normal file
22
detection.c
Normal file
@@ -0,0 +1,22 @@
|
||||
#include <darknet.h>
|
||||
|
||||
#include "detection.h"
|
||||
|
||||
|
||||
detection * get_detection(detection *dets, int index, int dets_len)
|
||||
{
|
||||
if (index >= dets_len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dets + index;
|
||||
}
|
||||
|
||||
float get_detection_probability(detection *det, int index, int prob_len)
|
||||
{
|
||||
if (index >= prob_len) {
|
||||
return .0;
|
||||
}
|
||||
|
||||
return det->prob[index];
|
||||
}
|
75
detection.go
75
detection.go
@@ -1,10 +1,81 @@
|
||||
package darknet
|
||||
|
||||
import "time"
|
||||
// #include <darknet.h>
|
||||
//
|
||||
// #include "detection.h"
|
||||
import "C"
|
||||
import (
|
||||
"image"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Detection represents a detection.
|
||||
type Detection struct {
|
||||
BoundingBox
|
||||
|
||||
ClassIDs []int
|
||||
ClassNames []string
|
||||
Probabilities []float32
|
||||
}
|
||||
|
||||
// DetectionResult represents the inference results from the network.
|
||||
type DetectionResult struct {
|
||||
// Detections []*Detection
|
||||
Detections []*Detection
|
||||
NetworkOnlyTimeTaken time.Duration
|
||||
OverallTimeTaken time.Duration
|
||||
}
|
||||
|
||||
func makeDetection(img *DarknetImage, det *C.detection, threshold float32, classes int, classNames []string) *Detection {
|
||||
|
||||
if det == nil {
|
||||
return &Detection{}
|
||||
}
|
||||
|
||||
dClassIDs := make([]int, 0)
|
||||
dClassNames := make([]string, 0)
|
||||
dProbs := make([]float32, 0)
|
||||
|
||||
for i := 0; i < int(classes); i++ {
|
||||
dProb := float32(C.get_detection_probability(det, C.int(i), C.int(classes)))
|
||||
if dProb > threshold {
|
||||
dClassIDs = append(dClassIDs, i)
|
||||
cN := classNames[i]
|
||||
dClassNames = append(dClassNames, cN)
|
||||
dProbs = append(dProbs, dProb*100)
|
||||
}
|
||||
}
|
||||
|
||||
fImgW := C.float(img.Width)
|
||||
fImgH := C.float(img.Height)
|
||||
halfRatioW := det.bbox.w / 2.0
|
||||
halfRatioH := det.bbox.h / 2.0
|
||||
out := Detection{
|
||||
BoundingBox: BoundingBox{
|
||||
StartPoint: image.Point{
|
||||
X: int((det.bbox.x - halfRatioW) * fImgW),
|
||||
Y: int((det.bbox.y - halfRatioH) * fImgH),
|
||||
},
|
||||
EndPoint: image.Point{
|
||||
X: int((det.bbox.x + halfRatioW) * fImgW),
|
||||
Y: int((det.bbox.y + halfRatioH) * fImgH),
|
||||
},
|
||||
},
|
||||
|
||||
ClassIDs: dClassIDs,
|
||||
ClassNames: dClassNames,
|
||||
Probabilities: dProbs,
|
||||
}
|
||||
|
||||
return &out
|
||||
}
|
||||
|
||||
func makeDetections(img *DarknetImage, detections *C.detection, detectionsLength int, threshold float32, classes int, classNames []string) []*Detection {
|
||||
// Make list of detection objects.
|
||||
ds := make([]*Detection, detectionsLength)
|
||||
for i := 0; i < int(detectionsLength); i++ {
|
||||
det := C.get_detection(detections, C.int(i), C.int(detectionsLength))
|
||||
d := makeDetection(img, det, threshold, classes, classNames)
|
||||
ds[i] = d
|
||||
}
|
||||
return ds
|
||||
}
|
||||
|
7
detection.h
Normal file
7
detection.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <darknet.h>
|
||||
|
||||
|
||||
extern detection * get_detection(detection *dets, int index, int dets_len);
|
||||
extern float get_detection_probability(detection *det, int index, int prob_len);
|
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"image/jpeg"
|
||||
"log"
|
||||
"os"
|
||||
@@ -37,7 +38,7 @@ func main() {
|
||||
DataConfigurationFile: *dataConfigFile,
|
||||
NetworkConfigurationFile: *configFile,
|
||||
WeightsFile: *weightsFile,
|
||||
Threshold: .5,
|
||||
Threshold: .25,
|
||||
}
|
||||
if err := n.Init(); err != nil {
|
||||
printError(err)
|
||||
@@ -54,6 +55,7 @@ func main() {
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
_ = src
|
||||
|
||||
imgDarknet, err := darknet.Image2Float32(src)
|
||||
if err != nil {
|
||||
@@ -67,18 +69,18 @@ func main() {
|
||||
return
|
||||
}
|
||||
_ = dr
|
||||
// log.Println("Network-only time taken:", dr.NetworkOnlyTimeTaken)
|
||||
// log.Println("Overall time taken:", dr.OverallTimeTaken, len(dr.Detections))
|
||||
// for _, d := range dr.Detections {
|
||||
|
||||
// for i := range d.ClassIDs {
|
||||
// bBox := d.BoundingBox
|
||||
// fmt.Printf("%s (%d): %.4f%% | start point: (%d,%d) | end point: (%d, %d)\n",
|
||||
// d.ClassNames[i], d.ClassIDs[i],
|
||||
// d.Probabilities[i],
|
||||
// bBox.StartPoint.X, bBox.StartPoint.Y,
|
||||
// bBox.EndPoint.X, bBox.EndPoint.Y,
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
log.Println("Network-only time taken:", dr.NetworkOnlyTimeTaken)
|
||||
log.Println("Overall time taken:", dr.OverallTimeTaken, len(dr.Detections))
|
||||
for _, d := range dr.Detections {
|
||||
for i := range d.ClassIDs {
|
||||
bBox := d.BoundingBox
|
||||
fmt.Printf("%s (%d): %.4f%% | start point: (%d,%d) | end point: (%d, %d)\n",
|
||||
d.ClassNames[i], d.ClassIDs[i],
|
||||
d.Probabilities[i],
|
||||
bBox.StartPoint.X, bBox.StartPoint.Y,
|
||||
bBox.EndPoint.X, bBox.EndPoint.Y,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
18
example/out-sample.png
Normal file
18
example/out-sample.png
Normal file
@@ -0,0 +1,18 @@
|
||||
[
|
||||
{
|
||||
"frame_id":1,
|
||||
"filename":"/home/dimitrii/Downloads/mega.jpg",
|
||||
"objects": [
|
||||
{"class_id":3, "name":"bus", "relative_coordinates":{"center_x":0.475497, "center_y":0.317034, "width":0.175112, "height":0.104746}, "confidence":0.686032},
|
||||
{"class_id":3, "name":"bus", "relative_coordinates":{"center_x":0.278355, "center_y":0.302800, "width":0.087061, "height":0.052067}, "confidence":0.562420},
|
||||
{"class_id":1, "name":"car", "relative_coordinates":{"center_x":0.799558, "center_y":0.643484, "width":0.388328, "height":0.539759}, "confidence":0.942335},
|
||||
{"class_id":1, "name":"car", "relative_coordinates":{"center_x":0.365836, "center_y":0.431383, "width":0.267126, "height":0.156932}, "confidence":0.776083},
|
||||
{"class_id":1, "name":"car", "relative_coordinates":{"center_x":0.513763, "center_y":0.475799, "width":0.301966, "height":0.240549}, "confidence":0.684380},
|
||||
{"class_id":1, "name":"car", "relative_coordinates":{"center_x":0.717148, "center_y":0.516788, "width":0.456320, "height":0.313704}, "confidence":0.584288},
|
||||
{"class_id":1, "name":"car", "relative_coordinates":{"center_x":0.217955, "center_y":0.379872, "width":0.212185, "height":0.101100}, "confidence":0.468769},
|
||||
{"class_id":1, "name":"car", "relative_coordinates":{"center_x":0.126970, "center_y":0.337752, "width":0.035609, "height":0.022990}, "confidence":0.452899},
|
||||
{"class_id":0, "name":"person", "relative_coordinates":{"center_x":0.051506, "center_y":0.369395, "width":0.056224, "height":0.175025}, "confidence":0.978385},
|
||||
{"class_id":0, "name":"person", "relative_coordinates":{"center_x":0.097309, "center_y":0.370574, "width":0.048715, "height":0.142128}, "confidence":0.801452}
|
||||
]
|
||||
}
|
||||
]
|
7
image.c
7
image.c
@@ -14,4 +14,9 @@ image prepare_image(image img, int w, int h, int c){
|
||||
img.h=h;
|
||||
img.c=c;
|
||||
return img;
|
||||
}
|
||||
}
|
||||
|
||||
image new_image(int w, int h, int c){
|
||||
image out = make_image(w, h, c);
|
||||
return out;
|
||||
}
|
||||
|
8
image.go
8
image.go
@@ -46,12 +46,14 @@ func Image2Float32(img image.Image) (DarknetImage, error) {
|
||||
imgDarknet := DarknetImage{
|
||||
Width: width,
|
||||
Height: height,
|
||||
image: C.new_darknet_image(),
|
||||
// image: C.new_darknet_image(),
|
||||
}
|
||||
|
||||
imgDarknet.image = C.prepare_image(imgDarknet.image, C.int(width), C.int(height), 3)
|
||||
imgDarknet.image.data = float_p(ans)
|
||||
// imgDarknet.image = C.prepare_image(imgDarknet.image, C.int(width), C.int(height), 3)
|
||||
// imgDarknet.image.data = float_p(ans)
|
||||
// imgDarknet.image = C.resize_image(imgDarknet.image, 416, 416) // Do we need resize? (detection function actually does it)
|
||||
|
||||
imgDarknet.image = C.load_image_color(C.CString("/home/dimitrii/Downloads/mega.jpg"), 416, 416)
|
||||
|
||||
return imgDarknet, nil
|
||||
}
|
||||
|
3
image.h
3
image.h
@@ -3,4 +3,5 @@
|
||||
#include <darknet.h>
|
||||
|
||||
extern image new_darknet_image();
|
||||
extern image prepare_image(image img, int w, int h, int c);
|
||||
extern image prepare_image(image img, int w, int h, int c);
|
||||
extern image new_image(int w, int h, int c);
|
10
network.c
10
network.c
@@ -4,19 +4,19 @@
|
||||
|
||||
#include "network.h"
|
||||
|
||||
// int get_network_layer_classes(network *n, int index) {
|
||||
// return n->layers[index].classes;
|
||||
// }
|
||||
#include "detection.h"
|
||||
|
||||
struct network_box_result perform_network_detect(network *n, image *img, int classes, float thresh, float hier_thresh, float nms) {
|
||||
image sized = letterbox_image(*img, n->w, n->h);
|
||||
struct network_box_result result = { NULL };
|
||||
float *X = sized.data;
|
||||
network_predict(*n, X);
|
||||
result.detections = get_network_boxes(n, img->w, img->h,thresh, hier_thresh, 0, 1, &result.detections_len, 0);
|
||||
int letter_box = 0;
|
||||
network_predict_ptr(n, X);
|
||||
result.detections = get_network_boxes(n, img->w, img->h, thresh, hier_thresh, 0, 1, &result.detections_len, letter_box);
|
||||
if (nms) {
|
||||
do_nms_sort(result.detections, result.detections_len, classes, nms);
|
||||
}
|
||||
free_image(sized);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
39
network.go
39
network.go
@@ -41,7 +41,18 @@ func (n *YOLONetwork) Init() error {
|
||||
wFile := C.CString(n.WeightsFile)
|
||||
defer C.free(unsafe.Pointer(wFile))
|
||||
|
||||
// GPU device ID must be set before `load_network()` is invoked.
|
||||
// data := C.CString(n.DataConfigurationFile)
|
||||
// defer C.free(unsafe.Pointer(data))
|
||||
|
||||
// inptim := C.CString("/home/dimitrii/Downloads/mega.jpg")
|
||||
// defer C.free(unsafe.Pointer(inptim))
|
||||
|
||||
// outputim := C.CString("/home/dimitrii/work/src/github.com/LdDl/go-darknet/example/out-sample.png")
|
||||
// defer C.free(unsafe.Pointer(outputim))
|
||||
|
||||
// C.test_detector(data, nCfg, wFile, inptim, 0.4, 0.5, 1, 1, 0, outputim, 0, 0)
|
||||
|
||||
// // GPU device ID must be set before `load_network()` is invoked.
|
||||
C.cuda_set_device(C.int(n.GPUDeviceIndex))
|
||||
n.cNet = C.load_network(nCfg, wFile, 0)
|
||||
|
||||
@@ -56,12 +67,11 @@ func (n *YOLONetwork) Init() error {
|
||||
n.hierarchalThreshold = .5
|
||||
|
||||
// Currently NMS is always 0.4.
|
||||
n.nms = .4
|
||||
n.nms = .45
|
||||
|
||||
// n.Classes = int(C.get_network_layer_classes(n.cNet, n.cNet.n-1))
|
||||
// cClassNames := loadClassNames(n.DataConfigurationFile)
|
||||
// defer freeClassNames(cClassNames)
|
||||
// n.ClassNames = makeClassNames(cClassNames, n.Classes)
|
||||
metadata := C.get_metadata(nCfg)
|
||||
n.Classes = int(metadata.classes)
|
||||
n.ClassNames = makeClassNames(metadata.names, n.Classes)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -77,28 +87,21 @@ func (n *YOLONetwork) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Detect specified image.
|
||||
// Detect specified image
|
||||
func (n *YOLONetwork) Detect(img *DarknetImage) (*DetectionResult, error) {
|
||||
if n.cNet == nil {
|
||||
return nil, errNetworkNotInit
|
||||
}
|
||||
|
||||
startTime := time.Now()
|
||||
C.network_predict_image(n.cNet, img.image)
|
||||
// result := C.perform_network_detect(n.cNet, &img.image, C.int(n.Classes), C.float(n.Threshold), C.float(n.hierarchalThreshold), C.float(n.nms))
|
||||
result := C.perform_network_detect(n.cNet, &img.image, C.int(n.Classes), C.float(n.Threshold), C.float(n.hierarchalThreshold), C.float(n.nms))
|
||||
endTime := time.Now()
|
||||
// defer C.free_detections(result.detections, result.detections_len)
|
||||
|
||||
// ds := makeDetections(img, result.detections, int(result.detections_len),
|
||||
// n.Threshold, n.Classes, n.ClassNames)
|
||||
|
||||
defer C.free_detections(result.detections, result.detections_len)
|
||||
ds := makeDetections(img, result.detections, int(result.detections_len), n.Threshold, n.Classes, n.ClassNames)
|
||||
endTimeOverall := time.Now()
|
||||
|
||||
out := DetectionResult{
|
||||
// Detections: ds,
|
||||
Detections: ds,
|
||||
NetworkOnlyTimeTaken: endTime.Sub(startTime),
|
||||
OverallTimeTaken: endTimeOverall.Sub(startTime),
|
||||
}
|
||||
|
||||
return &out, nil
|
||||
}
|
||||
|
@@ -8,4 +8,4 @@ struct network_box_result {
|
||||
};
|
||||
|
||||
extern int get_network_layer_classes(network *n, int index);
|
||||
extern struct network_box_result perform_network_detect(network *n, image *img, int classes, float thresh, float hier_thresh, float nms);
|
||||
extern struct network_box_result perform_network_detect(network *n, image *img, int classes, float thresh, float hier_thresh, float nms);
|
BIN
predictions.jpg
Normal file
BIN
predictions.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.1 MiB |
Reference in New Issue
Block a user