-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsloth.go
99 lines (88 loc) · 2.79 KB
/
sloth.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
package lblconv
// Sloth specific functionality.
import (
"encoding/json"
"fmt"
"io/ioutil"
)
// SlothAnnotation is a single annotation within a Sloth file.
type SlothAnnotation struct {
Class string `json:"class,omitempty"`
Type string `json:"type,omitempty"`
X float64 `json:"x,omitempty"`
Y float64 `json:"y,omitempty"`
Width float64 `json:"width,omitempty"`
Height float64 `json:"height,omitempty"`
}
// SlothAnnotatedFile defines the Sloth annotation structure for a single file.
type SlothAnnotatedFile struct {
Annotations []SlothAnnotation `json:"annotations"`
Class string `json:"class,omitempty"`
FilePath string `json:"filename,omitempty"`
}
// FromSloth reads and parses Sloth annotations from the file at path.
func FromSloth(path string) ([]AnnotatedFile, error) {
enc, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
var slothData []SlothAnnotatedFile
err = json.Unmarshal(enc, &slothData)
if err != nil {
return nil, fmt.Errorf("failed to parse Sloth input from %q: %v", path, err)
}
// Convert to the intermediate representation.
data := make([]AnnotatedFile, 0, len(slothData))
for _, slothFileData := range slothData {
// Per file data. Convert all annotations.
fileData := AnnotatedFile{
Annotations: make([]Annotation, len(slothFileData.Annotations)),
FilePath: slothFileData.FilePath,
}
for i, a := range slothFileData.Annotations {
annotation := Annotation{Label: a.Class}
annotation.Coords[0] = a.X
annotation.Coords[1] = a.Y
annotation.Coords[2] = a.X + a.Width
annotation.Coords[3] = a.Y + a.Height
fileData.Annotations[i] = annotation
}
data = append(data, fileData)
}
return data, nil
}
// ToSloth converts the intermediate representation to Sloth format.
func ToSloth(data []AnnotatedFile) []SlothAnnotatedFile {
slothData := make([]SlothAnnotatedFile, 0, len(data))
for _, fileData := range data {
slothFileData := SlothAnnotatedFile{
Annotations: make([]SlothAnnotation, len(fileData.Annotations)),
Class: "image",
FilePath: fileData.FilePath,
}
for i, a := range fileData.Annotations {
slothLabel := SlothAnnotation{
Class: a.Label,
Type: "rect",
X: a.Coords[0],
Y: a.Coords[1],
Width: a.Coords[2] - a.Coords[0],
Height: a.Coords[3] - a.Coords[1],
}
slothFileData.Annotations[i] = slothLabel
}
slothData = append(slothData, slothFileData)
}
return slothData
}
// WriteSloth writes the Sloth annotations to outFile.
func WriteSloth(outFile string, data []SlothAnnotatedFile) error {
enc, err := json.MarshalIndent(data, "", " ")
if err != nil {
return err
}
if err := ioutil.WriteFile(outFile, enc, 0644); err != nil {
return fmt.Errorf("cannot write file %q: %v", outFile, err)
}
return nil
}