labelImg操作麻烦,用opencv写了个假的,勉强能用

eternal-wisdom / 2024-10-23 / 原文

LabelImage.py:

  1 import cv2
  2 import os
  3 import copy
  4 
  5 
  6 
  7 def noNagInt(array=[]):
  8     newArray = []
  9     for single in array:
 10         if single < 0:
 11             newArray.append(0)
 12         else:
 13             newArray.append(int(single))
 14     return newArray
 15 
 16 
 17 def beRangeAble(array=[], limit=()):
 18     if array[0] > limit[1]:
 19         array[0] = limit[1] - 1
 20     if array[1] > limit[0]:
 21         array[1] = limit[0] - 1
 22     return array
 23 
 24 
 25 class MakeLabel:
 26     def __init__(self,
 27                  winName="",
 28                  presentImage=0,
 29                  resize=(1024, 720),
 30                  label=[],
 31                  root="",
 32                  train="",
 33                  val=""):
 34         self.frame = None
 35         self.size = resize
 36         self.frameShape = 480, 640, 3
 37         self.__frameDraw = None
 38         self.__presentFileInt = presentImage
 39         self.__presentFile = ""
 40         self.__root = root
 41         self.__train = train
 42         self.__val = val
 43 
 44         self.__label = label
 45         self.__labelOpt = self.__YYY(self.__label)
 46         self.__nowLabel = self.__labelOpt.getPresent()
 47         self.__boxes = {}
 48         for label in self.__label:
 49             self.__boxes[label] = self.__Box(label)
 50         self.__step = 15
 51         self.__record = [0, 0]
 52 
 53         self.__colorOpt = self.__Color()
 54         self.__color = {}
 55         for label in self.__label:
 56             self.__color[label] = self.__colorOpt.getColor()
 57 
 58         self.__frameWinName = winName
 59         self.__font = cv2.FONT_HERSHEY_SCRIPT_SIMPLEX
 60 
 61         self.__nextImage = False
 62         self.__LButtonDown = False
 63         self.__LButtonUp = True
 64 
 65         goodLuck = "Good Luck!"
 66         print(goodLuck)
 67 
 68     class __Box:
 69         def __init__(self, label):
 70             self.width = 0
 71             self.height = 0
 72             self.center = [0, 0]
 73             self.label = label
 74 
 75         def reset(self):
 76             self.width = 0
 77             self.height = 0
 78             self.center = [0, 0]
 79 
 80     class __YYY:
 81         def __init__(self, string):
 82             self.__index = 0
 83             self.string = string
 84             self.__length = len(string)
 85 
 86         def getPresent(self):
 87             return self.string[self.__index]
 88 
 89         def toNext(self):
 90             if self.__index < self.__length - 1:
 91                 self.__index += 1
 92 
 93         def reset(self):
 94             self.__index = 0
 95 
 96     class __Color:
 97         def __init__(self):
 98             self.__index = 0
 99             self.color = [(155, 255, 255), (255, 155, 255), (255, 255, 155), (155, 155, 255), (255, 155, 155), (155, 255, 155)]
