def test_raw_object_regression(self): raw_8bit = convert_to_8bit(self.raw_image) features = quick_features(raw_8bit) with open("expected/case_1_blob_qf.pickle", "rb") as f: expected_features = pickle.load(f) #pickle.dump(features, open("expected/case_1_blob_qf.pickle", "wb")) expect_rep = sorted(expected_features) features_rep = sorted(features) self.assertEqual(str(expect_rep), str(features_rep))
def test_simple_object(self): features = quick_features(self.red_blob) blob_mask = np.uint8(np.mean(self.red_blob, 2)) > 0 diff = blob_mask != (features['binary'] > 0) self.assertLess(np.count_nonzero(diff), 4) # uses edges so it is slightly different self.assertEqual(14, features['area']) self.assertAlmostEqual(6.876, features['major_axis_length'], 2) self.assertAlmostEqual(2.781, features['minor_axis_length'], 2) self.assertAlmostEqual(0.068, features['orientation'], 2) self.assertEqual(0.01, features['clipped_fraction']) self.assertEqual(0.875, features['solidity']) # is it spread a bit
def test_intensity_object(self): red_blue_blob = self.red_blob.copy() red_blue_blob[5:8, 2:7, 2] = 20 features = quick_features(red_blue_blob) red_intensity = features['intensity_red'] self.assertAlmostEqual(129, red_intensity['median_intensity'], 1) self.assertAlmostEqual(79, red_intensity['mean_intensity'], 0) # it includes some borders self.assertGreater(70, red_intensity['std_intensity'], 3) self.assertAlmostEqual(1, red_intensity['perc_25_intensity'], 3) self.assertAlmostEqual(129, red_intensity['perc_75_intensity'], 3) blue_intensity = features['intensity_blue'] self.assertAlmostEqual(20, blue_intensity['median_intensity'], 1) self.assertAlmostEqual(15.7, blue_intensity['mean_intensity'], 0) # it includes some borders self.assertGreater(8, blue_intensity['std_intensity'], 3) self.assertAlmostEqual(20, blue_intensity['perc_25_intensity'], 3) self.assertAlmostEqual(20, blue_intensity['perc_75_intensity'], 3) gray_intensity = features['intensity_gray'] self.assertAlmostEqual(49, gray_intensity['median_intensity'], 1) self.assertAlmostEqual(31.5, gray_intensity['mean_intensity'], 0) self.assertAlmostEqual(22.85, gray_intensity['std_intensity'], 1) self.assertAlmostEqual(6, gray_intensity['perc_25_intensity'], 3) self.assertAlmostEqual(50, gray_intensity['perc_75_intensity'], 3) # there is nothing in green only noise green_intensity = features['intensity_green'] self.assertGreater(1, green_intensity['mean_intensity']) self.assertGreater(1, green_intensity['std_intensity'], 3) self.assertAlmostEqual(0, green_intensity['perc_25_intensity'], 3) self.assertAlmostEqual(1, green_intensity['perc_75_intensity'], 3) self.assertGreater(0.1, green_intensity['mass_displace_in_images'], 3) self.assertGreater(0.1, green_intensity['mass_displace_in_minors'], 3)
def process_image(bundle): image_path = bundle['image_path'] image = bundle['image'] data_path = bundle['data_path'] image_dir = bundle['image_dir'] cfg = bundle['cfg'] total_images = bundle['total_images'] filename = os.path.basename(image_path) # Patch bug in PCAM where timestamp string is somtimes incorrectly set to # 0 or a small value. Use the file creation time instead. # # This is okay so long as the queue in PCAM mostly empty. We can adapt # the frame counter to fix this in the future. timestamp = 0 for substr in filename.split('-'): try: timestamp = int(substr) break except ValueError: pass # use the file creation time if the timestamp is funky if timestamp < 100000: timestamp = os.path.getctime(image_path) prefix = filename.split('.')[0] # image is preloaded so no need to load here #image = cvtools.import_image(data_path,filename,bayer_pattern=cv2.COLOR_BAYER_BG2RGB) img_c_8bit = cvtools.convert_to_8bit(image) # images will be saved out later so set save_to_disk to False features = cvtools.quick_features(img_c_8bit, save_to_disk=False, abs_path=image_dir, file_prefix=prefix) filename = os.path.basename(image_path).split('.')[0] + '.png' timestring = datetime.datetime.fromtimestamp(timestamp).strftime( '%Y-%m-%d %H:%M:%S') entry = {} entry['maj_axis_len'] = features['major_axis_length'] entry['min_axis_len'] = features['minor_axis_length'] entry['aspect_ratio'] = features['aspect_ratio'] entry['area'] = features['area'] entry['clipped_fraction'] = features['clipped_fraction'] entry['orientation'] = features['orientation'] * 180 / math.pi entry['timestring'] = timestring entry['timestamp'] = timestamp entry['width'] = img_c_8bit.shape[1] entry['height'] = img_c_8bit.shape[0] entry['url'] = bundle['reldir'] + '/' + filename entry['file_size'] = os.path.getsize(image_path) output = {} output['entry'] = entry output['image_path'] = image_dir output['prefix'] = prefix output['features'] = features return output
def process_image(bundle): image_path = bundle['image_path'] image = bundle['image'] data_path = bundle['data_path'] image_dir = bundle['image_dir'] cfg = bundle['cfg'] total_images = bundle['total_images'] filename = os.path.basename(image_path) # Patch bug in PCAM where timestamp string is somtimes incorrectly set to # 0 or a small value. Use the file creation time instead. # # This is okay so long as the queue in PCAM mostly empty. We can adapt # the frame counter to fix this in the future. timestamp = 0 for substr in filename.split('-'): try: timestamp = int(substr) break except ValueError: pass # Range check the timestamp if timestamp < 100000: print("" + filename + " strange timestamp.") #timestamp = os.path.getctime(image_path) output = {} return output prefix = filename.split('.')[0] # image is preloaded so no need to load here #image = cvtools.import_image(data_path,filename,bayer_pattern=cv2.COLOR_BAYER_BG2RGB) img_c_8bit = cvtools.convert_to_8bit(image) # images will be saved out later so set save_to_disk to False features = cvtools.quick_features(img_c_8bit, save_to_disk=False, abs_path=image_dir, file_prefix=prefix, cfg=cfg) use_jpeg = use_jpeg = cfg.get("UseJpeg").lower() == 'true' if use_jpeg: filename = os.path.basename(image_path).split('.')[0] + '.jpeg' else: filename = os.path.basename(image_path).split('.')[0] + '.png' # handle new file formwat with unixtime in microseconds if timestamp > 1498093400000000: timestamp = timestamp / 1000000 # Range check the timestamp if timestamp < 100000 or timestamp > time.time(): print("" + filename + " strange timestamp.") #timestamp = os.path.getctime(image_path) output = {} return output # print "Timestamp: " + str(timestamp) timestring = datetime.datetime.fromtimestamp(timestamp).strftime( '%Y-%m-%d %H:%M:%S') entry = {} entry['maj_axis_len'] = features['major_axis_length'] entry['min_axis_len'] = features['minor_axis_length'] entry['aspect_ratio'] = features['aspect_ratio'] entry['area'] = features['area'] entry['clipped_fraction'] = features['clipped_fraction'] entry['orientation'] = features['orientation'] * 180 / math.pi entry['eccentricity'] = features['eccentricity'] entry['solidity'] = features['solidity'] entry['estimated_volume'] = features['estimated_volume'] entry['intensity_gray'] = features['intensity_gray'] entry['intensity_red'] = features['intensity_red'] entry['intensity_green'] = features['intensity_green'] entry['intensity_blue'] = features['intensity_blue'] entry['timestring'] = timestring entry['timestamp'] = timestamp entry['width'] = img_c_8bit.shape[1] entry['height'] = img_c_8bit.shape[0] entry['url'] = bundle['reldir'] + '/' + filename entry['file_size'] = os.path.getsize(image_path) output = {} output['entry'] = entry output['image_path'] = image_dir output['prefix'] = prefix output['features'] = features return output