Spaces:
Runtime error
Runtime error
Niv Sardi
commited on
Commit
·
4e1c07d
1
Parent(s):
63501c1
imtool: better types and use our data structures
Browse filesSigned-off-by: Niv Sardi <[email protected]>
- python/imtool.py +54 -67
python/imtool.py
CHANGED
@@ -4,7 +4,7 @@ import os
|
|
4 |
import math
|
5 |
import cv2
|
6 |
import numpy as np
|
7 |
-
from typing import NamedTuple, Tuple
|
8 |
|
9 |
from entity import Entity
|
10 |
from common import mkdir
|
@@ -19,8 +19,8 @@ class BoundingBox(NamedTuple):
|
|
19 |
h: float = 0.0
|
20 |
|
21 |
@classmethod
|
22 |
-
def from_centroid(cls, c, shape
|
23 |
-
(
|
24 |
print(cls, c, shape)
|
25 |
self = cls(x=math.floor(w*(c.x - c.w/2))
|
26 |
, y=math.floor(h*(c.y - c.h/2))
|
@@ -35,21 +35,48 @@ class BoundingBox(NamedTuple):
|
|
35 |
|
36 |
@property
|
37 |
def start(self):
|
38 |
-
return (self.x, self.y)
|
39 |
|
40 |
@property
|
41 |
def end(self):
|
42 |
-
return (self.x + self.w, self.y + self.h)
|
43 |
|
44 |
-
def to_centroid(self, shape
|
45 |
(h, w, c) = shape
|
46 |
return Centroid(x=math.floor(self.x + self.w/2)/w
|
47 |
, y=math.floor(self.y + self.h/2)/h
|
48 |
, w=math.ceil(self.w)/w
|
49 |
, h=math.ceil(self.h)/h)
|
50 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
51 |
class Centroid(BoundingBox):
|
52 |
-
def to_bounding_box(self, shape
|
53 |
(h, w, c) = shape
|
54 |
|
55 |
return BoundingBox(
|
@@ -58,10 +85,8 @@ class Centroid(BoundingBox):
|
|
58 |
, w=math.ceil(w*self.w)
|
59 |
, h=math.ceil(h*self.h))
|
60 |
|
61 |
-
def to_anotation(self, id: int
|
62 |
-
|
63 |
-
|
64 |
-
return f'{id} {self.x/w} {self.y/h} {self.w/w} {self.h/h}'
|
65 |
|
66 |
def read_marker(filename: str, Type: type):
|
67 |
ret = []
|
@@ -70,8 +95,7 @@ def read_marker(filename: str, Type: type):
|
|
70 |
lines = f.readlines()
|
71 |
for l in lines:
|
72 |
(b, x,y,w,h) = [float(i) for i in l.split(' ')]
|
73 |
-
bco = b
|
74 |
-
print(b, x,y,w,h)
|
75 |
ret.append(Type(x,y,w,h))
|
76 |
return bco, ret
|
77 |
|
@@ -93,17 +117,16 @@ def floor_point(x: float, y: float):
|
|
93 |
return (math.floor(x), math.floor(y))
|
94 |
|
95 |
def cut_img(im, s: Tuple[float, float], e: Tuple[float, float]):
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
|
101 |
-
|
102 |
-
return im[y:h, x:w]
|
103 |
|
104 |
def cut_logo(im, l):
|
105 |
(x, y, w, h) = floor_logo(l)
|
106 |
-
return im[
|
107 |
|
108 |
def add_alpha(img):
|
109 |
b, g, r = cv2.split(img)
|
@@ -200,62 +223,26 @@ def crop(id, fn, logos):
|
|
200 |
rim = cv2.rectangle(rim, start, end, color, 10)
|
201 |
li = []
|
202 |
for l in logos:
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
logo_color, 5)
|
207 |
-
def intersect():
|
208 |
-
six = l.x - f.x
|
209 |
-
siy = l.y - f.y
|
210 |
-
eix = six + l.w
|
211 |
-
eiy = siy + l.h
|
212 |
-
|
213 |
-
#print('intersect', (six, siy), (eix, eiy), f, l)
|
214 |
-
|
215 |
-
if six < 0:
|
216 |
-
if six + l.w < 0:
|
217 |
-
return None
|
218 |
-
six = 0
|
219 |
-
if siy < 0:
|
220 |
-
if siy + l.h < 0:
|
221 |
-
return None
|
222 |
-
siy = 0
|
223 |
-
if eix > tw:
|
224 |
-
if eix - l.w > tw:
|
225 |
-
return None
|
226 |
-
eix = tw
|
227 |
-
if eiy > th:
|
228 |
-
if eiy - l.h > th:
|
229 |
-
return None
|
230 |
-
eiy = th
|
231 |
-
|
232 |
-
return BoundingBox(six, siy, eix - six, eiy - siy)
|
233 |
-
|
234 |
-
p = intersect()
|
235 |
if p:
|
236 |
li.append(p)
|
237 |
|
238 |
-
nim = im
|
239 |
-
rnim =
|
240 |
img_name =f"{img_out}/{basename}-x{x}y{y}.jpg"
|
241 |
txt_name =f"{txt_out}/{basename}-x{x}y{y}.txt"
|
242 |
|
243 |
cv2.imwrite(img_name, nim)
|
244 |
if len(li):
|
245 |
-
with open(txt_name, 'w') as
|
246 |
for p in li:
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
floor_point(cx + p.w/2, cy + p.h/2),
|
253 |
-
logo_color,
|
254 |
-
5)
|
255 |
-
|
256 |
-
a = f"{int(id)} {cx/TILE_SIZE} {cy/TILE_SIZE} {p.w/TILE_SIZE} {p.h/TILE_SIZE}\n"
|
257 |
-
f.write(a)
|
258 |
-
print(a)
|
259 |
cv2.imwrite(f'{debug_out}/{basename}{x}{y}.debug.png', dim)
|
260 |
|
261 |
cv2.imwrite(f'{debug_out}/{basename}.debug.png', rim)
|
|
|
4 |
import math
|
5 |
import cv2
|
6 |
import numpy as np
|
7 |
+
from typing import NamedTuple, Tuple, List
|
8 |
|
9 |
from entity import Entity
|
10 |
from common import mkdir
|
|
|
19 |
h: float = 0.0
|
20 |
|
21 |
@classmethod
|
22 |
+
def from_centroid(cls, c, shape):
|
23 |
+
(ih, iw, ic) = shape
|
24 |
print(cls, c, shape)
|
25 |
self = cls(x=math.floor(w*(c.x - c.w/2))
|
26 |
, y=math.floor(h*(c.y - c.h/2))
|
|
|
35 |
|
36 |
@property
|
37 |
def start(self):
|
38 |
+
return floor_point(self.x, self.y)
|
39 |
|
40 |
@property
|
41 |
def end(self):
|
42 |
+
return floor_point(self.x + self.w, self.y + self.h)
|
43 |
|
44 |
+
def to_centroid(self, shape):
|
45 |
(h, w, c) = shape
|
46 |
return Centroid(x=math.floor(self.x + self.w/2)/w
|
47 |
, y=math.floor(self.y + self.h/2)/h
|
48 |
, w=math.ceil(self.w)/w
|
49 |
, h=math.ceil(self.h)/h)
|
50 |
|
51 |
+
def intersect(self, f):
|
52 |
+
six = self.x - f.x
|
53 |
+
siy = self.y - f.y
|
54 |
+
eix = six + self.w
|
55 |
+
eiy = siy + self.h
|
56 |
+
|
57 |
+
|
58 |
+
|
59 |
+
if six < 0:
|
60 |
+
if six + self.w < 0:
|
61 |
+
return None
|
62 |
+
six = 0
|
63 |
+
if siy < 0:
|
64 |
+
if siy + self.h < 0:
|
65 |
+
return None
|
66 |
+
siy = 0
|
67 |
+
if eix > f.w:
|
68 |
+
if eix - self.w > f.w:
|
69 |
+
return None
|
70 |
+
eix = f.w
|
71 |
+
if eiy > f.h:
|
72 |
+
if eiy - self.h > f.h:
|
73 |
+
return None
|
74 |
+
eiy = f.h
|
75 |
+
|
76 |
+
return BoundingBox(six, siy, eix - six, eiy - siy)
|
77 |
+
|
78 |
class Centroid(BoundingBox):
|
79 |
+
def to_bounding_box(self, shape):
|
80 |
(h, w, c) = shape
|
81 |
|
82 |
return BoundingBox(
|
|
|
85 |
, w=math.ceil(w*self.w)
|
86 |
, h=math.ceil(h*self.h))
|
87 |
|
88 |
+
def to_anotation(self, id: int):
|
89 |
+
return f'{id} {self.x} {self.y} {self.w} {self.h}'
|
|
|
|
|
90 |
|
91 |
def read_marker(filename: str, Type: type):
|
92 |
ret = []
|
|
|
95 |
lines = f.readlines()
|
96 |
for l in lines:
|
97 |
(b, x,y,w,h) = [float(i) for i in l.split(' ')]
|
98 |
+
bco = int(b)
|
|
|
99 |
ret.append(Type(x,y,w,h))
|
100 |
return bco, ret
|
101 |
|
|
|
117 |
return (math.floor(x), math.floor(y))
|
118 |
|
119 |
def cut_img(im, s: Tuple[float, float], e: Tuple[float, float]):
|
120 |
+
x1 = math.floor(s[0])
|
121 |
+
y1 = math.floor(s[1])
|
122 |
+
x2 = math.floor(e[0])
|
123 |
+
y2 = math.floor(e[1])
|
124 |
|
125 |
+
return im[y1:y2, x1:x2]
|
|
|
126 |
|
127 |
def cut_logo(im, l):
|
128 |
(x, y, w, h) = floor_logo(l)
|
129 |
+
return im[y:y+h, x:x+w]
|
130 |
|
131 |
def add_alpha(img):
|
132 |
b, g, r = cv2.split(img)
|
|
|
223 |
rim = cv2.rectangle(rim, start, end, color, 10)
|
224 |
li = []
|
225 |
for l in logos:
|
226 |
+
bl = l.to_bounding_box(im.shape)
|
227 |
+
rim = cv2.rectangle(rim, bl.start, bl.end, logo_color, 5)
|
228 |
+
p = bl.intersect(f)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
229 |
if p:
|
230 |
li.append(p)
|
231 |
|
232 |
+
nim = cut_img(im, start, end)
|
233 |
+
rnim = cut_img(im, start, end)
|
234 |
img_name =f"{img_out}/{basename}-x{x}y{y}.jpg"
|
235 |
txt_name =f"{txt_out}/{basename}-x{x}y{y}.txt"
|
236 |
|
237 |
cv2.imwrite(img_name, nim)
|
238 |
if len(li):
|
239 |
+
with open(txt_name, 'w') as label:
|
240 |
for p in li:
|
241 |
+
dim = cv2.rectangle(rnim, p.start, p.end, logo_color, 5)
|
242 |
+
lc = p.to_centroid((TILE_SIZE, TILE_SIZE, 3))
|
243 |
+
|
244 |
+
a = f"{int(id)} {lc.x} {lc.y} {lc.w} {lc.h}"
|
245 |
+
label.write(a)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
246 |
cv2.imwrite(f'{debug_out}/{basename}{x}{y}.debug.png', dim)
|
247 |
|
248 |
cv2.imwrite(f'{debug_out}/{basename}.debug.png', rim)
|