def toLabelFile(self, image_path, samples): shapes = [] for sample in samples: shapes.append({ 'label': sample.label, 'line_color': None, 'fill_color': None, 'points': sample.points, 'shape_type': sample.shape_type, }) self.checkAborted() local_image_path = os.path.basename(image_path) image_data = LabelFile.load_image_file(image_path) label_file_name = os.path.splitext(image_path)[0] + LabelFile.suffix label_file = LabelFile() label_file.save( label_file_name, shapes, local_image_path, sample.image_size[0], sample.image_size[1], imageData=image_data, lineColor=None, fillColor=None, otherData=None, flags=None, )
def resize(self, size): """ Collabrate with crop, If crop is need before resize, using cropResize instead Arguemengs: size(tuple): W X H """ count = 0 for name in tqdm(self.names): jsoncontent = self.readJsonFile(f"{name}.json") # print("JsonContent", jsoncontent) newImage, jsoncontent = self._resize(name, size, jsoncontent) savedLoc = osp.join(self.dst_dir, f"{name}{self.image_suffix}") newImage.save(savedLoc) if jsoncontent is not None: imageData = LabelFile.load_image_file(savedLoc) imageData = base64.b64encode(imageData).decode("utf-8") jsoncontent["imageData"] = imageData with open(osp.join(self.dst_dir, f"{name}.json"), "w") as f: f.write(json.dumps(jsoncontent, indent=True)) count += 1 if self.debug: break print(f"Done for {count}")
def main(): parser = argparse.ArgumentParser() parser.add_argument('json_file') args = parser.parse_args() label_file = LabelFile(args.json_file) img = utils.img_data_to_arr(label_file.imageData) label_name_to_value = {'_background_': 0} for shape in sorted(label_file.shapes, key=lambda x: x['label']): label_name = shape['label'] if label_name in label_name_to_value: label_value = label_name_to_value[label_name] else: label_value = len(label_name_to_value) label_name_to_value[label_name] = label_value lbl, _ = utils.shapes_to_label(img.shape, label_file.shapes, label_name_to_value) label_names = [None] * (max(label_name_to_value.values()) + 1) for name, value in label_name_to_value.items(): label_names[value] = name lbl_viz = imgviz.label2rgb( label=lbl, img=imgviz.asgray(img), label_names=label_names, font_size=30, loc='rb', ) plt.subplot(121) plt.imshow(img) plt.subplot(122) plt.imshow(lbl_viz) plt.show()
def main(): parser = argparse.ArgumentParser() parser.add_argument( '--input', '-I', '-i', help='input json file of labelme generated (if it ends with .json it is ' 'recognized as file, else as directory)') args = parser.parse_args() config_from_args = args.__dict__ filename = config_from_args.pop('input') #print(filename) labelFile = LabelFile(filename) #print(f"len(labelFile.shapes) = {len(labelFile.shapes)}") i = 1 for s in labelFile.shapes: pointslen = len(s['points']) if pointslen < 10: print("{} line in {}".format(i, filename))
def saveLabels(self, filename): lf = LabelFile() def format_shape(s): return dict(label=str(s.label), line_color=s.line_color.getRgb() if s.line_color != self.lineColor else None, fill_color=s.fill_color.getRgb() if s.fill_color != self.fillColor else None, points=[(p.x(), p.y()) for p in s.points]) shapes = [format_shape(shape) for shape in self.labelList.shapes] flags = {} for i in range(self.flag_widget.count()): item = self.flag_widget.item(i) key = item.text() flag = item.checkState() == Qt.Checked flags[key] = flag try: imagePath = os.path.relpath( self.imagePath, os.path.dirname(filename)) imageData = self.imageData if self._config['store_data'] else None lf.save( filename=filename, shapes=shapes, imagePath=imagePath, imageData=imageData, lineColor=self.lineColor.getRgb(), fillColor=self.fillColor.getRgb(), otherData=self.otherData, flags=flags, ) self.labelFile = lf items = self.fileListWidget.findItems( self.imagePath, Qt.MatchExactly ) if len(items) > 0: if len(items) != 1: raise RuntimeError('There are duplicate files.') items[0].setCheckState(Qt.Checked) # disable allows next and previous image to proceed # self.filename = filename return True except LabelFileError as e: self.errorMessage('Error saving label data', '<b>%s</b>' % e) return False
def getLabelFilesFromDataFolder(self, data_folder): label_files = [] for root, dirs, files in os.walk(data_folder): for f in files: if LabelFile.is_label_file(f): full_path = os.path.normpath(os.path.join(root, f)) label_files.append(full_path) self.checkAborted() return label_files
def addFromLabelFile(self, label_file, root_folder): lf = LabelFile(label_file) image_size = (lf.imageHeight, lf.imageWidth) image_dir = os.path.dirname(os.path.relpath(label_file, root_folder)) for s in lf.shapes: image_path = os.path.normpath(os.path.join(image_dir, lf.imagePath)) self.addSample(image_path, image_size, s[0], s[1], s[4]) self.checkAborted()
def data2labelme(self): data_labelme = {} data_labelme["version"] = "4.2.10" data_labelme["flags"] = {} data_labelme["shapes"] = self.shapes data_labelme["imagePath"] = os.path.basename(self.file_name) #data_labelme["imageData"] = None data_labelme["imageData"] = base64.b64encode( LabelFile.load_image_file(self.file_name)).decode('utf-8') return data_labelme
def main(): parser = argparse.ArgumentParser() parser.add_argument( '--input', '-I', '-i', help='input json file of labelme generated (if it ends with .json it is ' 'recognized as file, else as directory)') args = parser.parse_args() config_from_args = args.__dict__ filename = config_from_args.pop('input') #print(filename) labelFile = LabelFile(filename) #print(f"len(labelFile.shapes) = {len(labelFile.shapes)}") sameShape = {} plen = [] for s in labelFile.shapes: pointslen = len(s['points']) plen.append(pointslen) for i in range(len(plen) - 1, -1, -1): for j in range(i - 1, -1, -1): if plen[i] == plen[j]: #print(f"{j} and {i} len is the same {plen[i]}") shapei = labelFile.shapes[i] shapej = labelFile.shapes[j] kstep = 0 for k in range(0, plen[i]): dx = math.fabs( float(shapei['points'][k][0]) - float(shapej['points'][k][0])) dy = math.fabs( float(shapei['points'][k][1]) - float(shapej['points'][k][1])) if dx > 2.0 or dy > 2.0: break kstep = kstep + 1 if kstep == plen[i]: #print(f"{j} and {i} shape is the same") sameShape[j] = i print(sameShape)
def saveLabels(self, filename): lf = LabelFile() def format_shape(s): return dict(label=str(s.label), line_color=s.line_color.getRgb() if s.line_color != self.lineColor else None, fill_color=s.fill_color.getRgb() if s.fill_color != self.fillColor else None, points=[(p.x(), p.y()) for p in s.points]) shapes = [format_shape(shape) for shape in self.labelList.shapes] flags = {} for i in range(self.flag_widget.count()): item = self.flag_widget.item(i) key = item.text() flag = item.checkState() == Qt.Checked flags[key] = flag try: imagePath = os.path.relpath( self.imagePath, os.path.dirname(filename)) imageData = self.imageData if self._config['store_data'] else None lf.save( filename=filename, shapes=shapes, imagePath=imagePath, imageData=imageData, lineColor=self.lineColor.getRgb(), fillColor=self.fillColor.getRgb(), otherData=self.otherData, flags=flags, ) self.labelFile = lf # disable allows next and previous image to proceed # self.filename = filename return True except LabelFileError as e: self.errorMessage('Error saving label data', '<b>%s</b>' % e) return False
def rotate(self, degs, center=None, boarderValue=(0, 0, 0), scale=1.0, **kwargs): """ Arguments: degs: list or iterable (float) center(tuple | None): if the all the image size are the same, it could be applied when rotating, if image size differes from each other, leave it unchanged to let program choose the center of the image """ count = 0 if kwargs.get("start"): print("[Warning] api changed, using `degs` instead") for name in tqdm(self.names): orijsoncontent = self.readJsonFile(f"{name}.json") if orijsoncontent is None: continue # print("JsonContent", jsoncontent) rc = 0 for deg in degs: jsoncontent = copy.deepcopy(orijsoncontent) newImage = self._rotate(name, jsoncontent, deg, center, boarderValue, scale=scale) newName = f"{name}-r{deg}-s{scale}-{rc:04}" savedLoc = osp.join(self.dst_dir, f"{newName}{self.image_suffix}") rc += 1 newImage.save(savedLoc) if jsoncontent is not None: imageData = LabelFile.load_image_file(savedLoc) imageData = base64.b64encode(imageData).decode("utf-8") jsoncontent["imageData"] = imageData with open(osp.join(self.dst_dir, f"{newName}.json"), "w") as f: f.write(json.dumps(jsoncontent, indent=True)) count += 1 if self.debug: break if self.debug: break print(f"Done Rotation for {count}")
def make_label_visualize_image(self, json_file): label_file = LabelFile(json_file) img = utils.img_data_to_arr(label_file.imageData) label_name_to_value = {"_background_": 0} for shape in sorted(label_file.shapes, key=lambda x: x["label"]): label_name = shape["label"] if label_name in label_name_to_value: label_value = label_name_to_value[label_name] else: label_value = len(label_name_to_value) label_name_to_value[label_name] = label_value lbl, _ = utils.shapes_to_label( img.shape, label_file.shapes, label_name_to_value ) label_names = [None] * (max(label_name_to_value.values()) + 1) for name, value in label_name_to_value.items(): label_names[value] = name lbl_viz = imgviz.label2rgb( label=lbl, img=imgviz.asgray(img), label_names=label_names, font_size=30, loc="rb", ) return lbl_viz fig = plt.figure() ax1 = fig.add_subplot(111) ax1.imshow(img) ax2 = fig.add_subplot(111) ax2.imshow(lbl_viz) fig.canvas.draw() data = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='') data = data.reshape(fig.canvas.get_width_height()[::-1] + (3,)) # plt.subplot(121) # plt.imshow(img) # plt.subplot(122) # plt.imshow(lbl_viz) # plt.show() # # plt.draw() return data
def importDirImages(self, dirpath, load=True): if not self.mayContinue() or not dirpath: return self.lastOpenDir = dirpath self.filename = None self.fileListWidget.clear() for filename in self.scanAllImages(dirpath): label_file = os.path.splitext(filename)[0] + '.json' item = QtWidgets.QListWidgetItem(filename) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) if QtCore.QFile.exists(label_file) and \ LabelFile.isLabelFile(label_file): item.setCheckState(Qt.Checked) else: item.setCheckState(Qt.Unchecked) self.fileListWidget.addItem(item) self.openNextImg(load=load)
def importDirImages(self, dirpath, load=True): if not self.mayContinue() or not dirpath: return self.lastOpenDir = dirpath self.filename = None self.fileListWidget.clear() for filename in self.scanAllImages(dirpath): label_file = os.path.splitext(filename)[0] + '.json' item = QtWidgets.QListWidgetItem(filename) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) if QtCore.QFile.exists(label_file) and \ LabelFile.isLabelFile(label_file): item.setCheckState(Qt.Checked) else: item.setCheckState(Qt.Unchecked) self.fileListWidget.addItem(item) self.openNextImg(load=load)
def shift(self, maxpixel=10, step=10, direction=(1, 1), boarderValue=(0, 0, 0)): """ pixel shift will be 10, 5 if max is 10 and step is 5 direction is the vector that shift will be, for example (1, 1) will shift the image to the up-right corner for pixel """ count = 0 assert direction[0] != 0 or direction[1] != 0 for name in tqdm(self.names): orijsoncontent = self.readJsonFile(f"{name}.json") if orijsoncontent is None: continue # print("JsonContent", jsoncontent) rc = 0 for pixel in range(maxpixel, 0, -step): if pixel <= 0: break xy = (direction[0] * pixel, direction[1] * pixel) jsoncontent = copy.deepcopy(orijsoncontent) newImage = self._shift(name, jsoncontent, xy, boarderValue) newName = f"{name}-t{direction[0]}-{direction[1]}-{pixel}-{rc:04}" savedLoc = osp.join(self.dst_dir, f"{newName}{self.image_suffix}") rc += 1 newImage.save(savedLoc) if jsoncontent is not None: imageData = LabelFile.load_image_file(savedLoc) imageData = base64.b64encode(imageData).decode("utf-8") jsoncontent["imageData"] = imageData with open(osp.join(self.dst_dir, f"{newName}.json"), "w") as f: f.write(json.dumps(jsoncontent, indent=True)) count += 1 if self.debug: break if self.debug: break print(f"Done Shift for {count}")
def main(): parser = argparse.ArgumentParser() parser.add_argument( '--input', '-I', '-i', help='input json file of labelme generated (if it ends with .json it is ' 'recognized as file, else as directory)' ) args = parser.parse_args() config_from_args = args.__dict__ filename = config_from_args.pop('input') #print(filename) labelFile = LabelFile(filename) #print(f"len(labelFile.shapes) = {len(labelFile.shapes)}") fshape = labelFile.shapes[0] newPoints = [] newPoints.append(fshape['points'][0]) pointslen = len(fshape['points']) keepPointIndex = 0; for i in range(1, pointslen): dx = math.fabs(float(fshape['points'][i][0]) - float(fshape['points'][keepPointIndex][0])) dy = math.fabs(float(fshape['points'][i][1]) - float(fshape['points'][keepPointIndex][1])) if dx > 2.0 or dy > 2.0: keepPointIndex = i newPoints.append(fshape['points'][keepPointIndex]) print(newPoints)
def run(self): logger.debug('Start import from directory') try: import ptvsd ptvsd.debug_this_thread() except: pass data = Map(self.data) num_images = len(data.images) pattern = data.pattern output_dir = data.output_dir filters = data.filters filter_label_func = self.acceptAll if 'label' in filters and not filters['label'] == StatisticsModel.STATISTICS_FILTER_ALL: filter_label_func = self.acceptLabel image_count = 0 all_shapes = [] items = [] self.checkAborted() for i, filename in enumerate(data.images): self.thread.update.emit(None, i, num_images) self.checkAborted() # Search pattern if pattern and pattern.lower() not in filename.lower(): # re.search(pattern, filename, re.IGNORECASE) == None: continue label_file = os.path.splitext(filename)[0] + '.json' if output_dir: label_file_without_path = os.path.basename(label_file) label_file = os.path.normpath(os.path.join(output_dir, label_file_without_path)) # ListItem item = QtWidgets.QListWidgetItem(filename) item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable) item.setCheckState(Qt.Unchecked) self.checkAborted() shapes = [] has_labels = False labels_for_image = set([]) label_file_exists = os.path.isfile(label_file) # Labels if label_file_exists: labelFile = LabelFile(label_file) for label, points, line_color, fill_color, shape_type, flags in labelFile.shapes: if filter_label_func(label): has_labels = True shape = Shape(label=label, shape_type=shape_type) shapes.append(shape) labels_for_image.add(label) # Filters if 'label' in filters and not filters['label'] == StatisticsModel.STATISTICS_FILTER_ALL: if not filters['label'] in labels_for_image: continue if 'has_label' in filters: if filters['has_label'] == StatisticsModel.STATISTICS_FILTER_LABELED and not has_labels: continue if filters['has_label'] == StatisticsModel.STATISTICS_FILTER_UNLABELED and has_labels: continue image_count += 1 items.append(item) if has_labels: item.setCheckState(Qt.Checked) all_shapes.append(shapes) if image_count % data['update_interval'] == 0: self.thread.data.emit({ 'items': items, 'num_images': image_count, 'all_shapes': all_shapes, }) image_count = 0 all_shapes = [] items = [] self.checkAborted() self.thread.data.emit({ 'num_images': image_count, 'all_shapes': all_shapes, 'items': items, })
def test_data_to_sever(): ''' Check that the data that is sent from the labeling tool is correct when it is sent to the server This test assumes that a development server is running and is specified in the config file ''' config = labelme.config.get_config( config_file="labelme/config/config_unittests.yaml") with tempfile.TemporaryDirectory() as tmpdir: # Attempt to login to the server and download 3 images to label try: ih = ImageHandler(config["server"], config["port"], config["username"], config["password"], tmpdir) ih.get_new_hits(max_number_hits=4, max_images_downloaded=3) except: EnvironmentError( "Could not connect to server, is it running at the location specified in the config_unittests.yaml file?" ) # Go through and get the file locations and store basic data about the images labels_to_test = [ { "top_left_x": 671.9, "top_left_y": 106.9, "top_right_x": 1186.7, "top_right_y": 138.3, "bottom_left_x": 703.5, "bottom_left_y": 1101.7, "bottom_right_x": 1211.9, "bottom_right_y": 1122.2, "image_id": None, "hit_id": None, "results": { "slope_left": 31.481013, "slope_right": 39.043651, "slope": 35.262332, "intercept_left": -21045.192405, "intercept_right": -46194.800397, "intercept": -32653.94157, "intercept_percent": -27.211617975, "center_x": 943.044318, "center_x_percent": 0.5894026988, "width_horizontal": 510.961816, "width_horizontal_percent": 0.319351135, "width_normal": 510.7564755382, "width_normal_percent": 0.3192227972, } }, { "top_left_x": 694.0, "top_left_y": 94.3, "top_right_x": 1200.9, "top_right_y": 108.4, "bottom_left_x": 679.9, "bottom_left_y": 1139.5, "bottom_right_x": 1186.7, "bottom_right_y": 1136.4, "image_id": None, "hit_id": None, "results": { "slope_left": -74.127660, "slope_right": -72.394366, "slope": -73.261013, "intercept_left": 51538.895745, "intercept_right": 87046.794366, "intercept": 69512.510279, # note this is inverted so need to add image_height to the inventor calc "intercept_percent": 57.9270918992, "center_x": 940.643701, "center_x_percent": 0.5879023131, "width_horizontal": 506.931431, "width_horizontal_percent": 0.3168321444, "width_normal": 506.8842124439, "width_normal_percent": 0.3168026328, } }, { "top_left_x": 690.9, "top_left_y": 78.5, "top_right_x": 1208.8, "top_right_y": 72.2, "bottom_left_x": 734.9, "bottom_left_y": 1167.9, "bottom_right_x": 1243.4, "bottom_right_y": 1136.4, "image_id": None, "hit_id": None, "results": { "slope_left": 24.759091, "slope_right": 30.757225, "slope": 27.758158, "intercept_left": -17027.555909, "intercept_right": -37107.134104, "intercept": -26296.5888881, "intercept_percent": -21.9138240734, "center_x": 968.961583, "center_x_percent": 0.6056009894, "width_horizontal": 513.997225, "width_horizontal_percent": 0.3212482656, "width_normal": 513.6640081061, "width_normal_percent": 0.3210400051, } } ] images = {} for root, _, files in os.walk(tmpdir): for fname in files: if len(images) >= 3: # only want first 3 images break if fname[-5:] == ".jpeg": images[fname[:-5]] = { 'root': root, 'path': os.path.join(root, fname), 'hit_id': root.split(os.sep)[-1].split("_")[-1], 'image_id': fname[:-5], 'label': labels_to_test[len(images)], 'solution': labels_to_test[len(images)]['results'] } assert len( images) == 3, "Did not get 3 images to label from the server!" # Generate labels for each image, save the path to the label in the images dict for image_id in images: image = images[image_id] label = image['label'] result_fname = os.path.join(image["root"], "{}.json".format(image["image_id"])) images[image_id]["result_fname"] = result_fname result = LabelFile() result.save( filename=result_fname, shapes=[{ "label": "edge", "line_color": None, "fill_color": None, "points": [[label["top_left_x"], label["top_left_y"]], [label["top_right_x"], label["top_right_y"]], [label["bottom_right_x"], label["bottom_right_y"]], [label["bottom_left_x"], label["bottom_left_y"]]], "shape_type": "polygon", "flags": {} }], imagePath=image["path"], imageHeight=1200, imageWidth=1600) # upload the result to the server and verfiy ImageHandler._convert_labelme_to_edges() for image_id in images: image = images[image_id] label = image['label'] result_fname = images[image_id]["result_fname"] response = ih.submit_label_file(result_fname) images[image_id]['railedge_id'] = response[ "server_response_created_object_id"] # Verify the updated saved data is correct. # ImageHandler converts the locations in the shape key to the 4 locations needed. Verify it did it correctly # This tests the ImageHandler._convert_labelme_to_edges function for vert in ['top', 'bottom']: for lat in ['left', 'right']: for coord in ['x', 'y']: floatsClose( response["{}_{}_{}".format(vert, lat, coord)], label["{}_{}_{}".format(vert, lat, coord)], msg="Occured in {}_{}_{}".format(vert, lat, coord)) # download the results from the server and verify the result is correct for image_id in images: image = images[image_id] result_correct = image['label']['results'] railedge_id = image['railedge_id'] response = ih.client.get("{}?id={}".format(ih.url_api_edge, railedge_id)) response_json = response.json() assert len( response_json ) == 1, "Got {} railedge labels, should only get 1!".format( len(response_json)) result = response_json[0] for key in result_correct: floatsClose(result[key], result_correct[key], msg="key: {}".format(key))
def loadFile(self, filename=None): """Load the specified file, or the last opened file if None.""" # changing fileListWidget loads file if (filename in self.imageList and self.fileListWidget.currentRow() != self.imageList.index(filename)): self.fileListWidget.setCurrentRow(self.imageList.index(filename)) return self.resetState() self.canvas.setEnabled(False) if filename is None: filename = self.settings.value('filename', '') filename = str(filename) if not QtCore.QFile.exists(filename): self.errorMessage('Error opening file', 'No such file: <b>%s</b>' % filename) return False # assumes same name, but json extension self.status("Loading %s..." % os.path.basename(str(filename))) label_file = os.path.splitext(filename)[0] + '.json' if QtCore.QFile.exists(label_file) and \ LabelFile.isLabelFile(label_file): try: self.labelFile = LabelFile(label_file) # FIXME: PyQt4 installed via Anaconda fails to load JPEG # and JSON encoded images. # https://github.com/ContinuumIO/anaconda-issues/issues/131 if QtGui.QImage.fromData(self.labelFile.imageData).isNull(): raise LabelFileError( 'Failed loading image data from label file.\n' 'Maybe this is a known issue of PyQt4 built on' ' Anaconda, and may be fixed by installing PyQt5.') except LabelFileError as e: self.errorMessage( 'Error opening file', "<p><b>%s</b></p>" "<p>Make sure <i>%s</i> is a valid label file." % (e, label_file)) self.status("Error reading %s" % label_file) return False self.imageData = self.labelFile.imageData self.imagePath = os.path.join(os.path.dirname(label_file), self.labelFile.imagePath) self.lineColor = QtGui.QColor(*self.labelFile.lineColor) self.fillColor = QtGui.QColor(*self.labelFile.fillColor) self.otherData = self.labelFile.otherData else: # Load image: # read data first and store for saving into label file. self.imageData = read(filename, None) if self.imageData is not None: # the filename is image not JSON self.imagePath = filename self.labelFile = None image = QtGui.QImage.fromData(self.imageData) if image.isNull(): formats = [ '*.{}'.format(fmt.data().decode()) for fmt in QtGui.QImageReader.supportedImageFormats() ] self.errorMessage( 'Error opening file', '<p>Make sure <i>{0}</i> is a valid image file.<br/>' 'Supported image formats: {1}</p>'.format( filename, ','.join(formats))) self.status("Error reading %s" % filename) return False self.image = image self.filename = filename if self._config['keep_prev']: prev_shapes = self.canvas.shapes self.canvas.loadPixmap(QtGui.QPixmap.fromImage(image)) if self._config['flags']: self.loadFlags({k: False for k in self._config['flags']}) if self._config['keep_prev']: self.loadShapes(prev_shapes) if self.labelFile: self.loadLabels(self.labelFile.shapes) if self.labelFile.flags is not None: self.loadFlags(self.labelFile.flags) self.setClean() self.canvas.setEnabled(True) self.adjustScale(initial=True) self.paintCanvas() self.addRecentFile(self.filename) self.toggleActions(True) self.status("Loaded %s" % os.path.basename(str(filename))) return True
def loadFile(self, filename=None): """Load the specified file, or the last opened file if None.""" # changing fileListWidget loads file if (filename in self.imageList and self.fileListWidget.currentRow() != self.imageList.index(filename)): self.fileListWidget.setCurrentRow(self.imageList.index(filename)) return self.resetState() self.canvas.setEnabled(False) if filename is None: filename = self.settings.value('filename', '') filename = str(filename) if not QtCore.QFile.exists(filename): self.errorMessage( 'Error opening file', 'No such file: <b>%s</b>' % filename) return False # assumes same name, but json extension self.status("Loading %s..." % os.path.basename(str(filename))) label_file = os.path.splitext(filename)[0] + '.json' if QtCore.QFile.exists(label_file) and \ LabelFile.isLabelFile(label_file): try: self.labelFile = LabelFile(label_file) # FIXME: PyQt4 installed via Anaconda fails to load JPEG # and JSON encoded images. # https://github.com/ContinuumIO/anaconda-issues/issues/131 if QtGui.QImage.fromData(self.labelFile.imageData).isNull(): raise LabelFileError( 'Failed loading image data from label file.\n' 'Maybe this is a known issue of PyQt4 built on' ' Anaconda, and may be fixed by installing PyQt5.') except LabelFileError as e: self.errorMessage( 'Error opening file', "<p><b>%s</b></p>" "<p>Make sure <i>%s</i> is a valid label file." % (e, label_file)) self.status("Error reading %s" % label_file) return False self.imageData = self.labelFile.imageData self.imagePath = os.path.join(os.path.dirname(label_file), self.labelFile.imagePath) self.lineColor = QtGui.QColor(*self.labelFile.lineColor) self.fillColor = QtGui.QColor(*self.labelFile.fillColor) self.otherData = self.labelFile.otherData else: # Load image: # read data first and store for saving into label file. self.imageData = read(filename, None) if self.imageData is not None: # the filename is image not JSON self.imagePath = filename self.labelFile = None image = QtGui.QImage.fromData(self.imageData) if image.isNull(): formats = ['*.{}'.format(fmt.data().decode()) for fmt in QtGui.QImageReader.supportedImageFormats()] self.errorMessage( 'Error opening file', '<p>Make sure <i>{0}</i> is a valid image file.<br/>' 'Supported image formats: {1}</p>' .format(filename, ','.join(formats))) self.status("Error reading %s" % filename) return False self.image = image self.filename = filename if self._config['keep_prev']: prev_shapes = self.canvas.shapes self.canvas.loadPixmap(QtGui.QPixmap.fromImage(image)) if self._config['flags']: self.loadFlags({k: False for k in self._config['flags']}) if self._config['keep_prev']: self.loadShapes(prev_shapes) if self.labelFile: self.loadLabels(self.labelFile.shapes) if self.labelFile.flags is not None: self.loadFlags(self.labelFile.flags) self.setClean() self.canvas.setEnabled(True) self.adjustScale(initial=True) self.paintCanvas() self.addRecentFile(self.filename) self.toggleActions(True) self.status("Loaded %s" % os.path.basename(str(filename))) return True