Răsfoiți Sursa

Add group_id for shape annotation

Kentaro Wada 5 ani în urmă
părinte
comite
3936c55023

+ 241 - 264
examples/instance_segmentation/data_annotated/2011_000003.json

@@ -1,499 +1,480 @@
 {
-  "version": "3.14.2",
+  "version": "3.22.0",
   "flags": {},
   "shapes": [
     {
-      "label": "person-1",
-      "line_color": null,
-      "fill_color": null,
+      "label": "person",
       "points": [
         [
-          250.984126984127,
-          106.92063492063491
+          250.8142292490119,
+          107.33596837944665
         ],
         [
-          229.984126984127,
-          118.92063492063491
+          229.8142292490119,
+          119.33596837944665
         ],
         [
-          221.984126984127,
-          134.9206349206349
+          221.8142292490119,
+          135.33596837944665
         ],
         [
-          223.984126984127,
-          147.9206349206349
+          223.8142292490119,
+          148.33596837944665
         ],
         [
-          217.984126984127,
-          160.9206349206349
+          217.8142292490119,
+          161.33596837944665
         ],
         [
-          202.984126984127,
-          167.9206349206349
+          202.8142292490119,
+          168.33596837944665
         ],
         [
-          192.984126984127,
-          199.9206349206349
+          192.8142292490119,
+          200.33596837944665
         ],
         [
-          194.984126984127,
-          221.9206349206349
+          194.8142292490119,
+          222.33596837944665
         ],
         [
-          199.984126984127,
-          226.9206349206349
+          199.8142292490119,
+          227.33596837944665
         ],
         [
-          191.984126984127,
-          233.9206349206349
+          191.8142292490119,
+          234.33596837944665
         ],
         [
-          197.984126984127,
-          263.92063492063494
+          197.8142292490119,
+          264.3359683794467
         ],
         [
-          213.984126984127,
-          294.92063492063494
+          213.8142292490119,
+          295.3359683794467
         ],
         [
-          214.984126984127,
-          319.92063492063494
+          214.8142292490119,
+          320.3359683794467
         ],
         [
-          221.984126984127,
-          326.92063492063494
+          221.8142292490119,
+          327.3359683794467
         ],
         [
-          235.984126984127,
-          325.92063492063494
+          235.8142292490119,
+          326.3359683794467
         ],
         [
-          240.984126984127,
-          322.92063492063494
+          240.8142292490119,
+          323.3359683794467
         ],
         [
-          235.984126984127,
-          297.92063492063494
+          235.8142292490119,
+          298.3359683794467
         ],
         [
-          238.984126984127,
-          286.92063492063494
+          238.8142292490119,
+          287.3359683794467
         ],
         [
-          234.984126984127,
-          267.92063492063494
+          234.8142292490119,
+          268.3359683794467
         ],
         [
-          257.984126984127,
-          257.92063492063494
+          257.81422924901193,
+          258.3359683794467
         ],
         [
-          264.984126984127,
-          263.92063492063494
+          264.81422924901193,
+          264.3359683794467
         ],
         [
-          256.984126984127,
-          272.92063492063494
+          256.81422924901193,
+          273.3359683794467
         ],
         [
-          259.984126984127,
-          281.92063492063494
+          259.81422924901193,
+          282.3359683794467
         ],
         [
-          284.984126984127,
-          287.92063492063494
+          284.81422924901193,
+          288.3359683794467
         ],
         [
-          297.984126984127,
-          277.92063492063494
+          297.81422924901193,
+          278.3359683794467
         ],
         [
-          288.984126984127,
-          269.92063492063494
+          288.81422924901193,
+          270.3359683794467
         ],
         [
-          281.984126984127,
-          269.92063492063494
+          281.81422924901193,
+          270.3359683794467
         ],
         [
-          283.984126984127,
-          263.92063492063494
+          283.81422924901193,
+          264.3359683794467
         ],
         [
-          292.984126984127,
-          260.92063492063494
+          292.81422924901193,
+          261.3359683794467
         ],
         [
-          308.984126984127,
-          235.9206349206349
+          308.81422924901193,
+          236.33596837944665
         ],
         [
-          313.984126984127,
-          216.9206349206349
+          313.81422924901193,
+          217.33596837944665
         ],
         [
-          309.984126984127,
-          207.9206349206349
+          309.81422924901193,
+          208.33596837944665
         ],
         [
-          312.984126984127,
-          201.9206349206349
+          312.81422924901193,
+          202.33596837944665
         ],
         [
-          308.984126984127,
-          184.9206349206349
+          308.81422924901193,
+          185.33596837944665
         ],
         [
-          291.984126984127,
-          172.9206349206349
+          291.81422924901193,
+          173.33596837944665
         ],
         [
-          269.984126984127,
-          158.9206349206349
+          269.81422924901193,
+          159.33596837944665
         ],
         [
-          261.984126984127,
-          153.9206349206349
+          261.81422924901193,
+          154.33596837944665
         ],
         [
-          264.984126984127,
-          141.9206349206349
+          264.81422924901193,
+          142.33596837944665
         ],
         [
-          273.984126984127,
-          136.9206349206349
+          273.81422924901193,
+          137.33596837944665
         ],
         [
-          278.984126984127,
-          129.9206349206349
+          278.81422924901193,
+          130.33596837944665
         ],
         [
-          270.984126984127,
-          120.92063492063491
+          270.81422924901193,
+          121.33596837944665
         ]
       ],
+      "group_id": null,
       "shape_type": "polygon",
-      "flags": {
-        "occluded": true,
-        "truncated": false,
-        "male": true
-      }
+      "flags": {}
     },
     {
-      "label": "person-2",
-      "line_color": null,
-      "fill_color": null,
+      "label": "person",
       "points": [
         [
-          482,
-          85
+          482.81422924901193,
+          85.33596837944665
         ],
         [
-          468,
-          90
+          468.81422924901193,
+          90.33596837944665
         ],
         [
-          460,
-          110
+          460.81422924901193,
+          110.33596837944665
         ],
         [
-          460,
-          127
+          460.81422924901193,
+          127.33596837944665
         ],
         [
-          444,
-          137
+          444.81422924901193,
+          137.33596837944665
         ],
         [
-          419,
-          153
+          419.81422924901193,
+          153.33596837944665
         ],
         [
-          410,
-          163
+          410.81422924901193,
+          163.33596837944665
         ],
         [
-          403,
-          168
+          403.81422924901193,
+          168.33596837944665
         ],
         [
-          394,
-          170
+          394.81422924901193,
+          170.33596837944665
         ],
         [
-          386,
-          168
+          386.81422924901193,
+          168.33596837944665
         ],
         [
-          386,
-          184
+          386.81422924901193,
+          184.33596837944665
         ],
         [
-          392,
-          182
+          392.81422924901193,
+          182.33596837944665
         ],
         [
-          410,
-          187
+          410.81422924901193,
+          187.33596837944665
         ],
         [
-          414,
-          192
+          414.81422924901193,
+          192.33596837944665
         ],
         [
-          437,
-          189
+          437.81422924901193,
+          189.33596837944665
         ],
         [
-          434,
-          204
+          434.81422924901193,
+          204.33596837944665
         ],
         [
-          390,
-          195
+          390.81422924901193,
+          195.33596837944665
         ],
         [
-          386,
-          195
+          386.81422924901193,
+          195.33596837944665
         ],
         [
-          387,
-          208
+          387.81422924901193,
+          208.33596837944665
         ],
         [
-          381,
-          212
+          381.81422924901193,
+          212.33596837944665
         ],
         [
-          372,
-          212
+          372.81422924901193,
+          212.33596837944665
         ],
         [
-          372,
-          216
+          372.81422924901193,
+          216.33596837944665
         ],
         [
-          400,
-          270
+          400.81422924901193,
+          270.3359683794467
         ],
         [
-          389,
-          272
+          389.81422924901193,
+          272.3359683794467
         ],
         [
-          389,
-          274
+          389.81422924901193,
+          274.3359683794467
         ],
         [
-          403,
-          282
+          403.81422924901193,
+          282.3359683794467
         ],
         [
-          444,
-          283
+          444.81422924901193,
+          283.3359683794467
         ],
         [
-          443,
-          259
+          443.81422924901193,
+          259.3359683794467
         ],
         [
-          426,
-          244
+          426.81422924901193,
+          244.33596837944665
         ],
         [
-          462,
-          256
+          462.81422924901193,
+          256.3359683794467
         ],
         [
-          474,
-          270
+          474.81422924901193,
+          270.3359683794467
         ],
         [
-          477,
-          280
+          477.81422924901193,
+          280.3359683794467
         ],
         [
-          473,
-          289
+          473.81422924901193,
+          289.3359683794467
         ],
         [
-          471,
-          296
+          471.81422924901193,
+          296.3359683794467
         ],
         [
-          472,
-          317
+          472.81422924901193,
+          317.3359683794467
         ],
         [
-          480,
-          332
+          480.81422924901193,
+          332.3359683794467
         ],
         [
-          494,
-          335
+          494.81422924901193,
+          335.3359683794467
         ],
         [
-          498,
-          329
+          498.81422924901193,
+          329.3359683794467
         ],
         [
-          494,
-          308
+          494.81422924901193,
+          308.3359683794467
         ],
         [
-          499,
-          297
+          499.81422924901193,
+          297.3359683794467
         ],
         [
-          499,
-          90
+          499.81422924901193,
+          90.33596837944665
         ]
       ],
+      "group_id": 0,
       "shape_type": "polygon",
-      "flags": {
-        "occluded": true,
-        "truncated": true,
-        "male": true
-      }
+      "flags": {}
     },
     {
-      "label": "bottle",
-      "line_color": null,
-      "fill_color": null,
+      "label": "person",
       "points": [
         [
-          374,
-          159
+          370.81422924901193,
+          170.33596837944665
         ],
         [
-          369,
-          170
+          366.81422924901193,
+          173.33596837944665
         ],
         [
-          369,
-          210
+          365.81422924901193,
+          182.33596837944665
         ],
         [
-          375,
-          212
-        ],
+          368.81422924901193,
+          185.33596837944665
+        ]
+      ],
+      "group_id": 0,
+      "shape_type": "polygon",
+      "flags": {}
+    },
+    {
+      "label": "bottle",
+      "points": [
         [
-          387,
-          209
+          374.81422924901193,
+          159.33596837944665
         ],
         [
-          385,
-          185
+          369.81422924901193,
+          170.33596837944665
         ],
         [
-          385,
-          168
+          369.81422924901193,
+          210.33596837944665
         ],
         [
-          385,
-          165
+          375.81422924901193,
+          212.33596837944665
         ],
         [
-          382,
-          159
-        ]
-      ],
-      "shape_type": "polygon",
-      "flags": {
-        "occluded": false,
-        "truncated": false
-      }
-    },
-    {
-      "label": "person-2",
-      "line_color": null,
-      "fill_color": null,
-      "points": [
+          387.81422924901193,
+          209.33596837944665
+        ],
         [
-          370,
-          170
+          385.81422924901193,
+          185.33596837944665
         ],
         [
-          366,
-          173
+          385.81422924901193,
+          168.33596837944665
         ],
         [
-          365,
-          182
+          385.81422924901193,
+          165.33596837944665
         ],
         [
-          368,
-          185
+          382.81422924901193,
+          159.33596837944665
         ]
       ],
+      "group_id": null,
       "shape_type": "polygon",
-      "flags": {
-        "occluded": true,
-        "truncated": false,
-        "male": false
-      }
+      "flags": {}
     },
     {
       "label": "__ignore__",
-      "line_color": null,
-      "fill_color": null,
       "points": [
         [
-          338,
-          266
+          338.81422924901193,
+          266.3359683794467
         ],
         [
-          313,
-          269
+          313.81422924901193,
+          269.3359683794467
         ],
         [
-          297,
-          277
+          297.81422924901193,
+          277.3359683794467
         ],
         [
-          282,
-          288
+          282.81422924901193,
+          288.3359683794467
         ],
         [
-          273,
-          302
+          273.81422924901193,
+          302.3359683794467
         ],
         [
-          272,
-          320
+          272.81422924901193,
+          320.3359683794467
         ],
         [
-          279,
-          337
+          279.81422924901193,
+          337.3359683794467
         ],
         [
-          428,
-          337
+          428.81422924901193,
+          337.3359683794467
         ],
         [
-          432,
-          316
+          432.81422924901193,
+          316.3359683794467
         ],
         [
-          423,
-          296
+          423.81422924901193,
+          296.3359683794467
         ],
         [
-          403,
-          283
+          403.81422924901193,
+          283.3359683794467
         ],
         [
-          370,
-          270
+          370.81422924901193,
+          270.3359683794467
         ]
       ],
+      "group_id": null,
       "shape_type": "polygon",
-      "flags": {
-        "occluded": false,
-        "truncated": true
-      }
+      "flags": {}
     }
   ],
