def generate_negative_regions(image_dir, window_dims, modifiers_config=None): print 'generate_negative_regions:' image_list = utils.list_images_in_directory(image_dir) if len(image_list) == 0: raise ValueError('The given directory \'{}\' contains no images.'.format(image_dir)) print ' Found {} images.'.format(len(image_list)) # Create the modifier generator: # Note: Simply generate null modifiers if no modifier config is passed. modifier_generator = itertools.repeat(utils.RegionModifiers()) if modifiers_config: modifier_generator = utils.RegionModifiers.random_generator_from_config_dict(modifiers_config) min_w, min_h = window_dims min_size_length = min(min_w, min_h) / 2.0 while True: random.shuffle(image_list) for img_path in image_list: imsize = utils.get_image_dimensions(img_path) # Reject small images: w, h = imsize if w < min_w or h < min_h: continue # Generate a number of regions per image: for i in xrange(10): rect = gm.PixelRectangle.random_with_same_aspect(window_dims, imsize, min_size_length) mod = modifier_generator.next() reg = utils.ImageRegion(rect, img_path, mod) yield reg
def choose_positive_samples(image_dir, sample_size, bbinfo_dir): filtered_image_list = utils.list_images_in_directory(image_dir) # Filter out images without bounding boxes: global_info = training.loadGlobalInfo(bbinfo_dir) bbox_filter = lambda img_path: os.path.split(img_path)[1] in global_info filtered_image_list = filter(bbox_filter, filtered_image_list) # Extract image regions: img_regions = [] for img_path in filtered_image_list: key = os.path.split(img_path)[1] rects = utils.rectangles_from_cache_string(global_info[key]) for rect in rects: region = utils.ImageRegion(rect, img_path) img_regions.append(region) # Truncate region list to sample the correct number of images: if sample_size is None: random.shuffle(img_regions) else: img_regions = random.sample(img_regions, min(sample_size, len(img_regions))) if len(img_regions) < sample_size: raise ValueError( "Requested {} positive samples, but only {} could be found in '{}'!".format( sample_size, len(img_regions), image_dir ) ) return img_regions
def generate_negative_regions_with_exclusions(bak_img_dir, exl_info_map, window_dims, modifiers_config=None): print 'generate_negative_regions_with_exclusions:' all_images = utils.list_images_in_directory(bak_img_dir) if len(all_images) == 0: raise ValueError('The given directory \'{}\' contains no images.'.format(bak_img_dir)) print ' Found {} images.'.format(len(all_images)) all_images = [img_path for img_path in all_images if not utils.info_entry_for_image(exl_info_map, img_path) is None] print ' Found {} images with exclusion info.'.format(len(all_images)) if len(all_images) == 0: raise ValueError('The given directory \'{}\' contains no images with exclusion info.'.format(bak_img_dir)) image_list = all_images random.shuffle(image_list) modifier_generator = itertools.repeat(utils.RegionModifiers()) if modifiers_config: modifier_generator = utils.RegionModifiers.random_generator_from_config_dict(modifiers_config) while True: for img_path in image_list: imsize = utils.get_image_dimensions(img_path) for reg in generate_negative_regions_in_image_with_exclusions(img_path, exl_info_map, window_dims): mod = modifier_generator.next() # Assign a random modifier, and yield the region: new_reg = utils.ImageRegion(reg.rect, reg.fname, mod) yield new_reg # Shuffle the image list: random.shuffle(image_list)
def choose_positive_samples(image_dir, sample_size, bbinfo_dir): filtered_image_list = utils.list_images_in_directory(image_dir) # Filter out images without bounding boxes: global_info = training.loadGlobalInfo(bbinfo_dir) bbox_filter = lambda img_path: os.path.split(img_path)[1] in global_info filtered_image_list = filter(bbox_filter, filtered_image_list) # Extract image regions: img_regions = [] for img_path in filtered_image_list: key = os.path.split(img_path)[1] rects = utils.rectangles_from_cache_string(global_info[key]) for rect in rects: region = utils.ImageRegion(rect, img_path) img_regions.append(region) # Truncate region list to sample the correct number of images: if sample_size is None: random.shuffle(img_regions) else: img_regions = random.sample(img_regions, min(sample_size, len(img_regions))) if len(img_regions) < sample_size: raise ValueError( 'Requested {} positive samples, but only {} could be found in \'{}\'!' .format(sample_size, len(img_regions), image_dir)) return img_regions
def sampleTrainingImages(image_dir, synsets, sample_size, require_bboxes=False, bbinfo_dir=None): image_list = utils.list_images_in_directory(image_dir) # regexString = '.*({})_.*\.jpg'.format('|'.join(synsets)) # regexString = 'n?({})(_.*)?\.(jpg|png)'.format('|'.join(synsets)) regexString = '(.*/)?({})(_.*)?\.(jpg|png)'.format('|'.join(synsets)) synsetProg = re.compile(regexString) # Filter image file lists to match sysnet specifications: filtered_image_list = filter(lambda x: synsetProg.match(x), image_list) # print regexString # if len(regexString) > 100: # # print image_list # print filtered_image_list # If bounding boxes are required, filter out images without bounding boxes: if require_bboxes: global_info = utils.load_opencv_bounding_box_info_directory(bbinfo_dir, suffix='bbinfo') # global_info = loadGlobalInfo(bbinfo_dir) bbox_filter = lambda img_path: os.path.split(img_path)[1] in global_info filtered_image_list = filter(bbox_filter, filtered_image_list) print len(filtered_image_list) # Truncate file lists to sample the correct number of images: image_sample = filtered_image_list if not sample_size is None: image_sample = random.sample(filtered_image_list, min(sample_size, len(filtered_image_list))) return image_sample
def generate_positive_regions(image_dir, bbinfo_dir, modifiers_config=None, window_dims=None, min_size=(48,48)): print 'generate_positive_regions:' all_images = utils.list_images_in_directory(image_dir) # Create the modifier generator: # Note: Simply generate null modifiers if no modifier config is passed. modifier_generator = itertools.repeat(utils.RegionModifiers()) if modifiers_config: modifier_generator = utils.RegionModifiers.random_generator_from_config_dict(modifiers_config) # Filter out images without bounding boxes: bbinfo_map = utils.load_opencv_bounding_box_info_directory(bbinfo_dir, suffix='bbinfo') source_images = [img_path for img_path in all_images if not utils.info_entry_for_image(bbinfo_map, img_path) is None] # Extract image regions: source_regions = [] for img_path in source_images: rects = utils.info_entry_for_image(bbinfo_map, img_path) for rect in rects: # Reject small samples: if rect.w < float(min_size[0]) or rect.h < float(min_size[1]): continue region = utils.ImageRegion(rect, img_path) source_regions.append(region) print 'Found {} source regions.'.format(len(source_regions)) # Generate an infinite list of samples: while True: # Randomise the order of source images: # Note: Don't randomise if no modifiers are used. if modifiers_config: random.shuffle(source_regions) # For each source region: for reg in source_regions: mod = modifier_generator.next() # Enlarge to correct aspect ratio: new_rect = reg.rect if window_dims: aspect = window_dims[0] / float(window_dims[1]) new_rect = new_rect.enlarge_to_aspect(aspect) imsize = utils.get_image_dimensions(reg.fname) if not new_rect.lies_within_frame(imsize): # print 'bad', new_rect continue # else: # print new_rect # Assign a random modifier, and yield the region: new_reg = utils.ImageRegion(new_rect, reg.fname, mod) yield new_reg # If we're not using modifiers, only use each region once: if not modifiers_config: break
def runClassifier(classifier_yaml, output_dir): traincascade_data_dir = '{}/data'.format(output_dir) classifier_xml = '{}/cascade.xml'.format(traincascade_data_dir) if not os.path.isfile(classifier_xml): print 'ERROR: Classifier does not exist:', classifier_xml sys.exit(1) classifier = cv2.CascadeClassifier(classifier_xml) for test_dir in classifier_yaml['testing']['directories']: test_source_name = test_dir.strip('/').split('/')[-1] results_dir = '{}/{}_results'.format(output_dir, test_source_name) detections_fname = '{}/{}_detections.dat'.format( output_dir, test_source_name) img_list = utils.list_images_in_directory(test_dir) random.shuffle(img_list) for img_path in img_list: img = cv2.imread(img_path) while img.shape[0] > 1024: print 'resize:', img_path, img.shape img = cv2.resize(img, dsize=None, fx=0.5, fy=0.5) # # Check whether the image is upside-down: # if checkImageOrientation(img_path): # print 'Flipped!' # img = cv2.flip(img, -1) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) minSize = (img.shape[0] / 50, img.shape[1] / 50) cars = classifier.detectMultiScale( image=gray, # scaleFactor=1.05, scaleFactor=1.01, minNeighbors=4, minSize=minSize, ) print img_path, len(cars) if len(cars) > 0: for (x, y, w, h) in cars: # img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) lw = max(2, img.shape[0] / 100) cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), lw) # roi_gray = gray[y:y+h, x:x+w] # roi_color = img[y:y+h, x:x+w] # img = cv2.resize(img, dsize=None, fx=0.1, fy=0.1) # cv2.namedWindow("img", cv2.WINDOW_NORMAL) # cv2.resizeWindow('img', 500, 500) cv2.imshow('img', img) # cv2.imshow('img',img) cv2.waitKey(0) cv2.destroyAllWindows()
def runClassifier(classifier_yaml, output_dir): traincascade_data_dir = '{}/data'.format(output_dir) classifier_xml = '{}/cascade.xml'.format(traincascade_data_dir) if not os.path.isfile(classifier_xml): print 'ERROR: Classifier does not exist:', classifier_xml sys.exit(1) classifier = cv2.CascadeClassifier(classifier_xml) for test_dir in classifier_yaml['testing']['directories']: test_source_name = test_dir.strip('/').split('/')[-1] results_dir = '{}/{}_results'.format(output_dir, test_source_name) detections_fname = '{}/{}_detections.dat'.format(output_dir, test_source_name) img_list = utils.list_images_in_directory(test_dir) random.shuffle(img_list) for img_path in img_list: img = cv2.imread(img_path) while img.shape[0] > 1024: print 'resize:', img_path, img.shape img = cv2.resize(img, dsize=None, fx=0.5, fy=0.5) # # Check whether the image is upside-down: # if checkImageOrientation(img_path): # print 'Flipped!' # img = cv2.flip(img, -1) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) minSize = (img.shape[0] / 50, img.shape[1] / 50) cars = classifier.detectMultiScale( image=gray, # scaleFactor=1.05, scaleFactor=1.01, minNeighbors=4, minSize=minSize, ) print img_path, len(cars) if len(cars) > 0: for (x,y,w,h) in cars: # img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) lw = max(2, img.shape[0] / 100) cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),lw) # roi_gray = gray[y:y+h, x:x+w] # roi_color = img[y:y+h, x:x+w] # img = cv2.resize(img, dsize=None, fx=0.1, fy=0.1) # cv2.namedWindow("img", cv2.WINDOW_NORMAL) # cv2.resizeWindow('img', 500, 500) cv2.imshow('img', img) # cv2.imshow('img',img) cv2.waitKey(0) cv2.destroyAllWindows()
def generate_hard_negative_regions(bak_img_dir, classifier_dir, window_dims): all_images = utils.list_images_in_directory(bak_img_dir) w, h = window_dims window_aspect = w / float(h) with ObjectDetector(classifier_dir) as detector: while True: random.shuffle(all_images) for img_path in all_images: # Detect objects: img = cv2.imread(img_path) img_h, img_w = img.shape[:2] img_dims = (img_w, img_h) opencv_rects, scaled_img_dims = detector.detect_objects_in_image( img, resize=False, return_detection_img=False, progress=False ) pixel_rects = map(gm.PixelRectangle.from_opencv_bbox, opencv_rects) # Find rectangles in original image dimensions: pixel_rects = [rect.scale_image(scaled_img_dims, img_dims) for rect in pixel_rects] # Enlarge to window_dims: pixel_rects = [rect.enlarge_to_aspect(window_aspect) for rect in pixel_rects] # Ensure new rectangles are located within their images: pixel_rects = [rect.translated([0,0], img_dims) for rect in pixel_rects] pixel_rects = [rect for rect in pixel_rects if rect.lies_within_frame(img_dims)] # Convert to image regions: image_regions = [utils.ImageRegion(rect, img_path) for rect in pixel_rects] # Yield results: for reg in image_regions: yield reg
def sampleTrainingImages(image_dir, synsets, sample_size, require_bboxes=False, bbinfo_dir=None): image_list = utils.list_images_in_directory(image_dir) # regexString = '.*({})_.*\.jpg'.format('|'.join(synsets)) # regexString = 'n?({})(_.*)?\.(jpg|png)'.format('|'.join(synsets)) regexString = '(.*/)?({})(_.*)?\.(jpg|png)'.format('|'.join(synsets)) synsetProg = re.compile(regexString) # Filter image file lists to match sysnet specifications: filtered_image_list = filter(lambda x: synsetProg.match(x), image_list) # print regexString # if len(regexString) > 100: # # print image_list # print filtered_image_list # If bounding boxes are required, filter out images without bounding boxes: if require_bboxes: global_info = utils.load_opencv_bounding_box_info_directory( bbinfo_dir, suffix='bbinfo') # global_info = loadGlobalInfo(bbinfo_dir) bbox_filter = lambda img_path: os.path.split(img_path)[1 ] in global_info filtered_image_list = filter(bbox_filter, filtered_image_list) print len(filtered_image_list) # Truncate file lists to sample the correct number of images: image_sample = filtered_image_list if not sample_size is None: image_sample = random.sample( filtered_image_list, min(sample_size, len(filtered_image_list))) return image_sample
def annotate_directory(self, img_dir, bbinfo_file, display_width): self.display_width = display_width # Get sorted image list: img_paths = sorted(utils.list_images_in_directory(img_dir)) self.img_index = 0 # Set initial index. self.current_path = img_paths[self.img_index] self.current_img = cv2.imread(self.current_path) self.original_img = self.current_img self.original_shape = self.current_img.shape self.current_scale = 1.0 self.flipped = False self.deleting = False self.editing = False self.rect_tl = None self.rect_br = None if os.path.isfile(bbinfo_file): self.load_opencv_bounding_box_info(bbinfo_file) cv2.setMouseCallback(self.winName, annotate_mouse_callback, self) while True: self.update_display() key = cv2.waitKey(1) & 0xFF # Use arrow keys, or < and > to move between images. # ASCII Codes: # {28: 'right arrow', 29: 'left arrow'} # {30: 'up arrow', 31: 'down arrow'} # Non-standard codes that work for me: # r: 3, l: 2, u: 0, d: 1 right_pressed = (key == 28 or key == 46 or key == 3) left_pressed = (key == 29 or key == 44 or key == 2) # Use delete or backspace to enter delete mode. # ASCII DEL: 127 (the backspace key on OSX) # What OpenCV makes of my delete key: 40 delete_pressed = (key == 127 or key == 40 or key == 8) # Use up arrow or 'f' to flip an image. up_pressed = (key == 30 or key == 0) flip_pressed = up_pressed or key == ord('f') # Space pressed: space_pressed = key == 32 if key == ord('q'): print 'Quitting' break # Save all bounding boxes to the output file: elif key == ord('s'): print 'Saved: {}'.format(bbinfo_file) self.save_opencv_bounding_box_info(bbinfo_file) # Overwrite current image with a rotated copy: elif key == ord('i'): if self.flipped: print 'Overwritten with flipped image: {}'.format(bbinfo_file) self.current_img = cv2.imread(self.current_path) self.current_img = cv2.flip(self.current_img, -1) cv2.imwrite(self.current_path, self.current_img) self.original_img = self.current_img self.flipped = False h, w = self.current_img.shape[:2] rects = self.get_image_rectangles(self.current_path) rects = map(lambda r: r.rotated_180((w,h)), rects) _, key = os.path.split(self.current_path) self.bbinfo_map[key] = rects else: print 'Current image has not been rotated.' # Add a new bounding box: elif key == ord('n') or (space_pressed and not self.editing): print 'New bounding box' self.editing = True # Cancel: elif key == 27: # ESC key print 'Cancel' self.editing = False # Accept bounding box: elif key == 13 or (space_pressed and self.editing): # Enter / CR key if not self.rect_tl is None and not self.rect_br is None: rect = gm.PixelRectangle.fromCorners(self.rect_tl, self.rect_br) if rect.w > 10 and rect.h > 10: self.add_rectangle_to_image(self.current_path, rect) print 'Bounding box {} added.'.format(self.get_annotation_count()) self.editing = False self.rect_tl = None self.rect_br = None else: print 'WARNING: Small ({}x{}) bounding box was not added'.format(rect.w, rect.h) else: print 'WARNING: Invalid bounding box was not added' # Move to next/previous image: elif right_pressed or left_pressed: self.img_index += 1 if right_pressed else -1 self.img_index %= len(img_paths) self.current_path = img_paths[self.img_index] self.current_img = cv2.imread(self.current_path) self.original_img = self.current_img self.original_shape = self.current_img.shape[:2] self.flipped = False print 'Moved to image: {}, {}'.format(self.img_index, self.current_path) elif flip_pressed: # up arrow self.current_img = cv2.flip(self.current_img, -1) self.original_img = cv2.flip(self.original_img, -1) self.flipped = not self.flipped if self.rect_tl and self.rect_br: h, w = self.current_img.shape[:2] rect = gm.PixelRectangle.fromCorners(self.rect_tl, self.rect_br) rect = rect.rotated_180((w,h)) self.rect_tl = tuple(rect.tl) self.rect_br = tuple(rect.br) print 'Flipped image.' elif delete_pressed: self.deleting = True print 'Click a bounding box to DELETE it.' elif key != 255: # 255 means no key was pressed print 'Unused keycode: {}'.format(key)
def test_classifier(classifier_yaml, svm_file_path, window_dims): print "Loading detector..." print svm_file_path # Set the trained svm to my_hog hog_detector = get_svm_detector(svm_file_path) hog = get_hog_object(window_dims) print "len(hog_detector)", len(hog_detector) print "hog.getDescriptorSize()", hog.getDescriptorSize() hog.setSVMDetector(hog_detector) print "...[done]" for test_dir in classifier_yaml["testing"]["directories"]: test_source_name = test_dir.strip("/").split("/")[-1] # results_dir = '{}/{}_results'.format(output_dir, test_source_name) # detections_fname = '{}/{}_detections.dat'.format(output_dir, test_source_name) img_list = sorted(utils.list_images_in_directory(test_dir)) for img_path in img_list: img = cv2.imread(img_path) h, w = img.shape[:2] max_dim = 1200.0 # if w > max_dim + 50 or h > max_dim + 50: if abs(w - max_dim) > 50 or abs(h - max_dim) > 50: sx = max_dim / w sy = max_dim / h current_scale = min(sx, sy) img = cv2.resize(img, dsize=None, fx=current_scale, fy=current_scale) # img = cv2.resize(img, dsize=None, fx=1.5, fy=1.5) # while img.shape[1] > 2000: # print 'resize:', img_path, img.shape # img = cv2.resize(img, dsize=None, fx=0.5, fy=0.5) # # Check whether the image is upside-down: # if checkImageOrientation(img_path): # print 'Flipped!' # img = cv2.flip(img, -1) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) print "Detecting: {}".format(img_path) # winStride = (4,4) winStride = (8, 8) padding = (0, 0) # minSize = (img.shape[0] / 50, img.shape[1] / 50) cars, weights = hog.detectMultiScale( img, winStride=winStride, padding=padding, scale=1.05, useMeanshiftGrouping=False ) print "cars:", cars print "weights:", weights print img_path, len(cars) if len(cars) > 0: for (x, y, w, h) in cars: # img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) lw = max(2, min(img.shape[0], img.shape[1]) / 150) cv2.rectangle(img, (x, y), (x + w, y + h), (255, 255, 255), lw + 2) cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), lw) # roi_gray = gray[y:y+h, x:x+w] # roi_color = img[y:y+h, x:x+w] # img = cv2.resize(img, dsize=None, fx=0.1, fy=0.1) # cv2.namedWindow("img", cv2.WINDOW_NORMAL) # cv2.resizeWindow('img', 500, 500) cv2.imshow("img", img) # cv2.imshow('img',img) while True: key = cv2.waitKey(1) & 0xFF if key == 27: # ESC key cv2.destroyAllWindows() return elif key != 255: break
def update_preview_state(): """Return the new state of the UI given the new settings.""" print 'update_preview_state' print 'request data:' pprint.pprint(request.json) # Get the inputs: currentImgIndex = request.json['currentImgIndex'] hashed_image_dir = request.json['imageDir'] hashed_detector_dir = request.json['detectorDir'] performDetection = request.json['performDetection'] returnImage = request.json['returnImage'] config_yaml = fileutils.load_yaml_file(detector_config_fname) imageDir = validate_image_directory(hashed_image_dir, config_yaml) # Get the images: image_list = sorted(utils.list_images_in_directory(imageDir)) num_images = len(image_list) if num_images == 0: print 'ERROR: The directory \'{}\' contains no images.'.format( imageDir) # TODO: Display a better error to the client. flask.abort(404) # HTTP status codes: Not Found # Find the current image: if not currentImgIndex: currentImgIndex = 0 current_img_index = currentImgIndex % num_images current_img_path = image_list[current_img_index] send_img_path = current_img_path # Perform detection: detections = [] if performDetection: save_img_dir = os.path.join(app.root_path, 'static', 'cache') save_img_fname = '{}.jpg'.format( url_safe_hash(current_img_path + hashed_detector_dir)) save_img_path = os.path.join(save_img_dir, save_img_fname) send_img_path = save_img_path detection_img_exists = os.path.isfile(save_img_path) # if not returnImage and detection_img_exists: # # Delete the current image so that it isn't returned by mistake if # # the detection process fails. # os.remove(save_img_path) if not returnImage or not detection_img_exists: # Perform the detection. detectorDir = validate_detector_directory(hashed_detector_dir, config_yaml) # detector = ObjectDetector.load_from_directory(detectorDir) with ObjectDetector(detectorDir) as detector: img = cv2.imread(current_img_path) detections, img = detector.detect_objects_in_image(img) # cv2.imwrite fails silently if it can't save the image for any # reason. We manually check access permissions here, and throw # an exception to inform the webmaster if they're incorrect. sav_img_dir, _ = os.path.split(save_img_path) if not os.path.isdir(sav_img_dir): raise IOError( 'The sav_img_dir \'{}\' does not exist.'.format( sav_img_dir)) if not os.access(sav_img_dir, os.W_OK): raise IOError( 'The server user (probably www-data) does not have write permissions for the save_img_path: \'{sav_img_dir}\'' .format(sav_img_dir)) cv2.imwrite(save_img_path, img) previewState = jsonify({ 'numImages': num_images, 'currentImgIndex': current_img_index, 'currentImgPath': current_img_path, # 'currentImgUrl' : None, 'detections': detections }) if returnImage: print 'preview state:', previewState.data # Return the image return flask.send_file(send_img_path) else: # Return the new preview state: print 'response data:', previewState.data return previewState
def annotate_directory(self, img_dir, bbinfo_file, display_width): self.display_width = display_width # Get sorted image list: img_paths = sorted(utils.list_images_in_directory(img_dir)) self.img_index = 0 # Set initial index. self.current_path = img_paths[self.img_index] self.current_img = cv2.imread(self.current_path) self.original_img = self.current_img self.original_shape = self.current_img.shape self.current_scale = 1.0 self.flipped = False self.deleting = False self.editing = False self.rect_tl = None self.rect_br = None if os.path.isfile(bbinfo_file): self.load_opencv_bounding_box_info(bbinfo_file) cv2.setMouseCallback(self.winName, annotate_mouse_callback, self) while True: self.update_display() key = cv2.waitKey(1) & 0xFF # Use arrow keys, or < and > to move between images. # ASCII Codes: # {28: 'right arrow', 29: 'left arrow'} # {30: 'up arrow', 31: 'down arrow'} # Non-standard codes that work for me: # r: 3, l: 2, u: 0, d: 1 right_pressed = (key == 28 or key == 46 or key == 3) left_pressed = (key == 29 or key == 44 or key == 2) # Use delete or backspace to enter delete mode. # ASCII DEL: 127 (the backspace key on OSX) # What OpenCV makes of my delete key: 40 delete_pressed = (key == 127 or key == 40 or key == 8) # Use up arrow or 'f' to flip an image. up_pressed = (key == 30 or key == 0) flip_pressed = up_pressed or key == ord('f') # Space pressed: space_pressed = key == 32 if key == ord('q'): print 'Quitting' break # Save all bounding boxes to the output file: elif key == ord('s'): print 'Saved: {}'.format(bbinfo_file) self.save_opencv_bounding_box_info(bbinfo_file) # Overwrite current image with a rotated copy: elif key == ord('i'): if self.flipped: print 'Overwritten with flipped image: {}'.format( bbinfo_file) self.current_img = cv2.imread(self.current_path) self.current_img = cv2.flip(self.current_img, -1) cv2.imwrite(self.current_path, self.current_img) self.original_img = self.current_img self.flipped = False h, w = self.current_img.shape[:2] rects = self.get_image_rectangles(self.current_path) rects = map(lambda r: r.rotated_180((w, h)), rects) _, key = os.path.split(self.current_path) self.bbinfo_map[key] = rects else: print 'Current image has not been rotated.' # Add a new bounding box: elif key == ord('n') or (space_pressed and not self.editing): print 'New bounding box' self.editing = True # Cancel: elif key == 27: # ESC key print 'Cancel' self.editing = False # Accept bounding box: elif key == 13 or (space_pressed and self.editing): # Enter / CR key if not self.rect_tl is None and not self.rect_br is None: rect = gm.PixelRectangle.fromCorners( self.rect_tl, self.rect_br) if rect.w > 10 and rect.h > 10: self.add_rectangle_to_image(self.current_path, rect) print 'Bounding box {} added.'.format( self.get_annotation_count()) self.editing = False self.rect_tl = None self.rect_br = None else: print 'WARNING: Small ({}x{}) bounding box was not added'.format( rect.w, rect.h) else: print 'WARNING: Invalid bounding box was not added' # Move to next/previous image: elif right_pressed or left_pressed: self.img_index += 1 if right_pressed else -1 self.img_index %= len(img_paths) self.current_path = img_paths[self.img_index] self.current_img = cv2.imread(self.current_path) self.original_img = self.current_img self.original_shape = self.current_img.shape[:2] self.flipped = False print 'Moved to image: {}, {}'.format(self.img_index, self.current_path) elif flip_pressed: # up arrow self.current_img = cv2.flip(self.current_img, -1) self.original_img = cv2.flip(self.original_img, -1) self.flipped = not self.flipped if self.rect_tl and self.rect_br: h, w = self.current_img.shape[:2] rect = gm.PixelRectangle.fromCorners( self.rect_tl, self.rect_br) rect = rect.rotated_180((w, h)) self.rect_tl = tuple(rect.tl) self.rect_br = tuple(rect.br) print 'Flipped image.' elif delete_pressed: self.deleting = True print 'Click a bounding box to DELETE it.' elif key != 255: # 255 means no key was pressed print 'Unused keycode: {}'.format(key)
def update_preview_state(): """Return the new state of the UI given the new settings.""" print 'update_preview_state' print 'request data:' pprint.pprint(request.json) # Get the inputs: currentImgIndex = request.json['currentImgIndex'] hashed_image_dir = request.json['imageDir'] hashed_detector_dir = request.json['detectorDir'] performDetection = request.json['performDetection'] returnImage = request.json['returnImage'] config_yaml = fileutils.load_yaml_file(detector_config_fname) imageDir = validate_image_directory(hashed_image_dir, config_yaml) # Get the images: image_list = sorted(utils.list_images_in_directory(imageDir)) num_images = len(image_list) if num_images == 0: print 'ERROR: The directory \'{}\' contains no images.'.format(imageDir) # TODO: Display a better error to the client. flask.abort(404) # HTTP status codes: Not Found # Find the current image: if not currentImgIndex: currentImgIndex = 0 current_img_index = currentImgIndex % num_images current_img_path = image_list[current_img_index] send_img_path = current_img_path # Perform detection: detections = [] if performDetection: save_img_dir = os.path.join(app.root_path, 'static', 'cache') save_img_fname = '{}.jpg'.format(url_safe_hash(current_img_path + hashed_detector_dir)) save_img_path = os.path.join(save_img_dir, save_img_fname) send_img_path = save_img_path detection_img_exists = os.path.isfile(save_img_path) # if not returnImage and detection_img_exists: # # Delete the current image so that it isn't returned by mistake if # # the detection process fails. # os.remove(save_img_path) if not returnImage or not detection_img_exists: # Perform the detection. detectorDir = validate_detector_directory(hashed_detector_dir, config_yaml) # detector = ObjectDetector.load_from_directory(detectorDir) with ObjectDetector(detectorDir) as detector: img = cv2.imread(current_img_path) detections, img = detector.detect_objects_in_image(img) # cv2.imwrite fails silently if it can't save the image for any # reason. We manually check access permissions here, and throw # an exception to inform the webmaster if they're incorrect. sav_img_dir, _ = os.path.split(save_img_path) if not os.path.isdir(sav_img_dir): raise IOError('The sav_img_dir \'{}\' does not exist.'.format(sav_img_dir)) if not os.access(sav_img_dir, os.W_OK): raise IOError('The server user (probably www-data) does not have write permissions for the save_img_path: \'{sav_img_dir}\''.format(sav_img_dir)) cv2.imwrite(save_img_path, img) previewState = jsonify({ 'numImages' : num_images, 'currentImgIndex' : current_img_index, 'currentImgPath' : current_img_path, # 'currentImgUrl' : None, 'detections' : detections }) if returnImage: print 'preview state:', previewState.data # Return the image return flask.send_file(send_img_path) else: # Return the new preview state: print 'response data:', previewState.data return previewState
def test_classifier(classifier_yaml, svm_file_path, window_dims): print 'Loading detector...' print svm_file_path # Set the trained svm to my_hog hog_detector = get_svm_detector(svm_file_path) hog = get_hog_object(window_dims) print 'len(hog_detector)', len(hog_detector) print 'hog.getDescriptorSize()', hog.getDescriptorSize() hog.setSVMDetector(hog_detector) print '...[done]' for test_dir in classifier_yaml['testing']['directories']: test_source_name = test_dir.strip('/').split('/')[-1] # results_dir = '{}/{}_results'.format(output_dir, test_source_name) # detections_fname = '{}/{}_detections.dat'.format(output_dir, test_source_name) img_list = sorted(utils.list_images_in_directory(test_dir)) for img_path in img_list: img = cv2.imread(img_path) h, w = img.shape[:2] max_dim = 1200.0 # if w > max_dim + 50 or h > max_dim + 50: if abs(w - max_dim) > 50 or abs(h - max_dim) > 50: sx = max_dim / w sy = max_dim / h current_scale = min(sx, sy) img = cv2.resize(img, dsize=None, fx=current_scale, fy=current_scale) # img = cv2.resize(img, dsize=None, fx=1.5, fy=1.5) # while img.shape[1] > 2000: # print 'resize:', img_path, img.shape # img = cv2.resize(img, dsize=None, fx=0.5, fy=0.5) # # Check whether the image is upside-down: # if checkImageOrientation(img_path): # print 'Flipped!' # img = cv2.flip(img, -1) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) print 'Detecting: {}'.format(img_path) # winStride = (4,4) winStride = (8, 8) padding = (0, 0) # minSize = (img.shape[0] / 50, img.shape[1] / 50) cars, weights = hog.detectMultiScale(img, winStride=winStride, padding=padding, scale=1.05, useMeanshiftGrouping=False) print 'cars:', cars print 'weights:', weights print img_path, len(cars) if len(cars) > 0: for (x, y, w, h) in cars: # img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) lw = max(2, min(img.shape[0], img.shape[1]) / 150) cv2.rectangle(img, (x, y), (x + w, y + h), (255, 255, 255), lw + 2) cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), lw) # roi_gray = gray[y:y+h, x:x+w] # roi_color = img[y:y+h, x:x+w] # img = cv2.resize(img, dsize=None, fx=0.1, fy=0.1) # cv2.namedWindow("img", cv2.WINDOW_NORMAL) # cv2.resizeWindow('img', 500, 500) cv2.imshow('img', img) # cv2.imshow('img',img) while True: key = cv2.waitKey(1) & 0xFF if key == 27: # ESC key cv2.destroyAllWindows() return elif key != 255: break