def rearrange(img, old_xs, old_ys, new_xs, new_ys): coms, coms_x, coms_y = utils.decompose(img, 8) if len(coms) != len(old_xs): return np.full_like(img, fill_value=False) new_coms = [] for com, com_x, com_y in zip(coms, coms_x, coms_y): closet_dist = np.inf closest_ii = -1 for ii, old_x, old_y in zip(range(len(old_xs)), old_xs, old_ys): dist = abs(com_x - old_x) + abs(com_y - old_y) if dist < closet_dist: closet_dist = dist closest_ii = ii x = new_xs[closest_ii] y = new_ys[closest_ii] bg = np.full((300, 300), fill_value=False) bg[y:y + com.shape[0], x:x + com. shape[1]] = com # A bug here, but I am too tired to fix it today. new_coms.append(bg) current = np.full((300, 300), fill_value=False) for new_com in new_coms: current = np.logical_or(current, new_com) return utils.trim_binary_image(current)
def asymmetric_jaccard_coef_pos_fixed(A, B, A_to_B_x, A_to_B_y, coord=False): A_sum = A.sum() B_sum = B.sum() if 0 == A_sum: if 0 == B_sum: j_coef, diff, diff_to_B_x, diff_to_B_y = 0, None, 0, 0 else: j_coef, diff, diff_to_B_x, diff_to_B_y = 1, B, 0, 0 else: if 0 == B_sum: j_coef, diff, diff_to_B_x, diff_to_B_y = 0, None, 0, 0 else: A_aligned, B_aligned, aligned_to_B_x, aligned_to_B_y = utils.align( A, B, A_to_B_x, A_to_B_y) itsc = np.logical_and(A_aligned, B_aligned) j_coef = itsc.sum() / A_sum diff, diff_to_aligned_x, diff_to_aligned_y = utils.trim_binary_image( utils.erase_noise_point( np.logical_and(B_aligned, np.logical_not(itsc)), 4), coord=True) # diff = B - A diff_to_B_x = diff_to_aligned_x + aligned_to_B_x diff_to_B_y = diff_to_aligned_y + aligned_to_B_y if coord: return j_coef, diff, diff_to_B_x, diff_to_B_y else: return j_coef, diff
def soft_jaccard(A, B, asymmetric = False): A_tr, A_tr_to_A_x, A_tr_to_A_y = utils.trim_binary_image(A, coord = True) B_tr, B_tr_to_B_x, B_tr_to_B_y = utils.trim_binary_image(B, coord = True) sj, A_tr_to_B_tr_x, A_tr_to_B_tr_y, diff_B_tr = soft_jaccard_naive(A_tr, B_tr, asymmetric) if asymmetric: diff = utils.erase_noise_point(diff_B_tr, 4) diff_to_A_x = -A_tr_to_B_tr_x + A_tr_to_A_x diff_to_A_y = -A_tr_to_B_tr_y + A_tr_to_A_y diff_to_B_x = B_tr_to_B_x diff_to_B_y = B_tr_to_B_y return sj, int(diff_to_A_x), int(diff_to_A_y), int(diff_to_B_x), int(diff_to_B_y), diff else: A_to_B_x = -A_tr_to_A_x + A_tr_to_B_tr_x + B_tr_to_B_x A_to_B_y = -A_tr_to_A_y + A_tr_to_B_tr_y + B_tr_to_B_y return sj, int(A_to_B_x), int(A_to_B_y)
def add_diff(img, diff_to_ref_x, diff_to_ref_y, diff, ref): """ :param img: :param diff_to_ref_x: :param diff_to_ref_y: :param diff: :param ref: :return: """ if 0 == diff.sum(): return img iimg = img.copy() iimg_to_img_x = 0 iimg_to_img_y = 0 while True: _, ref_to_iimg_x, ref_to_iimg_y = jaccard.jaccard_coef(ref, iimg) diff_to_iimg_x = diff_to_ref_x + ref_to_iimg_x diff_to_iimg_y = diff_to_ref_y + ref_to_iimg_y score, _ = asymmetric_jaccard.asymmetric_jaccard_coef_pos_fixed( diff, iimg, diff_to_iimg_x, diff_to_iimg_y) if score > 0.9: ref_aligned, iimg_aligned, aligned_to_iimg_x, aligned_to_iimg_y = utils.align( ref, iimg, ref_to_iimg_x, ref_to_iimg_y) iimg_aligned = utils.erase_noise_point( np.logical_and(iimg_aligned, np.logical_not(ref_aligned)), 4) iimg = iimg_aligned iimg_to_img_x = aligned_to_iimg_x + iimg_to_img_x iimg_to_img_y = aligned_to_iimg_y + iimg_to_img_y if iimg.sum() == 0: return img else: break diff_to_img_x = diff_to_iimg_x + iimg_to_img_x diff_to_img_y = diff_to_iimg_y + iimg_to_img_x diff_aligned, img_aligned, _, _ = utils.align(diff, img, diff_to_img_x, diff_to_img_y) return utils.trim_binary_image(np.logical_or(img_aligned, diff_aligned))
def duplicate(img, copies_to_img_x, copies_to_img_y): current = img.copy() current_to_img_x = 0 current_to_img_y = 0 for copy_to_img_x, copy_to_img_y in zip(copies_to_img_x, copies_to_img_y): copy_to_current_x = copy_to_img_x - current_to_img_x copy_to_current_y = copy_to_img_y - current_to_img_y copy_aligned, current_aligned, aligned_to_current_x, aligned_to_current_y = utils.align( img, current, copy_to_current_x, copy_to_current_y) current = np.logical_or(copy_aligned, current_aligned) current_to_img_x = aligned_to_current_x + current_to_img_x current_to_img_y = aligned_to_current_y + current_to_img_y return utils.trim_binary_image(current)
def inv_unite(A, B, C): _, B_to_A_x, B_to_A_y = jaccard.jaccard_coef(B, A) _, C_to_A_x, C_to_A_y = jaccard.jaccard_coef(C, A) B_to_C_x = B_to_A_x - C_to_A_x B_to_C_y = B_to_A_y - C_to_A_y B_aligned, C_aligned, aligned_to_C_x, aligned_to_C_y = utils.align( B, C, B_to_C_x, B_to_C_y) B_new = np.logical_and(B_aligned, np.logical_not(C_aligned)) aligned_to_A_x = aligned_to_C_x + C_to_A_x aligned_to_A_y = aligned_to_C_y + C_to_A_y A_aligned, B_aligned, _, _ = utils.align(A, B_new, -aligned_to_A_x, -aligned_to_A_y) C_new = np.logical_and(A_aligned, np.logical_not(B_aligned)) C_new = utils.trim_binary_image(utils.erase_noise_point(C_new, 8)) return C_new
def shadow_mask_unite(A, B): shadow_A = utils.fill_holes(A) shadow_B = utils.fill_holes(B) score, shadow_A_to_B_x, shadow_A_to_B_y = jaccard.jaccard_coef(A, B) shadow_A_aligned, shadow_B_aligned, _, _ = utils.align( shadow_A, shadow_B, shadow_A_to_B_x, shadow_A_to_B_y) mask = np.logical_and(shadow_A_aligned, shadow_B_aligned) A_aligned, B_aligned, _, _ = utils.align(A, B, shadow_A_to_B_x, shadow_A_to_B_y) union = np.logical_or(A_aligned, B_aligned) masked_union = np.logical_and(mask, union) return utils.trim_binary_image(masked_union)
def evaluate_duplicate(u1, u2): scores = [] u1_to_u2_xs = [] u1_to_u2_ys = [] current = u2.copy() current_to_u2_x = 0 current_to_u2_y = 0 u1_tr = utils.trim_binary_image(u1) while current.sum(): old_score_tmp, old_diff_tmp_to_u1_x, old_diff_tmp_to_u1_y, old_diff_tmp_to_current_x, old_diff_tmp_to_current_y, old_diff_tmp = \ asymmetric_jaccard.asymmetric_jaccard_coef(u1, current) score_tmp, diff_tmp_to_u1_x, diff_tmp_to_u1_y, diff_tmp_to_current_x, diff_tmp_to_current_y, diff_tmp = \ soft_jaccard.soft_jaccard(u1, current, asymmetric = True) if score_tmp < 0.9: break scores.append(score_tmp) u1_to_current_x = (-diff_tmp_to_u1_x) - (-diff_tmp_to_current_x) u1_to_current_y = (-diff_tmp_to_u1_y) - (-diff_tmp_to_current_y) u1_to_u2_x = u1_to_current_x + current_to_u2_x u1_to_u2_y = u1_to_current_y + current_to_u2_y u1_to_u2_xs.append(u1_to_u2_x) u1_to_u2_ys.append(u1_to_u2_y) current = diff_tmp current_to_u2_x = diff_tmp_to_current_x + current_to_u2_x current_to_u2_y = diff_tmp_to_current_y + current_to_u2_y if 1 >= len(scores): mat_score = 0 u1_to_u2_locs = [] else: mat_score = np.mean(scores) u1_to_u2_xs = ((np.array(u1_to_u2_xs) - min(u1_to_u2_xs)) / u1_tr.shape[1]).tolist() u1_to_u2_ys = ((np.array(u1_to_u2_ys) - min(u1_to_u2_ys)) / u1_tr.shape[0]).tolist() u1_to_u2_locs = np.array(list(zip(u1_to_u2_xs, u1_to_u2_ys))) stub = utils.make_stub(u1_to_u2_locs) return mat_score, stub
def predict_duplicate_new(prob, anlg, tran, d): u3 = prob.matrix[anlg.get("value")[2]] u3_tr = utils.trim_binary_image(u3) u1_to_u2_locs = d.get("stub").get("u1_to_u2_locs") pred_data = [] for ii, opt in enumerate(prob.options): print(prob.name, anlg.get("name"), tran.get("name"), ii) if len(u1_to_u2_locs) <= 1: score = 0 else: dup_score, stub = transform.evaluate_duplicate(u3, opt) u3_to_opt_locs = stub.get("u1_to_u2_locs") if len(u1_to_u2_locs) != len(u3_to_opt_locs): score = 0 else: # it is actually a location map dist = np.array([[ np.linalg.norm(u1_to_u2_loc - u3_to_opt_loc) for u3_to_opt_loc in u3_to_opt_locs ] for u1_to_u2_loc in u1_to_u2_locs]) lcm_u2_com_ids, lcm_opt_com_ids, level = map.max_size_injective_mapping( dist, lambda a, b: a <= b) if len(lcm_u2_com_ids) != len(u1_to_u2_locs): score = 0 else: shape_relative_location_score = 1 - level / ( (u3.shape[0] / u3_tr.shape[0])**2 + (u3.shape[1] / u3_tr.shape[1])**2)**0.5 score = (dup_score + shape_relative_location_score) / 2 pred_data.append({ **d, "optn": ii + 1, "optn_score": score, "mato_score": (d.get("mat_score") + score) / 2, "pred": opt }) return pred_data
def xor_diff(img, diff_to_ref_x, diff_to_ref_y, diff, ref): """ :param img: :param diff_to_ref_x: :param diff_to_ref_y: :param diff: :param ref: :return: """ if 0 == diff.sum(): return img _, img_to_ref_x, img_to_ref_y = jaccard.jaccard_coef(img, ref) diff_to_img_x = diff_to_ref_x - img_to_ref_x diff_to_img_y = diff_to_ref_y - img_to_ref_y diff_aligned, img_aligned, _, _ = utils.align(diff, img, diff_to_img_x, diff_to_img_y) return utils.erase_noise_point( utils.trim_binary_image(np.logical_xor(img_aligned, diff_aligned)), 4)
def subtract_diff(img, diff_to_ref_x, diff_to_ref_y, diff, ref, coords=False): """ :param img: :param diff_to_ref_x: :param diff_to_ref_y: :param diff: :param ref: :return: """ if 0 == diff.sum(): if coords: return img, 0, 0 else: return img _, img_to_ref_x, img_to_ref_y = jaccard.jaccard_coef(img, ref) diff_to_img_x = diff_to_ref_x - img_to_ref_x diff_to_img_y = diff_to_ref_y - img_to_ref_y diff_aligned, img_aligned, aligned_to_img_x, aligned_to_img_y = utils.align( diff, img, diff_to_img_x, diff_to_img_y) result, result_to_aligned_x, result_to_aligned_y = utils.trim_binary_image( utils.erase_noise_point( np.logical_and(img_aligned, np.logical_not(diff_aligned)), 8), coord=True) if coords: diff_to_result_x = (diff_to_img_x - aligned_to_img_x) - result_to_aligned_x diff_to_result_y = (diff_to_img_y - aligned_to_img_y) - result_to_aligned_y return result, diff_to_result_x, diff_to_result_y else: return result
def load_problems(problem_folder = None, problem_coordinates_file = None, show_me = False): global raven_folder global raven_coordinates_file if problem_folder is None: problem_folder = raven_folder if problem_coordinates_file is None: problem_coordinates_file = raven_coordinates_file problem_filenames = natsorted([f for f in listdir(problem_folder) if isfile(join(problem_folder, f))]) problem_names = [f.split('.')[0] for f in problem_filenames] problem_paths = [join(problem_folder, f) for f in problem_filenames] raw_images = [plt.imread(path) for path in problem_paths] with open(problem_coordinates_file) as f: problem_coordinates = [] coordinates = [] for line in f: rect_coords = [int(x) for x in line.split()] if 0 == len(rect_coords): problem_coordinates.append(coordinates) coordinates = [] else: coordinates.append(rect_coords) with open("./problems/stuff.txt", "r") as f: answers = [] for line in f: answers.append(int(line)) problems = [] for img, coords, problem_name, answer in zip(raw_images, problem_coordinates, problem_names, answers): print(problem_name) jaccard.load_jaccard_cache(problem_name) coms = utils.extract_components(img, coords) smaller_coms = [rescale(image = com, scale = (0.5, 0.5)) for com in coms] binary_smaller_coms = [utils.grey_to_binary(com, 0.7) for com in smaller_coms] binary_smaller_coms = [utils.erase_noise_point(com, 4) for com in binary_smaller_coms] # let's try it first. Although somebody doesn't agree on this, but I think it won't hurt the alignment. # because even if the alignment is not what it is in the original images, it will still give the correct # answer. # and it will definitely accelerate the computation. binary_smaller_coms = [utils.trim_binary_image(com) for com in binary_smaller_coms] binary_smaller_coms, binary_smaller_coms_ref = standardize(binary_smaller_coms) if 10 == len(coms): matrix = utils.create_object_matrix(binary_smaller_coms[: 4], (2, 2)) matrix_ref = utils.create_object_matrix(binary_smaller_coms_ref[: 4], (2, 2)) options = binary_smaller_coms[4:] problems.append(RavenProgressiveMatrix(problem_name, matrix, matrix_ref, options, answer)) elif 17 == len(coms): matrix = utils.create_object_matrix(binary_smaller_coms[: 9], (3, 3)) matrix_ref = utils.create_object_matrix(binary_smaller_coms_ref[: 9], (3, 3)) options = binary_smaller_coms[9:] problems.append(RavenProgressiveMatrix(problem_name, matrix, matrix_ref, options, answer)) else: raise Exception("Crap!") jaccard.save_jaccard_cache(problem_name) if show_me: for prob in problems: prob.plot_problem() return problems
def load_problems(problem_folder=None, problem_coordinates_file=None, show_me=False): global raven_folder global raven_coordinates_file if problem_folder is None: problem_folder = raven_folder if problem_coordinates_file is None: problem_coordinates_file = raven_coordinates_file problem_filenames = natsorted([ f for f in listdir(problem_folder) if isfile(join(problem_folder, f)) ]) problem_names = [f.split('.')[0] for f in problem_filenames] problem_paths = [join(problem_folder, f) for f in problem_filenames] raw_images = [plt.imread(path) for path in problem_paths] with open(problem_coordinates_file) as f: problem_coordinates = [] coordinates = [] for line in f: rect_coords = [int(x) for x in line.split()] if 0 == len(rect_coords): problem_coordinates.append(coordinates) coordinates = [] else: coordinates.append(rect_coords) with open("./problems/stuff.txt", "r") as f: answers = [] for line in f: answers.append(int(line)) problems = [] for img, coords, problem_name, answer in zip(raw_images, problem_coordinates, problem_names, answers): print("load problem: " + problem_name) jaccard.load_jaccard_cache(problem_name) coms = utils.extract_components(img, coords) smaller_coms = [rescale(image=com, scale=(0.5, 0.5)) for com in coms] binary_smaller_coms = [ utils.grey_to_binary(com, 0.7) for com in smaller_coms ] binary_smaller_coms = [ utils.erase_noise_point(com, 4) for com in binary_smaller_coms ] binary_smaller_coms = [ utils.trim_binary_image(com) for com in binary_smaller_coms ] binary_smaller_coms, binary_smaller_coms_ref = standardize( binary_smaller_coms) if 10 == len(coms): matrix = utils.create_object_matrix(binary_smaller_coms[:4], (2, 2)) matrix_ref = utils.create_object_matrix( binary_smaller_coms_ref[:4], (2, 2)) options = binary_smaller_coms[4:] problems.append( RavenProgressiveMatrix(problem_name, matrix, matrix_ref, options, answer)) elif 17 == len(coms): matrix = utils.create_object_matrix(binary_smaller_coms[:9], (3, 3)) matrix_ref = utils.create_object_matrix( binary_smaller_coms_ref[:9], (3, 3)) options = binary_smaller_coms[9:] problems.append( RavenProgressiveMatrix(problem_name, matrix, matrix_ref, options, answer)) else: raise Exception("Crap!") jaccard.save_jaccard_cache(problem_name) if show_me: for prob in problems: prob.plot_problem() return problems