+  "imagePath": "2011_000003.jpg",
+  "imageData": null,
+  "imageHeight": 338,
+  "imageWidth": 500,
   "lineColor": [
     0,
     255,
@@ -505,9 +486,5 @@
     0,
     0,
     128
-  ],
-  "imagePath": "2011_000003.jpg",
-  "imageData": null,
-  "imageHeight": 338,
-  "imageWidth": 500
+  ]
 }

+ 45 - 31
examples/instance_segmentation/data_annotated/2011_000006.json

@@ -1,8 +1,9 @@
 {
-  "imagePath": "2011_000006.jpg",
+  "version": "3.22.0",
+  "flags": {},
   "shapes": [
     {
-      "line_color": null,
+      "label": "person",
       "points": [
         [
           204.936170212766,
@@ -105,11 +106,12 @@
           112.56382978723406
         ]
       ],
-      "fill_color": null,
-      "label": "person-1"
+      "group_id": null,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
-      "line_color": null,
+      "label": "person",
       "points": [
         [
           271.936170212766,
@@ -188,11 +190,12 @@
           148.56382978723406
         ]
       ],
-      "fill_color": null,
-      "label": "person-2"
+      "group_id": null,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
-      "line_color": null,
+      "label": "person",
       "points": [
         [
           308.936170212766,
@@ -259,11 +262,12 @@
           115.56382978723406
         ]
       ],
-      "fill_color": null,
-      "label": "person-3"
+      "group_id": null,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
-      "line_color": null,
+      "label": "chair",
       "points": [
         [
           308.936170212766,
@@ -326,11 +330,12 @@
           241.56382978723406
         ]
       ],
-      "fill_color": null,
-      "label": "chair"
+      "group_id": null,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
-      "line_color": null,
+      "label": "person",
       "points": [
         [
           425.936170212766,
@@ -357,11 +362,12 @@
           91.56382978723406
         ]
       ],
-      "fill_color": null,
-      "label": "person-4"
+      "group_id": null,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
-      "line_color": null,
+      "label": "__ignore__",
       "points": [
         [
           457.936170212766,
@@ -380,11 +386,12 @@
           87.56382978723406
         ]
       ],
-      "fill_color": null,
-      "label": "__ignore__"
+      "group_id": null,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
-      "line_color": null,
+      "label": "sofa",
       "points": [
         [
           183.936170212766,
@@ -423,11 +430,12 @@
           203.56382978723406
         ]
       ],
-      "fill_color": null,
-      "label": "sofa"
+      "group_id": 0,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
-      "line_color": null,
+      "label": "sofa",
       "points": [
         [
           103.93617021276599,
@@ -442,11 +450,12 @@
           311.56382978723406
         ]
       ],
-      "fill_color": null,
-      "label": "sofa"
+      "group_id": 0,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
-      "line_color": null,
+      "label": "sofa",
       "points": [
         [
           348.936170212766,
@@ -485,11 +494,12 @@
           164.56382978723406
         ]
       ],
-      "fill_color": null,
-      "label": "sofa"
+      "group_id": 0,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
-      "line_color": null,
+      "label": "sofa",
       "points": [
         [
           246.936170212766,
@@ -508,11 +518,15 @@
           256.56382978723406
         ]
       ],
-      "fill_color": null,
-      "label": "sofa"
+      "group_id": 0,
+      "shape_type": "polygon",
+      "flags": {}
     }
   ],
+  "imagePath": "2011_000006.jpg",
   "imageData": null,
+  "imageHeight": 375,
+  "imageWidth": 500,
   "lineColor": [
     0,
     255,

+ 47 - 38
examples/semantic_segmentation/data_annotated/2011_000003.json

@@ -1,9 +1,9 @@
 {
+  "version": "3.22.0",
+  "flags": {},
   "shapes": [
     {
       "label": "person",
-      "line_color": null,
-      "fill_color": null,
       "points": [
         [
           250.8142292490119,
@@ -169,12 +169,13 @@
           270.81422924901193,
           121.33596837944665
         ]
-      ]
+      ],
+      "group_id": null,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
       "label": "person",
-      "line_color": null,
-      "fill_color": null,
       "points": [
         [
           482.81422924901193,
@@ -340,12 +341,37 @@
           499.81422924901193,
           90.33596837944665
         ]
-      ]
+      ],
+      "group_id": 0,
+      "shape_type": "polygon",
+      "flags": {}
+    },
+    {
+      "label": "person",
+      "points": [
+        [
+          370.81422924901193,
+          170.33596837944665
+        ],
+        [
+          366.81422924901193,
+          173.33596837944665
+        ],
+        [
+          365.81422924901193,
+          182.33596837944665
+        ],
+        [
+          368.81422924901193,
+          185.33596837944665
+        ]
+      ],
+      "group_id": 0,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
       "label": "bottle",
-      "line_color": null,
-      "fill_color": null,
       "points": [
         [
           374.81422924901193,
@@ -383,35 +409,13 @@
           382.81422924901193,
           159.33596837944665
         ]
-      ]
-    },
-    {
-      "label": "person",
-      "line_color": null,
-      "fill_color": null,
-      "points": [
-        [
-          370.81422924901193,
-          170.33596837944665
-        ],
-        [
-          366.81422924901193,
-          173.33596837944665
-        ],
-        [
-          365.81422924901193,
-          182.33596837944665
-        ],
-        [
-          368.81422924901193,
-          185.33596837944665
-        ]
-      ]
+      ],
+      "group_id": null,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
       "label": "__ignore__",
-      "line_color": null,
-      "fill_color": null,
       "points": [
         [
           338.81422924901193,
@@ -461,9 +465,16 @@
           370.81422924901193,
           270.3359683794467
         ]
-      ]
+      ],
+      "group_id": null,
+      "shape_type": "polygon",
+      "flags": {}
     }
   ],
