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 <xaiki@evilgiggle.com>
- 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)
|