mirror of
https://github.com/LdDl/go-darknet.git
synced 2025-09-26 19:51:27 +08:00
upd git ignore
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -7,4 +7,6 @@ example/yolov3-320.weights
|
||||
example/yolov3-416.cfg
|
||||
example/yolov3-416.weights
|
||||
example/yolov3.cfg
|
||||
example/yolov3.weights
|
||||
example/yolov3.weights
|
||||
darknet.h
|
||||
*.so
|
24
classnames.c
24
classnames.c
@@ -1,24 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <darknet.h>
|
||||
|
||||
void free_class_names(char **names)
|
||||
{
|
||||
free(names);
|
||||
}
|
||||
|
||||
char ** read_class_names(char *data_cfg)
|
||||
{
|
||||
list *options = read_data_cfg(data_cfg);
|
||||
char *name_list = option_find_str(options, "names", "data/names.list");
|
||||
return get_labels(name_list);
|
||||
}
|
||||
|
||||
char * get_class_name(char **names, int index, int names_len)
|
||||
{
|
||||
if (index >= names_len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return names[index];
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
package darknet
|
||||
|
||||
// #include <stdlib.h>
|
||||
// #include "classnames.h"
|
||||
import "C"
|
||||
import "unsafe"
|
||||
|
||||
func freeClassNames(names **C.char) {
|
||||
C.free_class_names(names)
|
||||
}
|
||||
|
||||
func loadClassNames(dataConfigFile string) **C.char {
|
||||
d := C.CString(dataConfigFile)
|
||||
defer C.free(unsafe.Pointer(d))
|
||||
|
||||
return C.read_class_names(d)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
extern void free_class_names(char **names);
|
||||
extern char ** read_class_names(char *data_cfg);
|
||||
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/usr/local/lib -ldarknet -lm
|
||||
// #cgo LDFLAGS: -L./lib -ldark -lm
|
||||
import "C"
|
||||
|
19
detection.c
19
detection.c
@@ -1,19 +0,0 @@
|
||||
#include <darknet.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];
|
||||
}
|
84
detection.go
84
detection.go
@@ -1,84 +0,0 @@
|
||||
package darknet
|
||||
|
||||
// #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
|
||||
NetworkOnlyTimeTaken time.Duration
|
||||
OverallTimeTaken time.Duration
|
||||
}
|
||||
|
||||
func makeDetection(img *Image, 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 *Image, 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(classes))
|
||||
d := makeDetection(img, det, threshold, classes, classNames)
|
||||
ds[i] = d
|
||||
}
|
||||
|
||||
return ds
|
||||
}
|
@@ -1,6 +0,0 @@
|
||||
#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,8 +2,9 @@ package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"image/jpeg"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
darknet "github.com/LdDl/go-darknet"
|
||||
)
|
||||
@@ -44,31 +45,41 @@ func main() {
|
||||
}
|
||||
defer n.Close()
|
||||
|
||||
img, err := darknet.ImageFromPath(*imageFile)
|
||||
infile, err := os.Open(*imageFile)
|
||||
if err != nil {
|
||||
printError(err)
|
||||
return
|
||||
panic(err.Error())
|
||||
}
|
||||
defer img.Close()
|
||||
|
||||
dr, err := n.Detect(img)
|
||||
defer infile.Close()
|
||||
src, err := jpeg.Decode(infile)
|
||||
if err != nil {
|
||||
printError(err)
|
||||
return
|
||||
panic(err.Error())
|
||||
}
|
||||
|
||||
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,
|
||||
)
|
||||
}
|
||||
imgFalot32, err := darknet.Image2Float32(src)
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
_ = imgFalot32
|
||||
// defer img.Close()
|
||||
|
||||
// dr, err := n.Detect(img)
|
||||
// if err != nil {
|
||||
// printError(err)
|
||||
// return
|
||||
// }
|
||||
|
||||
// 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,
|
||||
// )
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
17
image.c
Normal file
17
image.c
Normal file
@@ -0,0 +1,17 @@
|
||||
#include <darknet.h>
|
||||
|
||||
image new_darknet_image() {
|
||||
image img;
|
||||
img.w = 0;
|
||||
img.h = 0;
|
||||
img.c = 0;
|
||||
img.data = NULL;
|
||||
return img;
|
||||
}
|
||||
|
||||
image prepare_image(image img, int w, int h, int c){
|
||||
img.w=w;
|
||||
img.h=h;
|
||||
img.c=c;
|
||||
return img;
|
||||
}
|
82
image.go
82
image.go
@@ -1,66 +1,40 @@
|
||||
package darknet
|
||||
|
||||
// #include <darknet.h>
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"C"
|
||||
"image"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// Image represents the image buffer.
|
||||
type Image struct {
|
||||
Width int
|
||||
Height int
|
||||
// DarknetImage represents the image buffer.
|
||||
// type DarknetImage struct {
|
||||
// Width int
|
||||
// Height int
|
||||
// image C.image
|
||||
// }
|
||||
|
||||
image C.image
|
||||
func float_p(arr []float32) *C.float {
|
||||
return (*C.float)(unsafe.Pointer(&arr[0]))
|
||||
}
|
||||
|
||||
var (
|
||||
errUnableToLoadImage = errors.New("unable to load image")
|
||||
)
|
||||
// Image2Float32 Returns []float32 representation of image.Image
|
||||
func Image2Float32(img image.Image) ([]float32, error) {
|
||||
width := img.Bounds().Dx()
|
||||
height := img.Bounds().Dy()
|
||||
imgwh := width * height
|
||||
imgSize := imgwh * 3
|
||||
|
||||
// Close and release resources.
|
||||
func (img *Image) Close() error {
|
||||
C.free_image(img.image)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ImageFromPath reads image file specified by path.
|
||||
func ImageFromPath(path string) (*Image, error) {
|
||||
p := C.CString(path)
|
||||
defer C.free(unsafe.Pointer(p))
|
||||
|
||||
img := Image{
|
||||
image: C.load_image_color(p, 0, 0),
|
||||
}
|
||||
|
||||
if img.image.data == nil {
|
||||
return nil, errUnableToLoadImage
|
||||
}
|
||||
|
||||
img.Width = int(img.image.w)
|
||||
img.Height = int(img.image.h)
|
||||
|
||||
return &img, nil
|
||||
}
|
||||
|
||||
// ImageFromMemory reads image file data represented by the specified byte
|
||||
// slice.
|
||||
func ImageFromMemory(buf []byte) (*Image, error) {
|
||||
cBuf := C.CBytes(buf)
|
||||
defer C.free(cBuf)
|
||||
|
||||
img := Image{
|
||||
image: C.load_image_from_memory_color((*C.uchar)(cBuf),
|
||||
C.int(len(buf)), 0, 0),
|
||||
}
|
||||
|
||||
if img.image.data == nil {
|
||||
return nil, errUnableToLoadImage
|
||||
}
|
||||
|
||||
img.Width = int(img.image.w)
|
||||
img.Height = int(img.image.h)
|
||||
|
||||
return &img, nil
|
||||
ans := make([]float32, imgSize)
|
||||
for x := 0; x < width; x++ {
|
||||
for y := 0; y < height; y++ {
|
||||
r, g, b, _ := img.At(y, x).RGBA()
|
||||
rpix, gpix, bpix := float32(r>>8)/float32(255.0), float32(g>>8)/float32(255.0), float32(b>>8)/float32(255.0)
|
||||
ans[y+x*height] = rpix
|
||||
ans[y+x*height+imgwh] = gpix
|
||||
ans[y+x*height+imgwh+imgwh] = bpix
|
||||
}
|
||||
}
|
||||
|
||||
return ans, nil
|
||||
}
|
||||
|
6
image.h
Normal file
6
image.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <darknet.h>
|
||||
|
||||
extern image new_darknet_image();
|
||||
extern image prepare_image(image img, int w, int h, int c);
|
36
network.c
36
network.c
@@ -1,22 +1,22 @@
|
||||
#include <stdlib.h>
|
||||
// #include <stdlib.h>
|
||||
|
||||
#include <darknet.h>
|
||||
// #include <darknet.h>
|
||||
|
||||
#include "network.h"
|
||||
// #include "network.h"
|
||||
|
||||
int get_network_layer_classes(network *n, int index) {
|
||||
return n->layers[index].classes;
|
||||
}
|
||||
// int get_network_layer_classes(network *n, int index) {
|
||||
// return n->layers[index].classes;
|
||||
// }
|
||||
|
||||
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);
|
||||
if (nms) {
|
||||
do_nms_sort(result.detections, result.detections_len, classes, nms);
|
||||
}
|
||||
free_image(sized);
|
||||
return result;
|
||||
}
|
||||
// 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);
|
||||
// if (nms) {
|
||||
// do_nms_sort(result.detections, result.detections_len, classes, nms);
|
||||
// }
|
||||
// free_image(sized);
|
||||
// return result;
|
||||
// }
|
||||
|
52
network.go
52
network.go
@@ -8,7 +8,6 @@ package darknet
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@@ -35,6 +34,7 @@ var (
|
||||
|
||||
// Init the network.
|
||||
func (n *YOLONetwork) Init() error {
|
||||
|
||||
nCfg := C.CString(n.NetworkConfigurationFile)
|
||||
defer C.free(unsafe.Pointer(nCfg))
|
||||
wFile := C.CString(n.WeightsFile)
|
||||
@@ -48,7 +48,7 @@ func (n *YOLONetwork) Init() error {
|
||||
return errUnableToInitNetwork
|
||||
}
|
||||
|
||||
C.set_batch_network(n.cNet, 1)
|
||||
// C.set_batch_network(n.cNet, 1)
|
||||
C.srand(2222222)
|
||||
|
||||
// Currently, hierarchal threshold is always 0.5.
|
||||
@@ -57,10 +57,10 @@ func (n *YOLONetwork) Init() error {
|
||||
// Currently NMS is always 0.4.
|
||||
n.nms = .4
|
||||
|
||||
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)
|
||||
// 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)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -71,33 +71,33 @@ func (n *YOLONetwork) Close() error {
|
||||
return errNetworkNotInit
|
||||
}
|
||||
|
||||
C.free_network(n.cNet)
|
||||
C.free_network(*n.cNet)
|
||||
n.cNet = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
// Detect specified image.
|
||||
func (n *YOLONetwork) Detect(img *Image) (*DetectionResult, error) {
|
||||
if n.cNet == nil {
|
||||
return nil, errNetworkNotInit
|
||||
}
|
||||
// func (n *YOLONetwork) Detect(img *Image) (*DetectionResult, error) {
|
||||
// if n.cNet == nil {
|
||||
// return nil, errNetworkNotInit
|
||||
// }
|
||||
|
||||
startTime := time.Now()
|
||||
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)
|
||||
// startTime := time.Now()
|
||||
// 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)
|
||||
// ds := makeDetections(img, result.detections, int(result.detections_len),
|
||||
// n.Threshold, n.Classes, n.ClassNames)
|
||||
|
||||
endTimeOverall := time.Now()
|
||||
// endTimeOverall := time.Now()
|
||||
|
||||
out := DetectionResult{
|
||||
Detections: ds,
|
||||
NetworkOnlyTimeTaken: endTime.Sub(startTime),
|
||||
OverallTimeTaken: endTimeOverall.Sub(startTime),
|
||||
}
|
||||
// out := DetectionResult{
|
||||
// Detections: ds,
|
||||
// NetworkOnlyTimeTaken: endTime.Sub(startTime),
|
||||
// OverallTimeTaken: endTimeOverall.Sub(startTime),
|
||||
// }
|
||||
|
||||
return &out, nil
|
||||
}
|
||||
// return &out, nil
|
||||
// }
|
||||
|
Reference in New Issue
Block a user