+  "imagePath": "2011_000003.jpg",
+  "imageData": null,
+  "imageHeight": 338,
+  "imageWidth": 500,
   "lineColor": [
     0,
     255,
@@ -475,7 +486,5 @@
     0,
     0,
     128
-  ],
-  "imagePath": "2011_000003.jpg",
-  "imageData": null
+  ]
 }

+ 47 - 33
examples/semantic_segmentation/data_annotated/2011_000006.json

@@ -1,9 +1,9 @@
 {
+  "version": "3.22.0",
+  "flags": {},
   "shapes": [
     {
       "label": "person",
-      "line_color": null,
-      "fill_color": null,
       "points": [
         [
           204.936170212766,
@@ -105,12 +105,13 @@
           216.936170212766,
           112.56382978723406
         ]
-      ]
+      ],
+      "group_id": null,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
       "label": "person",
-      "line_color": null,
-      "fill_color": null,
       "points": [
         [
           271.936170212766,
@@ -188,12 +189,13 @@
           296.936170212766,
           148.56382978723406
         ]
-      ]
+      ],
+      "group_id": null,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
       "label": "person",
-      "line_color": null,
-      "fill_color": null,
       "points": [
         [
           308.936170212766,
@@ -259,12 +261,13 @@
           336.936170212766,
           115.56382978723406
         ]
-      ]
+      ],
+      "group_id": null,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
       "label": "chair",
