need to deal with image

This commit is contained in:
Dimitrii
2020-02-19 14:52:19 +03:00
parent 30fbbb9949
commit 2b2f3f159c
20 changed files with 4015 additions and 46 deletions

6
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"files.associations": {
"detection.h": "c",
"network.h": "c"
}
}

3801
bad.list Normal file

File diff suppressed because it is too large Load Diff

8
classes.c Normal file
View 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
View 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
View File

@@ -0,0 +1,3 @@
#pragma once
extern char * get_class_name(char **names, int index, int names_len);

View File

@@ -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
View File

@@ -0,0 +1,5 @@
person
car
motorcycle
bus
truck

22
detection.c Normal file
View 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];
}

View File

@@ -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
View 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);

View File

@@ -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
View 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}
]
}
]

View File

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

View File

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

View File

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

BIN
main

Binary file not shown.

View File

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

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 MiB