100 
101         def getColor(self):
102             color = self.color[self.__index]
103             self.__index += 1
104             if self.__index >= len(self.color):
105                 self.__index = 0
106             return color
107 
108     def LoadImages(self, path, num=1_000_000_000):
109         images = []
110         index = 0
111         for root, dirs, files in os.walk(path):
112             for file in files:
113                 filePath = os.path.join(root, file)
114                 image = cv2.imread(filePath)
115                 image = cv2.resize(image, self.size)
116                 images.append(image)
117                 if index > num:
118                     return images
119         return images
120 
121     def __isInside(self, x, y):
122         if 0 < x < self.frameShape[1] and 0 < y < self.frameShape[0]:
123             return True
124         return False
125 
126     def __mouseCallBack(self, event, x, y, flags, param):
127         if not self.__isInside(x, y):
128             return
129         if event == cv2.EVENT_LBUTTONDOWN:
130             # self.__boxes[self.__nowLabel].center[0] = x
131             # self.__boxes[self.__nowLabel].center[1] = y
132             # self.__drawRect()
133             # self.__reShow()
134             if self.__LButtonDown:
135                 return
136             self.__record = [x, y]
137             self.__LButtonDown = True
138         elif event == cv2.EVENT_LBUTTONUP:
139             self.__LButtonDown = False
140         elif event == cv2.EVENT_RBUTTONDOWN:
141             for label in self.__label:
142                 self.__boxes[label].reset()
143             self.__labelOpt.reset()
144             self.__nowLabel = self.__labelOpt.getPresent()
145             self.__nextImage = True
146         elif event == cv2.EVENT_MOUSEMOVE:
147             if self.__LButtonDown:
148                 self.__boxes[self.__nowLabel].center[0] = (x+self.__record[0])//2
149                 self.__boxes[self.__nowLabel].center[1] = (y+self.__record[1])//2
150                 self.__boxes[self.__nowLabel].width = (x-self.__record[0])
151                 self.__boxes[self.__nowLabel].height = (y-self.__record[1])
152                 self.__drawRect()
153                 self.__reShow()
154         elif event == cv2.EVENT_MOUSEWHEEL:
155             if flags > 0:
156                 self.__boxes[self.__nowLabel].width //= 0.9
157                 self.__boxes[self.__nowLabel].height //= 0.9
158             elif flags < 0:
159                 self.__boxes[self.__nowLabel].width //= 1.1
160                 self.__boxes[self.__nowLabel].height //= 1.1
161             (self.__boxes[self.__nowLabel].width,
162              self.__boxes[self.__nowLabel].height) = noNagInt([
163                 self.__boxes[self.__nowLabel].width,
164                 self.__boxes[self.__nowLabel].height])
165 
166     def __reShow(self):
167         cv2.imshow(self.__frameWinName, self.__frameDraw)
168 
169     def __drawRect(self):
170         self.__frameDraw = copy.deepcopy(self.frame)
171         for label in self.__label:
172             pt1 = [self.__boxes[label].center[0] - self.__boxes[label].width // 2,
173                    self.__boxes[label].center[1] - self.__boxes[label].height // 2]
174             pt2 = [self.__boxes[label].center[0] + self.__boxes[label].width // 2,
175                    self.__boxes[label].center[1] + self.__boxes[label].height // 2]
176             pt1 = noNagInt(pt1)
177             pt1 = beRangeAble(pt1, self.frameShape)
178             pt2 = noNagInt(pt2)
179             pt2 = beRangeAble(pt2, self.frameShape)
180             # print(pt1, pt2)
181             color = self.__color[label]
182             pt1Offset = copy.deepcopy(pt1)
183             if pt1Offset[1] < 40:
184                 pt1Offset[1] = 40
185             self.__frameDraw = cv2.putText(self.__frameDraw, label, pt1Offset, self.__font, 1, color, 2)
186             self.__frameDraw = cv2.rectangle(self.__frameDraw, pt1, pt2, color, 1)
187 
188     def setFont(self, font):
189         self.__font = font
190 
191     def __write(self):
192         text = ""
193         for label in self.__label:
194             text += (label + " "
195                      + str(self.__boxes[label].center[0] / self.frameShape[1]) + " "
196                      + str(self.__boxes[label].center[1] / self.frameShape[0]) + " "
197                      + str(self.__boxes[label].width / self.frameShape[1]) + " "
198                      + str(self.__boxes[label].height / self.frameShape[0])) + "\n"
199         imgName = self.__root + self.__train + "/" + self.__presentFile + ".jpg"
200         valName = self.__root + self.__val + "/" + self.__presentFile + ".txt"
201         with open(valName, "w+") as file:
202             file.write(text)
203         cv2.imwrite(imgName, self.frame)
204 
205     def __processKey(self, key):
206         if key == ord('a'):
207             self.__boxes[self.__nowLabel].center[0] -= self.__step
208         elif key == ord('d'):
209             self.__boxes[self.__nowLabel].center[0] += self.__step
210         elif key == ord('w'):
211             self.__boxes[self.__nowLabel].center[1] -= self.__step
212         elif key == ord('s'):
213             self.__boxes[self.__nowLabel].center[1] += self.__step
214         elif key == ord('z'):
215             self.__boxes[self.__nowLabel].width += self.__step
216         elif key == ord('x'):
217             self.__boxes[self.__nowLabel].width -= self.__step
218         elif key == ord('f'):
219             self.__boxes[self.__nowLabel].height += self.__step
220         elif key == ord('v'):
221             self.__boxes[self.__nowLabel].height -= self.__step
222         elif key == ord('k'):
223             self.__write()
224             for label in self.__label:
225                 self.__boxes[label].reset()
226             self.__labelOpt.reset()
227             self.__nowLabel = self.__labelOpt.getPresent()
228             return True, False
229         elif key == ord("n"):
230             self.__labelOpt.toNext()
231             self.__nowLabel = self.__labelOpt.getPresent()
232         elif key == ord('q'):
233             return True, True
234         return False, False
235 
236     def view(self, path):
237         images = self.LoadImages(path)
238         count = 0
239         mark = False
240         for image in images:
241             if mark:
242                 break
243             if count < self.__presentFileInt:
244                 count += 1
245                 continue
246             # 导入图片
247             self.frame = image
248             self.frameShape = image.shape
249             print(self.frameShape)
250             self.__presentFile = str(self.__presentFileInt)
251             self.__presentFileInt += 1
252             count = self.__presentFileInt
253             # 操作
254             self.__drawRect()
255             self.__reShow()
256             # self.__label = input(f"Please input now Label{self.__presentFile}: ")
257             self.__nextImage = False
258             cv2.setMouseCallback(self.__frameWinName, self.__mouseCallBack)
259             while not self.__nextImage:
260                 key = cv2.waitKey(100) & 0xFF
261                 mark1, mark = self.__processKey(key)
262                 if mark1:
263                     break
264                 (self.__boxes[self.__nowLabel].width,
265                  self.__boxes[self.__nowLabel].height) = noNagInt([
266                     self.__boxes[self.__nowLabel].width,
267                     self.__boxes[self.__nowLabel].height])
268                 self.__drawRect()
269                 self.__reShow()
View Code

 

你要用的.py里面这样写:

 1 import cv2
 2 from LabelImage import MakeLabel
 3 
 4 yourPresentImageNumberWaitForProcess = 0
 5 yourImageSizeWhatYouWantToScale = (640, 480)
 6 yourLabelList = ["cat", "dog"]
 7 
 8 yourRoot = "path/to/your/root"
 9 yourTrain = "path/to/your/train"
10 yourVal = "path/to/your/val"
11 
12 yourObj = MakeLabel(winName="your windows name",
13                     presentImage=yourPresentImageNumberWaitForProcess,
14                     resize=yourImageSizeWhatYouWantToScale,
15                     label=yourLabelList,
16                     root=yourRoot,
17                     train=yourTrain,
18                     val=yourVal)
19 
20 pathOfOriginImage = "D:/path/to/your/images/which/wait/for/process"  # /process is a directory, pictures is /process/n_n.jpg
21 yourObj.setFont(cv2.FONT_HERSHEY_DUPLEX)  # 可写可不写
22 yourObj.view(pathOfOriginImage)
View Code

 

使用方法:

首先点击运行就进去了,然后鼠标左键开始画框,然后画完按"n"下一个标签(next),所有的标签都画完之后,按“k”保存,自动跳到下一张图片,

如果有废片也可以按鼠标右键跳过,

注意:要shift切换成 ‘英’ 文输入法才能按键盘

如果你画了100张(0-99)就去吃饭去了,回来的时候可以把

yourPresentImageNumberWaitForProcess = 0
presentImage=yourPresentImageNumberWaitForProcess
设置为100,这样就从第101张开始了

 

亲测有效:

 

但是有个缺点是每张图片都要包含所有类。。。今天没时间改了,改天有时间再来完善