-      "line_color": null,
-      "fill_color": null,
       "points": [
         [
           308.936170212766,
@@ -326,12 +329,13 @@
           350.936170212766,
           241.56382978723406
         ]
-      ]
+      ],
+      "group_id": null,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
       "label": "person",
-      "line_color": null,
-      "fill_color": null,
       "points": [
         [
           425.936170212766,
@@ -357,12 +361,13 @@
           446.936170212766,
           91.56382978723406
         ]
-      ]
+      ],
+      "group_id": null,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
       "label": "__ignore__",
-      "line_color": null,
-      "fill_color": null,
       "points": [
         [
           457.936170212766,
@@ -380,12 +385,13 @@
           474.936170212766,
           87.56382978723406
         ]
-      ]
+      ],
+      "group_id": null,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
       "label": "sofa",
-      "line_color": null,
-      "fill_color": null,
       "points": [
         [
           183.936170212766,
@@ -423,12 +429,13 @@
           110.93617021276599,
           203.56382978723406
         ]
-      ]
+      ],
+      "group_id": 0,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
       "label": "sofa",
-      "line_color": null,
-      "fill_color": null,
       "points": [
         [
           103.93617021276599,
@@ -442,12 +449,13 @@
           97.93617021276599,
           311.56382978723406
         ]
-      ]
+      ],
+      "group_id": 0,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
       "label": "sofa",
