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 predict_xor_diff(prob, anlg, tran, d): best_diff_to_u1_x = d.get("diff_to_u1_x") best_diff_to_u1_y = d.get("diff_to_u1_y") best_diff = d.get("diff") u3 = prob.matrix[anlg.get("value")[2]] u1_ref = prob.matrix_ref[anlg.get("value")[0]] prediction = transform.xor_diff(u3, best_diff_to_u1_x, best_diff_to_u1_y, best_diff, u1_ref) pred_data = [] for ii, opt in enumerate(prob.options): print(prob.name, anlg.get("name"), tran.get("name"), ii) pred_score, _, _ = jaccard.jaccard_coef(prediction, opt) u3_score, u3_to_opt_x, u3_to_opt_y = jaccard.jaccard_coef(u3, opt) u3_score = 1 - u3_score u1_aligned, u2_aligned, aligned_to_u2_x, aligned_to_u2_y = utils.align( u3, opt, u3_to_opt_x, u3_to_opt_y) diff = utils.erase_noise_point(np.logical_xor(u1_aligned, u2_aligned), 4) diff_score, _, _ = jaccard.jaccard_coef(diff, best_diff) score = (diff_score + u3_score + pred_score) / 3 pred_data.append({ **d, "optn": ii + 1, "optn_score": score, "mato_score": (d.get("mat_score") + score) / 2, "pred": prediction }) return pred_data
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 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 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 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 xor(imgA, imgB): if imgA.shape != imgB.shape: raise Exception("Crap!") return utils.erase_noise_point(np.logical_xor(imgA, imgB), 4)
def backward_subtract(imgA, imgB): if imgA.shape != imgB.shape: raise Exception("Crap!") return utils.erase_noise_point( np.logical_and(imgB, np.logical_not(np.logical_and(imgB, imgA))), 4)
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
def run_prob_anlg_tran_2x2(prob, anlg, tran): u1 = prob.matrix[anlg.get("value")[0]] u2 = prob.matrix[anlg.get("value")[1]] diff_to_u1_x = None diff_to_u1_y = None diff_to_u2_x = None diff_to_u2_y = None diff = None copies_to_u1_x = None copies_to_u1_y = None u1_coms_x = None u1_coms_y = None u2_coms_x = None u2_coms_y = None if "add_diff" == tran.get("name"): score, diff_to_u1_x, diff_to_u1_y, diff_to_u2_x, diff_to_u2_y, diff = \ asymmetric_jaccard.asymmetric_jaccard_coef(u1, u2) elif "subtract_diff" == tran.get("name"): score, diff_to_u2_x, diff_to_u2_y, diff_to_u1_x, diff_to_u1_y, diff = \ asymmetric_jaccard.asymmetric_jaccard_coef(u2, u1) elif "xor_diff" == tran.get("name"): score, u1_to_u2_x, u1_to_u2_y = jaccard.jaccard_coef(u1, u2) score = 1 - score u1_aligned, u2_aligned, aligned_to_u2_x, aligned_to_u2_y = utils.align( u1, u2, u1_to_u2_x, u1_to_u2_y) diff = utils.erase_noise_point(np.logical_xor(u1_aligned, u2_aligned), 4) diff_to_u2_x = int(aligned_to_u2_x) diff_to_u2_y = int(aligned_to_u2_y) diff_to_u1_x = int(diff_to_u2_x - u1_to_u2_x) diff_to_u1_y = int(diff_to_u2_y - u1_to_u2_y) elif "upscale_to" == tran.get("name"): u1_upscaled = transform.upscale_to(u1, u2) score, _, _ = jaccard.jaccard_coef(u2, u1_upscaled) elif "duplicate" == tran.get("name"): scores = [] u1_to_u2_xs = [] u1_to_u2_ys = [] current = u2.copy() current_to_u2_x = 0 current_to_u2_y = 0 while current.sum(): score_tmp, diff_tmp_to_u1_x, diff_tmp_to_u1_y, diff_tmp_to_current_x, diff_tmp_to_current_y, _ = \ asymmetric_jaccard.asymmetric_jaccard_coef(u1, current) if score_tmp < 0.6: 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) u1_aligned, current_aligned, aligned_to_current_x, aligned_to_current_y = utils.align( u1, current, u1_to_current_x, u1_to_current_y) current = utils.erase_noise_point( np.logical_and(current_aligned, np.logical_not(u1_aligned)), 8) current_to_u2_x = aligned_to_current_x + current_to_u2_x current_to_u2_y = aligned_to_current_y + current_to_u2_y if 1 >= len(scores): score = 0 copies_to_u1_x = [0] copies_to_u1_y = [0] else: score = min(scores) copies_to_u1_x = (np.array(u1_to_u2_xs[1:]) - u1_to_u2_xs[0]).tolist() copies_to_u1_y = (np.array(u1_to_u2_ys[1:]) - u1_to_u2_ys[0]).tolist() elif "rearrange" == tran.get("name"): score, u1_coms_x, u1_coms_y, u2_coms_x, u2_coms_y = transform.evaluate_rearrange( u1, u2) else: u1_t = transform.apply_unary_transformation(u1, tran) score, _, _ = jaccard.jaccard_coef(u1_t, u2) if "mirror" == tran.get("name") or "mirror_rot_180" == tran.get("name"): # if u1 or u2 is already symmetric, then we shouldn't use mirror tran. u1_mirror_score, _, _ = jaccard.jaccard_coef(u1_t, u1) u2_mirror = transform.apply_unary_transformation(u2, tran) u2_mirror_score, _, _ = jaccard.jaccard_coef(u2_mirror, u2) if max(u1_mirror_score, u2_mirror_score) > 0.9: score = 0 prob_anlg_tran_d = assemble_prob_anlg_tran_d(prob, anlg, tran, score, diff_to_u1_x=diff_to_u1_x, diff_to_u1_y=diff_to_u1_y, diff_to_u2_x=diff_to_u2_x, diff_to_u2_y=diff_to_u2_y, diff=diff, copies_to_u1_x=copies_to_u1_x, copies_to_u1_y=copies_to_u1_y, u1_coms_x=u1_coms_x, u1_coms_y=u1_coms_y, u2_coms_x=u2_coms_x, u2_coms_y=u2_coms_y) return prob_anlg_tran_d
def asymmetric_jaccard_coef_naive(A, B): """ max_diff is trimmed to its minimal box. (max_x, max_y) is the relative position of max_diff to A :param A: :param B: :return: a_j_coef, diff_to_A_x, diff_to_A_y, diff_to_B_x, diff_to_B_y, diff """ A_shape_y, A_shape_x = A.shape B_shape_y, B_shape_x = B.shape A_sum = A.sum() if A_shape_x < B_shape_x and A_shape_y < B_shape_y: A_to_B_coords, a_j_coefs = asymmetric_jaccard_coef_naive_embed( A, B, A_sum) elif A_shape_x >= B_shape_x and A_shape_y >= B_shape_y: B_to_A_coords, a_j_coefs = asymmetric_jaccard_coef_naive_embed( B, A, A_sum) A_to_B_coords = -B_to_A_coords elif A_shape_x < B_shape_x and A_shape_y >= B_shape_y: A_to_B_coords, a_j_coefs = asymmetric_jaccard_coef_naive_cross( A, B, A_sum) elif A_shape_x >= B_shape_x and A_shape_y < B_shape_y: B_to_A_coords, a_j_coefs = asymmetric_jaccard_coef_naive_cross( B, A, A_sum) A_to_B_coords = -B_to_A_coords else: raise Exception("Impossible Exception!") a_j_coef = np.max(a_j_coefs) coef_argmax = np.where(a_j_coefs == a_j_coef)[0] if 1 == len(coef_argmax): ii = coef_argmax[0] A_to_B_x, A_to_B_y = A_to_B_coords[ii] else: A_center_x = (A_shape_x - 1) / 2 A_center_y = (A_shape_y - 1) / 2 B_center_x = (B_shape_x - 1) / 2 B_center_y = (B_shape_y - 1) / 2 closest_center_ii = -1 smallest_center_dist = np.inf for ii in coef_argmax: x, y = A_to_B_coords[ii] center_dist = abs(x + A_center_x - B_center_x) + abs(y + A_center_y - B_center_y) if center_dist < smallest_center_dist: closest_center_ii = ii smallest_center_dist = center_dist A_to_B_x, A_to_B_y = A_to_B_coords[closest_center_ii] A_aligned, B_aligned, aligned_to_B_x, aligned_to_B_y = utils.align( A, B, A_to_B_x, A_to_B_y) diff = np.logical_and(B_aligned, np.logical_not(A_aligned)) if diff.any(): diff_y, diff_x = np.where(diff) diff_x_min = diff_x.min() diff_x_max = diff_x.max() + 1 diff_y_min = diff_y.min() diff_y_max = diff_y.max() + 1 diff = diff[diff_y_min:diff_y_max, diff_x_min:diff_x_max] diff_to_B_x = diff_x_min + aligned_to_B_x diff_to_B_y = diff_y_min + aligned_to_B_y diff_to_A_x = diff_to_B_x - A_to_B_x diff_to_A_y = diff_to_B_y - A_to_B_y else: # diff is all white, i.e. B is completely covered by A diff_to_A_x = 0 diff_to_A_y = 0 diff_to_B_x = A_to_B_x diff_to_B_y = A_to_B_y diff = np.full_like(A, fill_value=False) return a_j_coef, diff_to_A_x, diff_to_A_y, diff_to_B_x, diff_to_B_y, utils.erase_noise_point( diff, 4)