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()
你要用的.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)
使用方法:
首先点击运行就进去了,然后鼠标左键开始画框,然后画完按"n"下一个标签(next),所有的标签都画完之后,按“k”保存,自动跳到下一张图片,
如果有废片也可以按鼠标右键跳过,
注意:要shift切换成 ‘英’ 文输入法才能按键盘
如果你画了100张(0-99)就去吃饭去了,回来的时候可以把
yourPresentImageNumberWaitForProcess = 0
presentImage=yourPresentImageNumberWaitForProcess
设置为100,这样就从第101张开始了
亲测有效:
但是有个缺点是每张图片都要包含所有类。。。今天没时间改了,改天有时间再来完善