-      "line_color": null,
-      "fill_color": null,
       "points": [
         [
           348.936170212766,
@@ -485,12 +493,13 @@
           353.936170212766,
           164.56382978723406
         ]
-      ]
+      ],
+      "group_id": 0,
+      "shape_type": "polygon",
+      "flags": {}
     },
     {
       "label": "sofa",
-      "line_color": null,
-      "fill_color": null,
       "points": [
         [
           246.936170212766,
@@ -508,9 +517,16 @@
           261.936170212766,
           256.56382978723406
         ]
-      ]
+      ],
+      "group_id": 0,
+      "shape_type": "polygon",
+      "flags": {}
     }
   ],
+  "imagePath": "2011_000006.jpg",
+  "imageData": null,
+  "imageHeight": 375,
+  "imageWidth": 500,
   "lineColor": [
     0,
     255,
@@ -522,7 +538,5 @@
     0,
     0,
     128
-  ],
-  "imagePath": "2011_000006.jpg",
-  "imageData": null
+  ]
 }

+ 23 - 8
labelme/app.py

@@ -895,7 +895,9 @@ class MainWindow(QtWidgets.QMainWindow):
         shape = self.labelList.get_shape_from_item(item)
         if shape is None:
             return
-        text, flags = self.labelDialog.popUp(shape.label, flags=shape.flags)
+        text, flags, group_id = self.labelDialog.popUp(
+            text=shape.label, flags=shape.flags, group_id=shape.group_id,
+        )
         if text is None:
             return
         if not self.validateLabel(text):
