def plot_pca(X, y): # apply PCA to data pca = PCA(n_components=200) pca.fit(X, y) # plot variance explained by each component plt.plot(np.cumsum(pca.explained_variance_ratio_)) plt.xlabel('Number of PCA components') plt.ylabel('Total explained variance ratio') plt.grid() plt.savefig(get_file('output', 'graphs', 'pca_wing_explained.eps'), bbox_inches='tight') plt.clf() # plot principal component vs angle X_t = pca.transform(X) plt.scatter(X_t[:, 0].flatten(), y.flatten()) plt.xlabel('PCA Component 1') plt.ylabel('Wing angle (deg)') plt.grid() plt.savefig(get_file('output', 'graphs', 'pca_wing.eps'), bbox_inches='tight') plt.clf()
def main(): X = joblib.load(get_file('output', 'data', X_JOBLIB_NAME)) y = joblib.load(get_file('output', 'data', Y_JOBLIB_NAME)) for type in ['male', 'female']: print('{} fly orientation detector...'.format(type.capitalize())) train_once(X, y, type)
def plot_pca(X, y, type): # apply PCA to data pca = PCA(n_components=200) pca.fit(X, y) # plot variance explained by each component plt.plot(np.cumsum(pca.explained_variance_ratio_)) plt.xlabel('Number of PCA components') plt.ylabel('Total explained variance ratio') plt.grid() plt.savefig(get_file('output', 'graphs', 'pca_orient_{}_explained.eps'.format(type)), bbox_inches='tight') plt.clf() # show how data are separated by first two principal components X_t = pca.transform(X) for l, c, m in zip(range(2), ('blue', 'red'), ('o', 'x')): plt.scatter(X_t[y == l, 0], X_t[y == l, 1], color=c, label=CATEGORIES[l], alpha=0.5, marker=m) plt.legend(loc='upper right') plt.xlabel('PCA 1') plt.ylabel('PCA 2') plt.grid() plt.savefig(get_file('output', 'graphs', 'pca_orient_{}.eps'.format(type)), bbox_inches='tight') plt.clf()
def train_once(X, y): clf, X_train, X_test, y_train, y_test = train(X, y) report_model_classification(clf, X_train, X_test, y_train, y_test) tree.export_graphviz(clf, out_file=get_file('output', 'diagrams', 'tree_is_fly.dot'), feature_names=FEATURES, class_names=CATEGORIES, filled=True, rounded=True, special_characters=True) joblib.dump(clf, get_file('output', 'models', CLF_JOBLIB_NAME))
def train_once(X, y): clf, X_train, X_test, y_train, y_test = train(X, y, plot=True) report_model_regression(clf, X_train, X_test, y_train, y_test, units='radians') joblib.dump(clf, get_file('output', 'models', CLF_JOBLIB_NAME))
def train_once(X, y, type): clf, X_train, X_test, y_train, y_test = train(X, y, type, plot=True) report_model_classification(clf, X_train, X_test, y_train, y_test) joblib.dump(clf, get_file('output', 'models', clf_joblib_name(type)))
def __init__(self, type): self.clf = joblib.load(get_file('output', 'models', clf_joblib_name(type))) self.hog = make_hog()
def main(): X = joblib.load(get_file('output', 'data', X_JOBLIB_NAME)) y = joblib.load(get_file('output', 'data', Y_JOBLIB_NAME)) train_once(X, y)
def __init__(self): self.clf = joblib.load(get_file('output', 'models', CLF_JOBLIB_NAME))
def main(): X, y = load_data() joblib.dump(X, get_file('output', 'data', X_JOBLIB_NAME)) joblib.dump(y, get_file('output', 'data', Y_JOBLIB_NAME))
def load_data(tol_radians=0.1): hog = make_hog() X = [] y = [] img_count = 0 hand_labeled_count = 0 for anno in tqdm(get_annotations()): img = cv2.imread(anno.image_path, 0) mask = img_to_mask(img) contours = find_contours(img, mask=mask, type='core') for contour in contours: type = contour_label(anno, contour) if type == 'male': break else: continue if anno.count('mw') == 2 and anno.has('mh') and anno.has( 'ma') and anno.has('mp2'): mh = anno.get('mh')[0] ma = anno.get('ma')[0] mp2 = anno.get('mp2')[0] else: continue # make patch, which will compute the angle from the image body_patch = crop_to_contour(img, contour) # compute angle from labels label_angle = np.arctan2(ma[1] - mh[1], mh[0] - ma[0]) # find out if the image is flipped or not rotate_angle = body_patch.estimate_angle() diff = abs(angle_diff(rotate_angle, label_angle)) if diff <= tol_radians: pass elif np.pi - tol_radians <= diff <= np.pi + tol_radians: rotate_angle = rotate_angle + np.pi else: anno.warn( 'Could not properly determine whether image is flipped (diff={:0.1f} degrees)' .format(degrees(diff))) continue # find center of fly body_center = body_patch.estimate_center(absolute=True) # create patch centered on fly fly_patch = male_fly_patch(img, mask, body_center, rotate_angle) if fly_patch is None: continue origin = bound_point((body_center[0], body_center[1]), img) mp2_rel = [mp2[0] - origin[0], origin[1] - mp2[1]] rot_mat = get_rotation_matrix(np.pi / 2 - rotate_angle) mp2_rot = rot_mat.dot(mp2_rel) wings = [] for mw in anno.get('mw'): wing_rel = [mw[0] - origin[0], origin[1] - mw[1]] wing_rot = rot_mat.dot(wing_rel) - mp2_rot angle = np.arctan(abs(wing_rot[0]) / abs(wing_rot[1])) wings.append({'x': wing_rot[0], 'angle': angle}) if len(wings) != 2: anno.warn('Length of wings is not 2 for some reason, skipping...') continue if wings[0]['x'] > wings[1]['x']: # wing 0 is right, wing 1 is left right_wing_angle = wings[0]['angle'] left_wing_angle = wings[1]['angle'] else: # wing 1 is right, wing 0 is left right_wing_angle = wings[1]['angle'] left_wing_angle = wings[0]['angle'] # create a hog patches for both wings data = [] data.append({ 'hog_patch': make_hog_patch(fly_patch), 'angle': right_wing_angle }) data.append({ 'hog_patch': make_hog_patch(fly_patch.flip('horizontal')), 'angle': left_wing_angle }) # add data to X and y for datum in data: X.append(patch_to_features(datum['hog_patch'], hog)) y.append(datum['angle']) hand_labeled_count += 1 if DEBUG: plt.imshow(datum['hog_patch'].img) plt.show() # increment img_count to indicate that this file was actually used img_count += 1 # assemble features X = np.array(X, dtype=float) # assemble labels y = np.array(y, dtype=float) print('Used {} annotated images.'.format(img_count)) print('Used {} hand-labeled wings.'.format(hand_labeled_count)) report_labels_regression(np.degrees(y), filename=get_file('output', 'graphs', 'labels_wing.eps'), units='Wing Angle (degrees)') return X, y