-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathvideo.go
151 lines (128 loc) · 3.96 KB
/
video.go
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
package main
import (
"fmt"
"image"
"image/color"
"os"
"gocv.io/x/gocv"
)
// getOutputsNames : YOLO Layer
func getOutputsNames(net *gocv.Net) []string {
var outputLayers []string
for _, i := range net.GetUnconnectedOutLayers() {
layer := net.GetLayer(i)
layerName := layer.GetName()
if layerName != "_input" {
outputLayers = append(outputLayers, layerName)
}
}
return outputLayers
}
// PostProcess : All Detect Box
func PostProcess(frame gocv.Mat, outs *[]gocv.Mat) ([]image.Rectangle, []float32, []int) {
var classIds []int
var confidences []float32
var boxes []image.Rectangle
for _, out := range *outs {
data, _ := out.DataPtrFloat32()
for i := 0; i < out.Rows(); i, data = i+1, data[out.Cols():] {
scoresCol := out.RowRange(i, i+1)
scores := scoresCol.ColRange(5, out.Cols())
_, confidence, _, classIDPoint := gocv.MinMaxLoc(scores)
if confidence > 0.5 {
centerX := int(data[0] * float32(frame.Cols()))
centerY := int(data[1] * float32(frame.Rows()))
width := int(data[2] * float32(frame.Cols()))
height := int(data[3] * float32(frame.Rows()))
left := centerX - width/2
top := centerY - height/2
classIds = append(classIds, classIDPoint.X)
confidences = append(confidences, float32(confidence))
boxes = append(boxes, image.Rect(left, top, width, height))
}
}
}
return boxes, confidences, classIds
}
// ReadCOCO : Read coco.names
func ReadCOCO() []string {
var classes []string
read, _ := os.Open("./assets/coco.names")
defer read.Close()
for {
var t string
_, err := fmt.Fscan(read, &t)
if err != nil {
break
}
classes = append(classes, t)
}
return classes
}
// drawRect : Detect Class to Draw Rect
func drawRect(img gocv.Mat, boxes []image.Rectangle, classes []string, classIds []int, indices []int) (gocv.Mat, []string) {
var detectClass []string
for _, idx := range indices {
if idx == 0 {
continue
}
gocv.Rectangle(&img, image.Rect(boxes[idx].Max.X, boxes[idx].Max.Y, boxes[idx].Max.X+boxes[idx].Min.X, boxes[idx].Max.Y+boxes[idx].Min.Y), color.RGBA{255, 0, 0, 0}, 2)
gocv.PutText(&img, classes[classIds[idx]], image.Point{boxes[idx].Max.X, boxes[idx].Max.Y + 30}, gocv.FontHersheyPlain, 10, color.RGBA{0, 0, 255, 0}, 3)
detectClass = append(detectClass, classes[classIds[idx]])
}
return img, detectClass
}
// Detect : Run YOLOv4 Process
func Detect(net *gocv.Net, src gocv.Mat, scoreThreshold float32, nmsThreshold float32, OutputNames []string, classes []string) (gocv.Mat, []string) {
img := src.Clone()
img.ConvertTo(&img, gocv.MatTypeCV32F)
blob := gocv.BlobFromImage(img, 1/255.0, image.Pt(416, 416), gocv.NewScalar(0, 0, 0, 0), true, false)
net.SetInput(blob, "")
probs := net.ForwardLayers(OutputNames)
boxes, confidences, classIds := PostProcess(img, &probs)
indices := make([]int, 100)
if len(boxes) == 0 { // No Classes
return src, []string{}
}
gocv.NMSBoxes(boxes, confidences, scoreThreshold, nmsThreshold, indices)
return drawRect(src, boxes, classes, classIds, indices)
}
// GetFrame : Read Frame and Process
func GetFrame(cap *gocv.VideoCapture) {
// Init
classes := ReadCOCO()
net := gocv.ReadNet("./assets/yolov4.weights", "./assets/yolov4.cfg")
defer net.Close()
net.SetPreferableBackend(gocv.NetBackendType(gocv.NetBackendDefault))
net.SetPreferableTarget(gocv.NetTargetType(gocv.NetTargetCPU))
img := gocv.NewMat()
defer img.Close()
OutputNames := getOutputsNames(&net)
window := gocv.NewWindow("yolo")
for {
if ok := cap.Read(&img); !ok {
fmt.Printf("Device closed\n")
return
}
if img.Empty() {
continue
}
detectImg, detectClass := Detect(&net, img.Clone(), 0.45, 0.5, OutputNames, classes)
fmt.Printf("Dectect Class : %v\n", detectClass)
window.IMShow(detectImg)
gocv.WaitKey(1)
detectImg.Close()
}
}
func main() {
fmt.Println(os.Args[1])
cap, err := gocv.OpenVideoCapture(os.Args[1])
if err != nil {
fmt.Printf("Error opening capture device")
return
}
defer cap.Close()
go GetFrame(cap)
// Time Out
select {}
}