派生自 libgowrapper/yolo

zhangmeng
2019-12-11 b63c8219736016e3b3952465f41abede37a38fbd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
package main
 
/*
#cgo CFLAGS: -I${SRCDIR}/sdk/include -w -g
#cgo CXXFLAGS: -I${SRCDIR}/sdk/include -w -g -std=c++11
#cgo LDFLAGS: -L/usr/local/cuda-8.0/lib64 -L${SRCDIR}/sdk/lib
#cgo LDFLAGS: -Wl,-rpath,${SRCDIR}/sdk/lib
#cgo LDFLAGS: -ldarknet -lcudart -lcublas -lcurand -lcudnn -lrt -ldl -lpthread
#include <stdlib.h>
#include "cyolo.h"
*/
import "C"
import (
    "unsafe"
 
    "basic.com/libgowrapper/sdkstruct.git"
)
 
type trackInfo struct {
    lastTrackObjs []sdkstruct.CObjTrackInfo
    lastTrackID   uint64
}
 
// YoloHandle wrap C
type YoloHandle struct {
    handle  unsafe.Pointer
    tracker map[string]*trackInfo
}
 
// RatioInterTrack 跟踪判断重叠阈值
const RatioInterTrack = 50 //跟踪判断重叠阈值
 
// NewSDK init yolo sdk
func NewSDK(fc, fw, fn string, gi int) interface{} {
 
    c := C.CString(fc)
    defer C.free(unsafe.Pointer(c))
    w := C.CString(fw)
    defer C.free(unsafe.Pointer(w))
    n := C.CString(fn)
    defer C.free(unsafe.Pointer(n))
 
    g := C.int(gi)
 
    p := C.init(c, w, n, g)
    return &YoloHandle{
        handle:  p,
        tracker: make(map[string]*trackInfo),
    }
}
 
// Free free
func Free(i interface{}) {
    y := i.(*YoloHandle)
    if y != nil && y.handle != nil {
        C.release(y.handle)
    }
}
 
// CYoloObjInfoArrayToGoArray convert cObjInfo array to go
func CYoloObjInfoArrayToGoArray(cArray unsafe.Pointer, count int) (goArray []sdkstruct.CObjInfo) {
    p := uintptr(cArray)
 
    for i := 0; i < count; i++ {
        j := *(*sdkstruct.CObjInfo)(unsafe.Pointer(p))
        goArray = append(goArray, j)
        p += unsafe.Sizeof(j)
    }
    return
}
 
// YoloDetect yolo detect
func YoloDetect(y *YoloHandle, data []byte, w, h, c int, thrsh float32, umns int) []sdkstruct.CObjInfo {
 
    var count C.int
    var cobjinfo unsafe.Pointer
 
    ret := C.detect(y.handle,
        unsafe.Pointer(&data[0]), C.int(w), C.int(h), C.int(c),
        C.float(thrsh), C.int(umns),
        &cobjinfo, &count)
 
    if ret == 0 {
        defer C.free(cobjinfo)
        return CYoloObjInfoArrayToGoArray(unsafe.Pointer(cobjinfo), int(count))
    }
    return nil
}
 
// YoloObjName obj name by type
func YoloObjName(typ int) string {
    p := C.obj_name_by_type(C.int(typ))
 
    return C.GoString(p)
}
 
func max(a, b int32) int32 {
    if a < b {
        return b
    }
    return a
}
 
func min(a, b int32) int32 {
    if a < b {
        return a
    }
    return b
}
 
func countInterAreaOfTwoRect(rect1 sdkstruct.CRECT, rect2 sdkstruct.CRECT) int32 {
    xMin := min(rect1.Left, rect2.Left)
    yMin := min(rect1.Top, rect2.Top)
    xMax := max(rect1.Right, rect2.Right)
    yMax := max(rect1.Bottom, rect2.Bottom)
 
    wRect1 := rect1.Right - rect1.Left
    hRect1 := rect1.Bottom - rect1.Top
 
    wRect2 := rect2.Right - rect2.Left
    hRect2 := rect2.Bottom - rect2.Top
 
    wInter := wRect1 + wRect2 - (xMax - xMin)
    hInter := hRect1 + hRect2 - (yMax - yMin)
 
    if (wInter <= 0) || (hInter <= 0) {
        return 0
    }
 
    areaInter := wInter * hInter
    areaRect1 := wRect1 * hRect1
    areaRect2 := wRect2 * hRect2
    ratio := areaInter * 100 / min(areaRect1, areaRect2)
 
    return ratio
}
 
// YoloDetectTrack2 yolo detect   (只识别人)
func YoloDetectTrack2(y *YoloHandle, LastYoloObjs []sdkstruct.CObjTrackInfo, LastTrackID *uint64, data []byte, w, h, c int, thrsh float32, umns int) (allObjs []sdkstruct.CObjTrackInfo, newObjs []sdkstruct.CObjTrackInfo) {
 
    var tmp sdkstruct.CObjTrackInfo
    //LastYoloObjs
    detectObjs := YoloDetect(y, data, w, h, c, thrsh, umns)
 
    for _, vLast := range LastYoloObjs {
        for i := 0; i < len(detectObjs); i++ {
            //fmt.Println("vNew.Typ:", vNew.Typ)
            if vLast.ObjInfo.Typ == detectObjs[i].Typ { //同一类别,比如都是人体
                ratio := countInterAreaOfTwoRect(vLast.ObjInfo.RcObj, detectObjs[i].RcObj)
                if ratio >= RatioInterTrack {
                    //update LastYoloObjs
                    vLast.ObjInfo.RcObj = detectObjs[i].RcObj
                    vLast.ObjInfo.Prob = detectObjs[i].Prob
 
                    allObjs = append(allObjs, vLast)
                    detectObjs = append(detectObjs[:i], detectObjs[i+1:]...) //从检测目标里删除已经查到的跟踪目标
                    i--
                    break //上一帧跟踪的目标已经找到,无需往下处理其他检测目标
                }
            }
        }
    }
 
    //处理新出现的目标
    id := *LastTrackID
    if len(detectObjs) > 0 {
        for _, vAdd := range detectObjs {
            tmp.ObjInfo = vAdd
            tmp.ID = id
            id++
 
            allObjs = append(allObjs, tmp)
            newObjs = append(newObjs, tmp)
        }
    }
    *LastTrackID = id
    return allObjs, newObjs
}
 
// Run yolo detect   (只识别人)
func Run(i interface{}, id string, data []byte, w, h, c int, thrsh float32, umns int) ([]sdkstruct.CObjTrackInfo, []sdkstruct.CObjTrackInfo) {
    if data == nil || w <= 0 || h <= 0 {
        return nil, nil
    }
    y := i.(*YoloHandle)
 
    channel := c
    if channel == 0 {
        channel = 3
    }
 
    v, ok := y.tracker[id]
    if !ok {
        i := &trackInfo{}
        y.tracker[id] = i
        v = i
    }
    whole, recent := YoloDetectTrack2(y, v.lastTrackObjs, &v.lastTrackID, data, w, h, channel, thrsh, umns)
    y.tracker[id].lastTrackObjs = whole
    y.tracker[id].lastTrackID = v.lastTrackID
 
    return whole, recent
}