@@ -908,10 +910,14 @@ class MainWindow(QtWidgets.QMainWindow):
             return
         shape.label = text
         shape.flags = flags
-        item.setText(text)
+        shape.group_id = group_id
+        if shape.group_id is None:
+            item.setText(shape.label)
+        else:
+            item.setText('{} ({})'.format(shape.label, shape.group_id))
         self.setDirty()
-        if not self.uniqLabelList.findItems(text, Qt.MatchExactly):
-            self.uniqLabelList.addItem(text)
+        if not self.uniqLabelList.findItems(shape.label, Qt.MatchExactly):
+            self.uniqLabelList.addItem(shape.label)
             self.uniqLabelList.sortItems()
 
     def fileSearchChanged(self):
@@ -955,7 +961,11 @@ class MainWindow(QtWidgets.QMainWindow):
         self.actions.edit.setEnabled(n_selected == 1)
 
     def addLabel(self, shape):
-        item = QtWidgets.QListWidgetItem(shape.label)
+        if shape.group_id is None:
+            text = shape.label
+        else:
+            text = '{} ({})'.format(shape.label, shape.group_id)
+        item = QtWidgets.QListWidgetItem(text)
         item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
         item.setCheckState(Qt.Checked)
         self.labelList.itemsToShapes.append((item, shape))
