Add default colors for masks (#1549)

* Use default colors for masks

* do not change labels in voc converter

* update tests

* add backgound color handling

* consider case with existing source colormap

* update changelog

* fix file name

* fix insert

* move color table colors to beginning
main
zhiltsov-max 6 years ago committed by GitHub
parent d57f7aefc1
commit ac922e33a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -7,6 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [1.1.0-alpha] - Unreleased
### Added
- Throttling policy for unauthenticated users (<https://github.com/opencv/cvat/pull/1531>)
- Added default label color table for mask export (https://github.com/opencv/cvat/pull/1549)
### Changed
- Removed information about e-mail from the basic user information (<https://github.com/opencv/cvat/pull/1627>)

@ -2,6 +2,7 @@
#
# SPDX-License-Identifier: MIT
import os.path as osp
from tempfile import TemporaryDirectory
from pyunpack import Archive
@ -9,7 +10,9 @@ from pyunpack import Archive
from cvat.apps.dataset_manager.bindings import (CvatTaskDataExtractor,
import_dm_annotations)
from cvat.apps.dataset_manager.util import make_zip_archive
from datumaro.cli.util import make_file_name
from datumaro.components.project import Dataset
from datumaro.util.mask_tools import generate_colormap
from .registry import dm_env, exporter, importer
@ -25,7 +28,8 @@ def _export(dst_file, task_data, save_images=False):
extractor = Dataset.from_extractors(extractor) # apply lazy transforms
with TemporaryDirectory() as temp_dir:
converter = dm_env.make_converter('voc_segmentation',
apply_colormap=True, label_map='source', save_images=save_images)
apply_colormap=True, label_map=make_colormap(task_data),
save_images=save_images)
converter(extractor, save_dir=temp_dir)
make_zip_archive(temp_dir, dst_file)
@ -39,3 +43,43 @@ def _import(src_file, task_data):
masks_to_polygons = dm_env.transforms.get('masks_to_polygons')
dataset = dataset.transform(masks_to_polygons)
import_dm_annotations(dataset, task_data)
DEFAULT_COLORMAP_CAPACITY = 2000
DEFAULT_COLORMAP_PATH = osp.join(osp.dirname(__file__), 'predefined_colors.txt')
def parse_default_colors(file_path=None):
if file_path is None:
file_path = DEFAULT_COLORMAP_PATH
colors = {}
with open(file_path) as f:
for line in f:
line = line.strip()
if not line or line[0] == '#':
continue
_, label, color = line.split(':')
colors[label] = tuple(map(int, color.split(',')))
return colors
def normalize_label(label):
label = make_file_name(label) # basically, convert to ASCII lowercase
label = label.replace('-', '_')
return label
def make_colormap(task_data):
labels = sorted([label['name']
for _, label in task_data.meta['task']['labels']])
if 'background' not in labels:
labels.insert(0, 'background')
predefined = parse_default_colors()
# NOTE: using pop() to avoid collisions
colormap = {k: predefined.pop(normalize_label(k), None) for k in labels}
random_labels = [k for k in labels if not colormap[k]]
if random_labels:
colors = generate_colormap(DEFAULT_COLORMAP_CAPACITY + len(random_labels))
for i, label in enumerate(random_labels):
colormap[label] = colors[DEFAULT_COLORMAP_CAPACITY + i]
return {l: [c, [], []] for l, c in colormap.items()}

@ -0,0 +1,731 @@
# ImageNet + OpenImages + PASCAL VOC +
# CamVid + CityScapes + Kitti +
# COCO + COCO stuff
# Format:
# pascal idx : normalized label name : R,G,B
0:background:0,0,0
1:accordion:128,0,0
2:adhesive_tape:0,128,0
3:aeroplane:128,128,0
4:aircraft:0,0,128
5:airplane:128,0,128
6:alarm_clock:0,128,128
7:alpaca:128,128,128
8:ambulance:64,0,0
9:animal:192,0,0
10:ant:64,128,0
11:antelope:192,128,0
12:apple:64,0,128
13:armadillo:192,0,128
14:artichoke:64,128,128
15:asparagus:192,128,128
16:axe:0,64,0
17:baby_bed:128,64,0
18:backpack:0,192,0
19:bagel:128,192,0
20:balance_beam:0,64,128
21:ball:128,64,128
22:balloon:0,192,128
23:banana:128,192,128
24:band_aid:64,64,0
25:banjo:192,64,0
26:banner:64,192,0
27:barge:192,192,0
28:barrel:64,64,128
29:baseball:192,64,128
30:baseball_bat:64,192,128
31:baseball_glove:192,192,128
32:basketball:0,0,64
33:bat:128,0,64
34:bathing_cap:0,128,64
35:bathroom_cabinet:128,128,64
36:bathtub:0,0,192
37:beaker:128,0,192
38:bear:0,128,192
39:bed:128,128,192
40:bee:64,0,64
41:beehive:192,0,64
42:beer:64,128,64
43:beetle:192,128,64
44:bell_pepper:64,0,192
45:belt:192,0,192
46:bench:64,128,192
47:bg:192,128,192
48:bicycle:0,64,64
49:bicycle_helmet:128,64,64
50:bicycle_wheel:0,192,64
51:bidet:128,192,64
52:billboard:0,64,192
53:billiard_table:128,64,192
54:binder:0,192,192
55:binoculars:128,192,192
56:bird:64,64,64
57:blanket:192,64,64
58:blender:64,192,64
59:blue_jay:192,192,64
60:boat:64,64,192
61:book:192,64,192
62:bookcase:64,192,192
63:bookshelf:192,192,192
64:boot:32,0,0
65:bottle:160,0,0
66:bow:32,128,0
67:bow_and_arrow:160,128,0
68:bow_tie:32,0,128
69:bowl:160,0,128
70:box:32,128,128
71:boy:160,128,128
72:branch:96,0,0
73:brassiere:224,0,0
74:bread:96,128,0
75:bridge:224,128,0
76:briefcase:96,0,128
77:broccoli:224,0,128
78:bronze_sculpture:96,128,128
79:brown_bear:224,128,128
80:building:32,64,0
81:building_other:160,64,0
82:bull:32,192,0
83:burrito:160,192,0
84:bus:32,64,128
85:bush:160,64,128
86:bust:32,192,128
87:butterfly:160,192,128
88:cabbage:96,64,0
89:cabinet:224,64,0
90:cabinetry:96,192,0
91:cage:224,192,0
92:cake:96,64,128
93:cake_stand:224,64,128
94:camel:96,192,128
95:camera:224,192,128
96:can_opener:32,0,64
97:canary:160,0,64
98:candle:32,128,64
99:candy:160,128,64
100:cannon:32,0,192
101:canoe:160,0,192
102:car:32,128,192
103:caravan:160,128,192
104:cardboard:96,0,64
105:carnivore:224,0,64
106:carpet:96,128,64
107:carrot:224,128,64
108:cart:96,0,192
109:castle:224,0,192
110:cat:96,128,192
111:caterpillar:224,128,192
112:cattle:32,64,64
113:ceiling_fan:160,64,64
114:ceiling_other:32,192,64
115:ceiling_tile:160,192,64
116:cell_phone:32,64,192
117:cello:160,64,192
118:centipede:32,192,192
119:chain_saw:160,192,192
120:chair:96,64,64
121:cheetah:224,64,64
122:chest_of_drawers:96,192,64
123:chicken:224,192,64
124:chime:96,64,192
125:chopsticks:224,64,192
126:christmas_tree:96,192,192
127:clock:224,192,192
128:cloth:0,32,0
129:clothes:128,32,0
130:clouds:0,160,0
131:coat:128,160,0
132:cocktail:0,32,128
133:cocktail_shaker:128,32,128
134:coconut:0,160,128
135:coffee:128,160,128
136:coffee_cup:64,32,0
137:coffee_maker:192,32,0
138:coffee_table:64,160,0
139:coffeemaker:192,160,0
140:coin:64,32,128
141:common_fig:192,32,128
142:computer_keyboard:64,160,128
143:computer_monitor:192,160,128
144:computer_mouse:0,96,0
145:construction:128,96,0
146:convenience_store:0,224,0
147:cookie:128,224,0
148:corded_phone:0,96,128
149:corkscrew:128,96,128
150:couch:0,224,128
151:counter:128,224,128
152:countertop:64,96,0
153:cow:192,96,0
154:cowboy_hat:64,224,0
155:crab:192,224,0
156:cream:64,96,128
157:cricket_ball:192,96,128
158:crocodile:64,224,128
159:croissant:192,224,128
160:croquet_ball:0,32,64
161:crosswalk:128,32,64
162:crown:0,160,64
163:crutch:128,160,64
164:cucumber:0,32,192
165:cup:128,32,192
166:cup_or_mug:0,160,192
167:cupboard:128,160,192
168:curtain:64,32,64
169:cutting_board:192,32,64
170:cyclist:64,160,64
171:dagger:192,160,64
172:deer:64,32,192
173:desk:192,32,192
174:desk_stuff:64,160,192
175:dessert:192,160,192
176:diaper:0,96,64
177:dice:128,96,64
178:digital_clock:0,224,64
179:dining_table:128,224,64
180:diningtable:0,96,192
181:dinosaur:128,96,192
182:dirt:0,224,192
183:dishwasher:128,224,192
184:dog:64,96,64
185:dog_bed:192,96,64
186:doll:64,224,64
187:dolphin:192,224,64
188:domestic_cat:64,96,192
189:dontcare:192,96,192
190:donut:64,224,192
191:door:192,224,192
192:door_handle:32,32,0
193:door_stuff:160,32,0
194:doughnut:32,160,0
195:dragonfly:160,160,0
196:drawer:32,32,128
197:dress:160,32,128
198:drink:32,160,128
199:drinking_straw:160,160,128
200:drum:96,32,0
201:duck:224,32,0
202:dumbbell:96,160,0
203:dynamic:224,160,0
204:eagle:96,32,128
205:earrings:224,32,128
206:egg:96,160,128
207:electric_fan:224,160,128
208:elephant:32,96,0
209:envelope:160,96,0
210:eye_glasses:32,224,0
211:face_powder:160,224,0
212:falcon:32,96,128
213:fedora:160,96,128
214:fence:32,224,128
215:fence_guard:160,224,128
216:fig:96,96,0
217:filing_cabinet:224,96,0
218:finish:96,224,0
219:fire_hydrant:224,224,0
220:fireplace:96,96,128
221:fish:224,96,128
222:flag:96,224,128
223:flashlight:224,224,128
224:floor_marble:32,32,64
225:floor_other:160,32,64
226:floor_stone:32,160,64
227:floor_tile:160,160,64
228:floor_wood:32,32,192
229:flower:160,32,192
230:flower_pot:32,160,192
231:flowerpot:160,160,192
232:flute:96,32,64
233:fog:224,32,64
234:food_other:96,160,64
235:food_processor:224,160,64
236:football:96,32,192
237:football_helmet:224,32,192
238:footwear:96,160,192
239:fork:224,160,192
240:fountain:32,96,64
241:fox:160,96,64
242:french_fries:32,224,64
243:french_horn:160,224,64
244:frisbee:32,96,192
245:frog:160,96,192
246:fruit:32,224,192
247:frying_pan:160,224,192
248:furniture:96,96,64
249:furniture_other:224,96,64
250:gas_stove:96,224,64
251:giant_panda:224,224,64
252:giraffe:96,96,192
253:girl:224,96,192
254:glasses:96,224,192
255:glove:224,224,192
256:goat:0,0,32
257:goggles:128,0,32
258:goldfish:0,128,32
259:golf_ball:128,128,32
260:golf_cart:0,0,160
261:golfcart:128,0,160
262:gondola:0,128,160
263:goose:128,128,160
264:grape:64,0,32
265:grapefruit:192,0,32
266:grass:64,128,32
267:gravel:192,128,32
268:ground:64,0,160
269:ground_other:192,0,160
270:guacamole:64,128,160
271:guitar:192,128,160
272:hair_brush:0,64,32
273:hair_drier:128,64,32
274:hair_dryer:0,192,32
275:hair_spray:128,192,32
276:hamburger:0,64,160
277:hammer:128,64,160
278:hamster:0,192,160
279:handbag:128,192,160
280:handgun:64,64,32
281:harbor_seal:192,64,32
282:harmonica:64,192,32
283:harp:192,192,32
284:harpsichord:64,64,160
285:hat:192,64,160
286:hat_with_a_wide_brim:64,192,160
287:head_cabbage:192,192,160
288:headphones:0,0,96
289:helicopter:128,0,96
290:helmet:0,128,96
291:high_heels:128,128,96
292:hill:0,0,224
293:hippopotamus:128,0,224
294:home_appliance:0,128,224
295:honeycomb:128,128,224
296:horizontal_bar:64,0,96
297:horn:192,0,96
298:horse:64,128,96
299:hot_dog:192,128,96
300:hotdog:64,0,224
301:house:192,0,224
302:houseplant:64,128,224
303:human:192,128,224
304:human_arm:0,64,96
305:human_beard:128,64,96
306:human_ear:0,192,96
307:human_eye:128,192,96
308:human_face:0,64,224
309:human_foot:128,64,224
310:human_hair:0,192,224
311:human_hand:128,192,224
312:human_head:64,64,96
313:human_leg:192,64,96
314:human_mouth:64,192,96
315:human_nose:192,192,96
316:ice_cream:64,64,224
317:ignore:192,64,224
318:infant_bed:64,192,224
319:insect:192,192,224
320:invertebrate:32,0,32
321:ipod:160,0,32
322:isopod:32,128,32
323:jacket:160,128,32
324:jaguar:32,0,160
325:jeans:160,0,160
326:jellyfish:32,128,160
327:jet_ski:160,128,160
328:jug:96,0,32
329:juice:224,0,32
330:kangaroo:96,128,32
331:kettle:224,128,32
332:keyboard:96,0,160
333:kitchen_appliance:224,0,160
334:kitchen_dining_room_table:96,128,160
335:kitchen_knife:224,128,160
336:kite:32,64,32
337:knife:160,64,32
338:koala_bear:32,192,32
339:ladder:160,192,32
340:ladle:32,64,160
341:ladybug:160,64,160
342:lamp:32,192,160
343:land_vehicle:160,192,160
344:lantern:96,64,32
345:laptop:224,64,32
346:lavender:96,192,32
347:leaves:224,192,32
348:lemon:96,64,160
349:leopard:224,64,160
350:license_plate:96,192,160
351:lifejacket:224,192,160
352:light:32,0,96
353:light_bulb:160,0,96
354:light_switch:32,128,96
355:lighthouse:160,128,96
356:lily:32,0,224
357:limousine:160,0,224
358:lion:32,128,224
359:lipstick:160,128,224
360:lizard:96,0,96
361:lobster:224,0,96
362:loveseat:96,128,96
363:luggage_and_bags:224,128,96
364:lynx:96,0,224
365:maillot:224,0,224
366:man:96,128,224
367:mango:224,128,224
368:maple:32,64,96
369:maraca:160,64,96
370:marine_invertebrates:32,192,96
371:marine_mammal:160,192,96
372:mat:32,64,224
373:measuring_cup:160,64,224
374:mechanical_fan:32,192,224
375:metal:160,192,224
376:microphone:96,64,96
377:microwave:224,64,96
378:microwave_oven:96,192,96
379:milk_can:224,192,96
380:miniskirt:96,64,224
381:mirror:224,64,224
382:mirror_stuff:96,192,224
383:misc:224,192,224
384:missile:0,32,32
385:mixer:128,32,32
386:mobile_phone:0,160,32
387:monkey:128,160,32
388:moss:0,32,160
389:moths_and_butterflies:128,32,160
390:motorbike:0,160,160
391:motorcycle:128,160,160
392:mountain:64,32,32
393:mouse:192,32,32
394:mud:64,160,32
395:muffin:192,160,32
396:mug:64,32,160
397:mule:192,32,160
398:mushroom:64,160,160
399:musical_instrument:192,160,160
400:musical_keyboard:0,96,32
401:nail:128,96,32
402:napkin:0,224,32
403:nature:128,224,32
404:neck_brace:0,96,160
405:necklace:128,96,160
406:net:0,224,160
407:nightstand:128,224,160
408:non_vehicle:64,96,32
409:obj:192,96,32
410:object:64,224,32
411:oboe:192,224,32
412:office_building:64,96,160
413:office_supplies:192,96,160
414:on_rails:64,224,160
415:orange:192,224,160
416:organ:0,32,96
417:ostrich:128,32,96
418:otter:0,160,96
419:oven:128,160,96
420:owl:0,32,224
421:oyster:128,32,224
422:paddle:0,160,224
423:palm_tree:128,160,224
424:pancake:64,32,96
425:paper:192,32,96
426:paper_towel:64,160,96
427:parachute:192,160,96
428:parking:64,32,224
429:parking_meter:192,32,224
430:parrot:64,160,224
431:pasta:192,160,224
432:pavement:0,96,96
433:peach:128,96,96
434:pear:0,224,96
435:pedestrian:128,224,96
436:pen:0,96,224
437:pencil_box:128,96,224
438:pencil_sharpener:0,224,224
439:penguin:128,224,224
440:perfume:64,96,96
441:person:192,96,96
442:personal_care:64,224,96
443:piano:192,224,96
444:picnic_basket:64,96,224
445:picture_frame:192,96,224
446:pig:64,224,224
447:pillow:192,224,224
448:pineapple:32,32,32
449:ping_pong_ball:160,32,32
450:pitcher:32,160,32
451:pizza:160,160,32
452:plant_other:32,32,160
453:plastic:160,32,160
454:plastic_bag:32,160,160
455:plate:160,160,160
456:plate_rack:96,32,32
457:platform:224,32,32
458:platter:96,160,32
459:playingfield:224,160,32
460:plumbing_fixture:96,32,160
461:polar_bear:224,32,160
462:pole:96,160,160
463:pole_group:224,160,160
464:pomegranate:32,96,32
465:popcorn:160,96,32
466:popsicle:32,224,32
467:porch:160,224,32
468:porcupine:32,96,160
469:poster:160,96,160
470:potato:32,224,160
471:potted_plant:160,224,160
472:pottedplant:96,96,32
473:power_drill:224,96,32
474:power_plugs_and_sockets:96,224,32
475:pressure_cooker:224,224,32
476:pretzel:96,96,160
477:printer:224,96,160
478:puck:96,224,160
479:pumpkin:224,224,160
480:punching_bag:32,32,96
481:purse:160,32,96
482:rabbit:32,160,96
483:raccoon:160,160,96
484:racket:32,32,224
485:radish:160,32,224
486:rail:32,160,224
487:rail_track:160,160,224
488:railing:96,32,96
489:railroad:224,32,96
490:raven:96,160,96
491:ray:224,160,96
492:red_panda:96,32,224
493:refrigerator:224,32,224
494:remote:96,160,224
495:remote_control:224,160,224
496:reptile:32,96,96
497:rhinoceros:160,96,96
498:rider:32,224,96
499:rifle:160,224,96
500:ring_binder:32,96,224
501:river:160,96,224
502:road:32,224,224
503:rock:160,224,224
504:rocket:96,96,96
505:roller_skates:224,96,96
506:roof:96,224,96
507:rose:224,224,96
508:rubber_eraser:96,96,224
509:rug:224,96,224
510:rugby_ball:96,224,224
511:ruler:224,224,224
512:salad:16,0,0
513:salt_and_pepper_shakers:144,0,0
514:salt_or_pepper_shaker:16,128,0
515:sand:144,128,0
516:sandal:16,0,128
517:sandwich:144,0,128
518:saucer:16,128,128
519:saxophone:144,128,128
520:scarf:80,0,0
521:scissors:208,0,0
522:scoreboard:80,128,0
523:scorpion:208,128,0
524:screwdriver:80,0,128
525:sculpture:208,0,128
526:sea:80,128,128
527:sea_lion:208,128,128
528:sea_turtle:16,64,0
529:seafood:144,64,0
530:seahorse:16,192,0
531:seal:144,192,0
532:seat_belt:16,64,128
533:segway:144,64,128
534:serving_tray:16,192,128
535:sewing_machine:144,192,128
536:shark:80,64,0
537:sheep:208,64,0
538:shelf:80,192,0
539:shellfish:208,192,0
540:shirt:80,64,128
541:shoe:208,64,128
542:shorts:80,192,128
543:shotgun:208,192,128
544:shower:16,0,64
545:shrimp:144,0,64
546:sidewalk:16,128,64
547:sink:144,128,64
548:skateboard:16,0,192
549:ski:144,0,192
550:skirt:16,128,192
551:skis:144,128,192
552:skull:80,0,64
553:skunk:208,0,64
554:sky:80,128,64
555:sky_other:208,128,64
556:skyscraper:80,0,192
557:slow_cooker:208,0,192
558:snail:80,128,192
559:snake:208,128,192
560:snow:16,64,64
561:snowboard:144,64,64
562:snowman:16,192,64
563:snowmobile:144,192,64
564:snowplow:16,64,192
565:soap_dispenser:144,64,192
566:soccer_ball:16,192,192
567:sock:144,192,192
568:sofa:80,64,64
569:sofa_bed:208,64,64
570:solid_other:80,192,64
571:sombrero:208,192,64
572:sparrow:80,64,192
573:spatula:208,64,192
574:spider:80,192,192
575:spoon:208,192,192
576:sports_ball:48,0,0
577:sports_uniform:176,0,0
578:squash:48,128,0
579:squirrel:176,128,0
580:stairs:48,0,128
581:starfish:176,0,128
582:start:48,128,128
583:static:176,128,128
584:stationary_bicycle:112,0,0
585:stethoscope:240,0,0
586:stone:112,128,0
587:stool:240,128,0
588:stop:112,0,128
589:stop_sign:240,0,128
590:stove:112,128,128
591:strainer:240,128,128
592:straw:48,64,0
593:strawberry:176,64,0
594:street_light:48,192,0
595:street_sign:176,192,0
596:stretcher:48,64,128
597:structural_other:176,64,128
598:studio_couch:48,192,128
599:submarine_sandwich:176,192,128
600:suit:112,64,0
601:suitcase:240,64,0
602:sun_hat:112,192,0
603:sunflower:240,192,0
604:sunglasses:112,64,128
605:surfboard:240,64,128
606:sushi:112,192,128
607:swan:240,192,128
608:swim_cap:48,0,64
609:swimming_pool:176,0,64
610:swimming_trunks:48,128,64
611:swimwear:176,128,64
612:swine:48,0,192
613:sword:176,0,192
614:syringe:48,128,192
615:table:176,128,192
616:table_tennis_racket:112,0,64
617:tablet_computer:240,0,64
618:tableware:112,128,64
619:taco:240,128,64
620:tank:112,0,192
621:tap:240,0,192
622:tape_player:112,128,192
623:tart:240,128,192
624:taxi:48,64,64
625:tea:176,64,64
626:teapot:48,192,64
627:teddy_bear:176,192,64
628:telephone:48,64,192
629:television:176,64,192
630:tennis_ball:48,192,192
631:tennis_racket:176,192,192
632:tent:112,64,64
633:terrain:240,64,64
634:textile_other:112,192,64
635:tiara:240,192,64
636:tick:112,64,192
637:tie:240,64,192
638:tiger:112,192,192
639:tin_can:240,192,192
640:tire:16,32,0
641:toaster:144,32,0
642:toilet:16,160,0
643:toilet_paper:144,160,0
644:tomato:16,32,128
645:toothbrush:144,32,128
646:torch:16,160,128
647:tortoise:144,160,128
648:towel:80,32,0
649:tower:208,32,0
650:toy:80,160,0
651:traffic_light:208,160,0
652:traffic_sign:80,32,128
653:trailer:208,32,128
654:train:80,160,128
655:tram:208,160,128
656:treadmill:16,96,0
657:tree:144,96,0
658:tripod:16,224,0
659:trombone:144,224,0
660:trousers:16,96,128
661:truck:144,96,128
662:trumpet:16,224,128
663:tunnel:144,224,128
664:turkey:80,96,0
665:turtle:208,96,0
666:tv:80,224,0
667:tv_or_monitor:208,224,0
668:tvmonitor:80,96,128
669:umbrella:208,96,128
670:undefined:80,224,128
671:unicycle:208,224,128
672:unlabeled:16,32,64
673:vacuum:144,32,64
674:van:16,160,64
675:vase:144,160,64
676:vegetable:16,32,192
677:vegetation:144,32,192
678:vehicle:16,160,192
679:vehicle_registration_plate:144,160,192
680:violin:80,32,64
681:void:208,32,64
682:volleyball:80,160,64
683:waffle:208,160,64
684:waffle_iron:80,32,192
685:wall:208,32,192
686:wall_brick:80,160,192
687:wall_clock:208,160,192
688:wall_concrete:16,96,64
689:wall_other:144,96,64
690:wall_panel:16,224,64
691:wall_stone:144,224,64
692:wall_tile:16,96,192
693:wall_wood:144,96,192
694:washer:16,224,192
695:washing_machine:144,224,192
696:waste_container:80,96,64
697:watch:208,96,64
698:water_bottle:80,224,64
699:water_other:208,224,64
700:watercraft:80,96,192
701:waterdrops:208,96,192
702:watermelon:80,224,192
703:weapon:208,224,192
704:whale:48,32,0
705:wheel:176,32,0
706:wheelchair:48,160,0
707:whiteboard:176,160,0
708:willow:48,32,128
709:window:176,32,128
710:window_blind:48,160,128
711:window_other:176,160,128
712:wine:112,32,0
713:wine_bottle:240,32,0
714:wine_glass:112,160,0
715:winter_melon:240,160,0
716:wok:112,32,128
717:woman:240,32,128
718:wood:112,160,128
719:wood_burning_stove:240,160,128
720:woodpecker:48,96,0
721:wrench:176,96,0
722:zebra:48,224,0
723:zucchini:176,224,0

@ -110,8 +110,8 @@ class _Converter:
self._images_dir = images_dir
def get_label(self, label_id):
return self._strip_label(self._extractor. \
categories()[AnnotationType.label].items[label_id].name)
return self._extractor. \
categories()[AnnotationType.label].items[label_id].name
def save_subsets(self):
subsets = self._extractor.subsets()
@ -207,7 +207,7 @@ class _Converter:
obj_elem = ET.SubElement(root_elem, 'object')
obj_label = self.get_label(obj.label)
obj_label = self.get_label(obj.label)
ET.SubElement(obj_elem, 'name').text = obj_label
if 'pose' in attr:
@ -357,8 +357,7 @@ class _Converter:
for item, item_labels in class_lists.items():
if not item_labels:
continue
item_labels = [self._strip_label(self.get_label(l))
for l in item_labels]
item_labels = [self.get_label(l) for l in item_labels]
presented = label in item_labels
f.write('%s % d\n' % (item, 1 if presented else -1))
@ -410,23 +409,37 @@ class _Converter:
path = osp.join(self._save_dir, VocPath.LABELMAP_FILE)
write_label_map(path, self._label_map)
@staticmethod
def _strip_label(label):
return label.lower().strip()
def _load_categories(self, label_map_source=None):
if label_map_source == LabelmapType.voc.name:
# strictly use VOC default labelmap
# use the default VOC colormap
label_map = make_voc_label_map()
elif label_map_source == LabelmapType.source.name:
# generate colormap from the input dataset
elif label_map_source == LabelmapType.source.name and \
AnnotationType.mask not in self._extractor.categories():
# generate colormap for input labels
labels = self._extractor.categories() \
.get(AnnotationType.label, LabelCategories())
label_map = OrderedDict()
label_map['background'] = [None, [], []]
for item in labels.items:
label_map[self._strip_label(item.name)] = [None, [], []]
label_map[item.name] = [None, [], []]
elif label_map_source == LabelmapType.source.name and \
AnnotationType.mask in self._extractor.categories():
# use source colormap
labels = self._extractor.categories()[AnnotationType.label]
colors = self._extractor.categories()[AnnotationType.mask]
label_map = OrderedDict()
has_black = False
for idx, item in enumerate(labels.items):
color = colors.colormap.get(idx)
if idx is not None:
if color == (0, 0, 0):
has_black = True
label_map[item.name] = [color, [], []]
if not has_black and 'background' not in label_map:
label_map['background'] = [(0, 0, 0), [], []]
label_map.move_to_end('background', last=False)
elif label_map_source in [LabelmapType.guess.name, None]:
# generate colormap for union of VOC and input dataset labels
@ -436,11 +449,10 @@ class _Converter:
source_labels = self._extractor.categories() \
.get(AnnotationType.label, LabelCategories())
for label in source_labels.items:
label_name = self._strip_label(label.name)
if label_name not in label_map:
if label.name not in label_map:
rebuild_colormap = True
if label.attributes or label_name not in label_map:
label_map[label_name] = [None, [], label.attributes]
if label.attributes or label.name not in label_map:
label_map[label.name] = [None, [], label.attributes]
if rebuild_colormap:
for item in label_map.values():
@ -469,27 +481,26 @@ class _Converter:
self._label_id_mapping = self._make_label_id_map()
def _is_label(self, s):
return self._label_map.get(self._strip_label(s)) is not None
return self._label_map.get(s) is not None
def _is_part(self, s):
s = self._strip_label(s)
for label_desc in self._label_map.values():
if s in label_desc[1]:
return True
return False
def _is_action(self, label, s):
return self._strip_label(s) in self._get_actions(label)
return s in self._get_actions(label)
def _get_actions(self, label):
label_desc = self._label_map.get(self._strip_label(label))
label_desc = self._label_map.get(label)
if not label_desc:
return []
return label_desc[2]
def _make_label_id_map(self):
source_labels = {
id: self._strip_label(label.name) for id, label in
id: label.name for id, label in
enumerate(self._extractor.categories().get(
AnnotationType.label, LabelCategories()).items)
}

@ -9,6 +9,12 @@ from datumaro.util.image import lazy_image, load_image
def generate_colormap(length=256):
"""
Generates colors using PASCAL VOC algorithm.
Returns index -> (R, G, B) mapping.
"""
def get_bit(number, index):
return (number >> index) & 1

@ -708,7 +708,7 @@ class VocConverterTest(TestCase):
SrcExtractor(), VocConverter(label_map='guess'),
test_dir, target_dataset=DstExtractor())
def test_dataset_with_source_labelmap(self):
def test_dataset_with_source_labelmap_undefined(self):
class SrcExtractor(TestExtractorBase):
def __iter__(self):
yield DatasetItem(id=1, annotations=[
@ -718,7 +718,7 @@ class VocConverterTest(TestCase):
def categories(self):
label_cat = LabelCategories()
label_cat.add('Label_1') # should become lowercase
label_cat.add('Label_1')
label_cat.add('label_2')
return {
AnnotationType.label: label_cat,
@ -727,7 +727,7 @@ class VocConverterTest(TestCase):
class DstExtractor(TestExtractorBase):
def __iter__(self):
yield DatasetItem(id=1, annotations=[
Bbox(2, 3, 4, 5, label=self._label('label_1'),
Bbox(2, 3, 4, 5, label=self._label('Label_1'),
id=1, group=1, attributes={
'truncated': False,
'difficult': False,
@ -746,7 +746,7 @@ class VocConverterTest(TestCase):
def categories(self):
label_map = OrderedDict()
label_map['background'] = [None, [], []]
label_map['label_1'] = [None, [], []]
label_map['Label_1'] = [None, [], []]
label_map['label_2'] = [None, [], []]
return VOC.make_voc_categories(label_map)
@ -755,6 +755,52 @@ class VocConverterTest(TestCase):
SrcExtractor(), VocConverter(label_map='source'),
test_dir, target_dataset=DstExtractor())
def test_dataset_with_source_labelmap_defined(self):
class SrcExtractor(TestExtractorBase):
def __iter__(self):
yield DatasetItem(id=1, annotations=[
Bbox(2, 3, 4, 5, label=0, id=1),
Bbox(1, 2, 3, 4, label=2, id=2),
])
def categories(self):
label_map = OrderedDict()
label_map['label_1'] = [(1, 2, 3), [], []]
label_map['background'] = [(0, 0, 0), [], []] # can be not 0
label_map['label_2'] = [(3, 2, 1), [], []]
return VOC.make_voc_categories(label_map)
class DstExtractor(TestExtractorBase):
def __iter__(self):
yield DatasetItem(id=1, annotations=[
Bbox(2, 3, 4, 5, label=self._label('label_1'),
id=1, group=1, attributes={
'truncated': False,
'difficult': False,
'occluded': False,
}
),
Bbox(1, 2, 3, 4, label=self._label('label_2'),
id=2, group=2, attributes={
'truncated': False,
'difficult': False,
'occluded': False,
}
),
])
def categories(self):
label_map = OrderedDict()
label_map['label_1'] = [(1, 2, 3), [], []]
label_map['background'] = [(0, 0, 0), [], []]
label_map['label_2'] = [(3, 2, 1), [], []]
return VOC.make_voc_categories(label_map)
with TestDir() as test_dir:
self._test_save_and_load(
SrcExtractor(), VocConverter(label_map='source'),
test_dir, target_dataset=DstExtractor())
def test_dataset_with_fixed_labelmap(self):
class SrcExtractor(TestExtractorBase):
def __iter__(self):

Loading…
Cancel
Save