@@ -963,7 +973,7 @@ class MainWindow(QtWidgets.QMainWindow):
         if not self.uniqLabelList.findItems(shape.label, Qt.MatchExactly):
             self.uniqLabelList.addItem(shape.label)
             self.uniqLabelList.sortItems()
-        self.labelDialog.addLabelHistory(item.text())
+        self.labelDialog.addLabelHistory(shape.label)
         for action in self.actions.onShapesPresent:
             action.setEnabled(True)
 
@@ -987,8 +997,11 @@ class MainWindow(QtWidgets.QMainWindow):
             points = shape['points']
             shape_type = shape['shape_type']
             flags = shape['flags']
+            group_id = shape.get('group_id')
 
-            shape = Shape(label=label, shape_type=shape_type)
+            shape = Shape(
+                label=label, shape_type=shape_type, group_id=group_id
+            )
             for x, y in points:
                 shape.addPoint(QtCore.QPointF(x, y))
             shape.close()
@@ -1020,6 +1033,7 @@ class MainWindow(QtWidgets.QMainWindow):
             return dict(
                 label=s.label.encode('utf-8') if PY2 else s.label,
                 points=[(p.x(), p.y()) for p in s.points],
+                group_id=s.group_id,
                 shape_type=s.shape_type,
                 flags=s.flags
             )
@@ -1127,7 +1141,8 @@ class MainWindow(QtWidgets.QMainWindow):
             text = ''
         if text:
             self.labelList.clearSelection()
-            self.addLabel(self.canvas.setLastLabel(text, flags))
+            shape = self.canvas.setLastLabel(text, flags)
+            self.addLabel(shape)
             self.actions.editMode.setEnabled(True)
             self.actions.undoLastPoint.setEnabled(False)
             self.actions.undo.setEnabled(True)

+ 1 - 0
labelme/label_file.py

@@ -88,6 +88,7 @@ class LabelFile(object):
                     points=s['points'],
                     shape_type=s.get('shape_type', 'polygon'),
                     flags=s.get('flags', {}),
+                    group_id=s.get('group_id')
                 )
                 for s in data['shapes']
             ]

+ 2 - 1
labelme/shape.py

@@ -37,8 +37,9 @@ class Shape(object):
     scale = 1.0
 
     def __init__(self, label=None, line_color=None, shape_type=None,
-                 flags=None):
+                 flags=None, group_id=None):
         self.label = label
+        self.group_id = group_id
         self.points = []
         self.fill = False
         self.selected = False

+ 22 - 4
labelme/widgets/label_dialog.py

@@ -43,9 +43,17 @@ class LabelDialog(QtWidgets.QDialog):
         self.edit.editingFinished.connect(self.postProcess)
         if flags:
             self.edit.textChanged.connect(self.updateFlags)
+        self.edit_group_id = QtWidgets.QLineEdit()
+        self.edit_group_id.setPlaceholderText('Group ID')
+        self.edit_group_id.setValidator(
+            QtGui.QRegExpValidator(QtCore.QRegExp(r'\d*'), None)
+        )
         layout = QtWidgets.QVBoxLayout()
         if show_text_field:
-            layout.addWidget(self.edit)
+            layout_edit = QtWidgets.QHBoxLayout()
+            layout_edit.addWidget(self.edit, 6)
+            layout_edit.addWidget(self.edit_group_id, 2)
+            layout.addLayout(layout_edit)
         # buttons
         self.buttonBox = bb = QtWidgets.QDialogButtonBox(
             QtWidgets.QDialogButtonBox.Ok | QtWidgets.QDialogButtonBox.Cancel,
@@ -178,7 +186,13 @@ class LabelDialog(QtWidgets.QDialog):
             flags[item.text()] = item.isChecked()
         return flags
 
-    def popUp(self, text=None, move=True, flags=None):
+    def getGroupId(self):
+        group_id = self.edit_group_id.text()
+        if group_id:
+            return int(group_id)
+        return None
+
+    def popUp(self, text=None, move=True, flags=None, group_id=None):
         if self._fit_to_content['row']:
             self.labelList.setMinimumHeight(
                 self.labelList.sizeHintForRow(0) * self.labelList.count() + 2
@@ -196,6 +210,10 @@ class LabelDialog(QtWidgets.QDialog):
             self.resetFlags(text)
         self.edit.setText(text)
         self.edit.setSelection(0, len(text))
+        if group_id is None:
+            self.edit_group_id.clear()
+        else:
+            self.edit_group_id.setText(str(group_id))
         items = self.labelList.findItems(text, QtCore.Qt.MatchFixedString)
         if items:
             if len(items) != 1:
@@ -207,6 +225,6 @@ class LabelDialog(QtWidgets.QDialog):
         if move:
             self.move(QtGui.QCursor.pos())
         if self.exec_():
-            return self.edit.text(), self.getFlags()
+            return self.edit.text(), self.getFlags(), self.getGroupId()
         else:
-            return None, None
+            return None, None, None

+ 6 - 3
tests/labelme_tests/widgets_tests/test_label_dialog.py

@@ -59,9 +59,10 @@ def test_LabelDialog_popUp(qtbot):
         qtbot.keyClick(widget.edit, QtCore.Qt.Key_Enter)  # NOQA
 
     QtCore.QTimer.singleShot(500, interact)
-    label, flags = widget.popUp('cat')
+    label, flags, group_id = widget.popUp('cat')
     assert label == 'person'
     assert flags == {}
+    assert group_id is None
 
     # popUp()
 
@@ -70,9 +71,10 @@ def test_LabelDialog_popUp(qtbot):
         qtbot.keyClick(widget.edit, QtCore.Qt.Key_Enter)  # NOQA
 
     QtCore.QTimer.singleShot(500, interact)
-    label, flags = widget.popUp()
+    label, flags, group_id = widget.popUp()
     assert label == 'person'
     assert flags == {}
+    assert group_id is None
 
     # popUp() + key_Up
 
@@ -82,6 +84,7 @@ def test_LabelDialog_popUp(qtbot):
         qtbot.keyClick(widget.edit, QtCore.Qt.Key_Enter)  # NOQA
 
     QtCore.QTimer.singleShot(500, interact)
-    label, flags = widget.popUp()
+    label, flags, group_id = widget.popUp()
     assert label == 'dog'
     assert flags == {}
+    assert group_id is None