commit d6684ac2f27e2b42f6dc84c04ef2a142f09ae043 Author: leon Date: Thu Feb 27 11:09:58 2025 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..aba02a1 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea/ diff --git a/params.json b/params.json new file mode 100644 index 0000000..ea7614a --- /dev/null +++ b/params.json @@ -0,0 +1,272 @@ +[ + { + "code": "1", + "type": "250x1450", + "x": "196.0", + "y": 0, + "center": "351", + "w": "1450", + "h": "250", + "angle": "0\u00b0" + }, + { + "code": "2", + "type": "300x300", + "x": "174.0", + "y": 0, + "center": "754", + "w": "300", + "h": "300", + "angle": "0\u00b0" + }, + { + "code": "3", + "type": "501x500", + "x": "889.5", + "y": 0, + "center": "1054.5", + "w": "500", + "h": "501", + "angle": "0\u00b0" + }, + { + "code": "4", + "type": "250x648", + "x": "-32.0", + "y": 0, + "center": "1149", + "w": "648", + "h": "250", + "angle": "0\u00b0" + }, + { + "code": "5", + "type": "250x250", + "x": "588.0", + "y": 0, + "center": "1543", + "w": "250", + "h": "250", + "angle": "0\u00b0" + }, + { + "code": "6", + "type": "249x249", + "x": "1031.5", + "y": 0, + "center": "1750.5", + "w": "249", + "h": "249", + "angle": "0\u00b0" + }, + { + "code": "7", + "type": "400x399", + "x": "-199.5", + "y": 0, + "center": "1955", + "w": "399", + "h": "400", + "angle": "0\u00b0" + }, + { + "code": "8", + "type": "300x302", + "x": "394.0", + "y": 0, + "center": "2159", + "w": "302", + "h": "300", + "angle": "0\u00b0" + }, + { + "code": "9", + "type": "300x302", + "x": "996.0", + "y": 0, + "center": "2157", + "w": "302", + "h": "300", + "angle": "0\u00b0" + }, + { + "code": "10", + "type": "248x1447", + "x": "2190.0", + "y": 0, + "center": "345", + "w": "1447", + "h": "248", + "angle": "0\u00b0" + }, + { + "code": "11", + "type": "298x297", + "x": "2198.5", + "y": 0, + "center": "747", + "w": "297", + "h": "298", + "angle": "0\u00b0" + }, + { + "code": "12", + "type": "499x499", + "x": "2891.0", + "y": 0, + "center": "1040.5", + "w": "499", + "h": "499", + "angle": "0\u00b0" + }, + { + "code": "13", + "type": "245x648", + "x": "1994.5", + "y": 0, + "center": "1146.5", + "w": "648", + "h": "245", + "angle": "0\u00b0" + }, + { + "code": "14", + "type": "247x247", + "x": "2589.5", + "y": 0, + "center": "1550.5", + "w": "247", + "h": "247", + "angle": "0\u00b0" + }, + { + "code": "15", + "type": "246x247", + "x": "2998.5", + "y": 0, + "center": "1757", + "w": "247", + "h": "246", + "angle": "0\u00b0" + }, + { + "code": "16", + "type": "398x392", + "x": "1799.5", + "y": 0, + "center": "1955", + "w": "392", + "h": "398", + "angle": "0\u00b0" + }, + { + "code": "17", + "type": "300x293", + "x": "2394.5", + "y": 0, + "center": "2147", + "w": "293", + "h": "300", + "angle": "0\u00b0" + }, + { + "code": "18", + "type": "298x297", + "x": "3001.5", + "y": 0, + "center": "2144", + "w": "297", + "h": "298", + "angle": "0\u00b0" + }, + { + "code": "19", + "type": "245x1447", + "x": "4191.5", + "y": 0, + "center": "344.5", + "w": "1447", + "h": "245", + "angle": "0\u00b0" + }, + { + "code": "20", + "type": "295x300", + "x": "4175.0", + "y": 0, + "center": "743.5", + "w": "300", + "h": "295", + "angle": "0\u00b0" + }, + { + "code": "21", + "type": "498x495", + "x": "4897.5", + "y": 0, + "center": "1030", + "w": "495", + "h": "498", + "angle": "0\u00b0" + }, + { + "code": "22", + "type": "245x648", + "x": "3977.0", + "y": 0, + "center": "1150.5", + "w": "648", + "h": "245", + "angle": "0\u00b0" + }, + { + "code": "23", + "type": "245x246", + "x": "4547.5", + "y": 0, + "center": "1541.5", + "w": "246", + "h": "245", + "angle": "0\u00b0" + }, + { + "code": "24", + "type": "245x245", + "x": "4992.5", + "y": 0, + "center": "1735.5", + "w": "245", + "h": "245", + "angle": "0\u00b0" + }, + { + "code": "25", + "type": "398x392", + "x": "3796.5", + "y": 0, + "center": "1955", + "w": "392", + "h": "398", + "angle": "0\u00b0" + }, + { + "code": "26", + "type": "298x296", + "x": "4392.5", + "y": 0, + "center": "2142", + "w": "296", + "h": "298", + "angle": "0\u00b0" + }, + { + "code": "27", + "type": "297x295", + "x": "4991.5", + "y": 0, + "center": "2146.5", + "w": "295", + "h": "297", + "angle": "0\u00b0" + } +] \ No newline at end of file diff --git a/search.py b/search.py new file mode 100644 index 0000000..5453e89 --- /dev/null +++ b/search.py @@ -0,0 +1,489 @@ +import cv2 +print(cv2.__version__) # 4.9.0 +import json +import math +import copy +import numpy as np +import time +from scipy.spatial import distance +from scipy.optimize import linear_sum_assignment + +def get_params(num_param, start, end): + return copy.deepcopy(num_param[start:end+1]) + +def parmas_to_num(text_param): + for item in text_param: + item['center'] = int(float(item['center']) * 1000) + item['x'] = int(item['x']) + item['w'] = int(item['w']) + item['h'] = int(item['h']) + return text_param + +def parmas_to_text(num_param): + for item in num_param: + item['center'] = str(item['center']) + item['x'] = str(item['x']) + item['w'] = str(item['w']) + item['h'] = str(item['h']) + item['x1'] = str(item['x1']) + item['y1'] = str(item['y1']) + item['x2'] = str(item['x2']) + item['y2'] = str(item['y2']) + item['x3'] = str(item['x3']) + item['y3'] = str(item['y3']) + item['x4'] = str(item['x4']) + item['y4'] = str(item['y4']) + item['x_center'] = str(item['x_center']) + item['y_center'] = str(item['y_center']) + return num_param + +def sort_params(params): + sorted_params = sorted(params, key=lambda item: (item['center'], item['x'])) + return sorted_params + +def print_params(sort_params): + for param in sort_params: + print(param["center"], param["x"], param["w"], param["h"]) + +def print_path(search_path): + for path in search_path: + print(path[0], path[1]) + +def search_path(sort_params): + searchPath = [] + for i in range(len(sort_params) - 1): + (r, theta) = cartesian_to_polar(sort_params[i]["x"], sort_params[i]["center"], + sort_params[i + 1]["x"], sort_params[i + 1]["center"]) + searchPath.append([r, theta]) + return searchPath + +def normalize_params_and_path(sort_params, search_path, index=0): + base = sort_params[index]["h"] + for param in sort_params: + param['center'] /= base + param['x'] /= base + param['w'] /= base + param['h'] /= base + param['w/h'] = param['w'] / param['h'] + if search_path != None: + for path in search_path: + path[0] /= base + # path[1] /= base + return sort_params, search_path + +def read_from_json(file_path): + with open(file_path, 'r') as f: + loaded_array = json.load(f) + return loaded_array + +def cartesian_to_polar(x1, y1, x2, y2): + dx = x2 - x1 + dy = y2 - y1 + r = math.sqrt(dx**2 + dy**2) + theta = math.atan2(dy, dx) + return r, theta + +def calculate_second_point(x1, y1, r, theta_radians): + # theta_radians = math.radians(theta_degrees) + x2 = x1 + r * math.cos(theta_radians) + y2 = y1 + r * math.sin(theta_radians) + + return x2, y2 + +def cal_c1c2c3c4(param, heigt): + ''' + 按照上左、上右、下右、下左的顺时针顺序 + ''' + param['x1'] = int(param['x'] - param['w'] / 2) + param['y1'] = heigt - int(param['center'] + param['h'] / 2) + + param['x2'] = int(param['x'] + param['w'] / 2) + param['y2'] = heigt - int(param['center'] + param['h'] / 2) + + param['x3'] = int(param['x'] + param['w'] / 2) + param['y3'] = heigt - int(param['center'] - param['h'] / 2) + + param['x4'] = int(param['x'] - param['w'] / 2) + param['y4'] = heigt - int(param['center'] - param['h'] / 2) + + param['x_center'] = int((param['x1'] + param['x2']) / 2) + param['y_center'] = int((param['y1'] + param['y3']) / 2) + return param + +def gen_im_from_params(params, type="lines"): + # 依据bim数据生成bim图 + # type: line points + ## 计算bim图长和宽 + max_y = -999999 + max_y_idx = -1 + max_x = -999999 + max_x_idx = -1 + for i, param in enumerate(params): + if param["x"] + param["w"] / 2 > max_x: + max_x = param["x"] + param["w"] / 2 + max_x_idx = i + if param["center"] + param["h"] / 2 > max_y: + max_y = param["center"] + param["h"] / 2 + max_y_idx = i + ## 为了不贴边,x,y固定加 500 + FILL_VALUE = 0 + bim_width = int(max_x) + bim_height = int(max_y) + bim_width += FILL_VALUE + bim_height += FILL_VALUE + bim_channels = 1 + im = np.zeros((bim_height, bim_width, bim_channels), dtype=np.uint8) + + for i, param in enumerate(params): + cal_c1c2c3c4(param, bim_height) + if type == "lines": + pts = np.asarray([[param['x1'], param['y1']], + [param['x2'], param['y2']], + [param['x3'], param['y3']], + [param['x4'], param['y4']]]) + cv2.polylines(im, [pts], True, (255,0,0), 8) + elif type == "points": + cv2.circle(im, (param['x1'], param['y1']), 1, 255, 20) + cv2.circle(im, (param['x2'], param['y2']), 1, 255, 20) + cv2.circle(im, (param['x3'], param['y3']), 1, 255, 20) + cv2.circle(im, (param['x4'], param['y4']), 1, 255, 20) + cv2.circle(im, (param['x'], int((param['y3'] + param['y2']) / 2 )), 1, (255,0,0), 8) + + return im + +def gen_points_from_params(params): + # 依据bim数据生成bim图 + # type: line points + ## 计算bim图长和宽 + max_y = -999999 + max_y_idx = -1 + max_x = -999999 + max_x_idx = -1 + for i, param in enumerate(params): + if param["x"] + param["w"] / 2 > max_x: + max_x = param["x"] + param["w"] / 2 + max_x_idx = i + if param["center"] + param["h"] / 2 > max_y: + max_y = param["center"] + param["h"] / 2 + max_y_idx = i + ## 为了不贴边,x,y固定加 500 + bim_height = int(max_y) + points = [] + adjacency = [] # 邻接矩阵 + for i, param in enumerate(params): + cal_c1c2c3c4(param, bim_height) + points.append([param['x1'], param['y1'], i]) + points.append([param['x2'], param['y2'], i]) + points.append([param['x3'], param['y3'], i]) + points.append([param['x4'], param['y4'], i]) + # points.append([param['x'], int((param['y3'] + param['y2']) / 2 )]) + points.append([param['x_center'], param['y_center'], i]) + return points + +def topological_similarity(adj1, adj2): + """ + 计算两个拓扑结构的相似度 + """ + # 计算邻接矩阵的相似度 + similarity = np.sum(adj1 == adj2) / (adj1.shape[0] * adj2.shape[1]) + return similarity + +def find_topological_matches(points1, adj1, points2, adj2, threshold=0.8): + """ + 基于拓扑结构寻找匹配点集 + """ + matches = [] + for i in range(len(points1)): + for j in range(len(points2)): + # 计算拓扑相似度 + sim = topological_similarity(adj1[i], adj2[j]) + if sim > threshold: + matches.append((i, j, sim)) + # 按相似度排序 + matches.sort(key=lambda x: x[2], reverse=True) + return matches + +from sklearn.linear_model import RANSACRegressor + +def ransac_shape_matching(points, reference_points): + model_ransac = RANSACRegressor(random_state=42) + try: + model_ransac.fit(reference_points, points[:len(reference_points)]) # 假设点数相同 + except ValueError as e: + print("Error fitting the model:", e) + return [] + + inlier_mask = model_ransac.inlier_mask_ + best_match_subset = points[inlier_mask] + + return best_match_subset + +def polar_to_cartesian(polar_points): + r = polar_points[:, 0] + theta = polar_points[:, 1] + x = r * np.cos(theta) + y = r * np.sin(theta) + return np.vstack((x, y)).T + +def compute_shape_context(points, nbins_r=5, nbins_theta=12): + n = points.shape[0] + shape_contexts = [] + r_max = np.max(distance.pdist(points)) + r_edges = np.logspace(-1, np.log10(r_max), nbins_r) + theta_edges = np.linspace(-np.pi, np.pi, nbins_theta + 1) + + for i in range(n): + current_point = points[i] + relative_points = points - current_point + rs = np.hypot(relative_points[:, 0], relative_points[:, 1]) + thetas = np.arctan2(relative_points[:, 1], relative_points[:, 0]) + H, _, _ = np.histogram2d(thetas, rs, bins=[theta_edges, r_edges]) + H /= np.sum(H) + 1e-8 # 归一化 + shape_contexts.append(H.flatten()) + + return np.array(shape_contexts) + +def match_shapes(sc1, sc2): + cost_matrix = distance.cdist(sc1, sc2, metric='sqeuclidean') + row_ind, col_ind = linear_sum_assignment(cost_matrix) + return cost_matrix[row_ind, col_ind].sum() + +def _sobel(image): + ''' + _sobel + ''' + if image.ndim > 2: + image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) + # todo 增加几个参数 http://blog.csdn.net/sunny2038/article/details/9170013 + _sobelx = cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize=1) + _sobely = cv2.Sobel(image, cv2.CV_64F, 0, 1, ksize=1) + + _sobelx = np.uint8(np.absolute(_sobelx)) + _sobely = np.uint8(np.absolute(_sobely)) + _sobelcombine = cv2.bitwise_or(_sobelx,_sobely) + return _sobelcombine + +def _findContours(image): + ''' + _findContours + http://blog.csdn.net/mokeding/article/details/20153325 + ''' + contours, _ = cv2.findContours(image.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) + return sorted(contours, key=cv2.contourArea, reverse=True) + +if __name__ == "__main__": + # 读取并处理数据 + data_bim = {} + data_bim["type"] = 0 + data_bim["params"] = read_from_json("./params.json") + data_bim["point"] = [] + data_bim["params"] = parmas_to_num(data_bim["params"]) + + data_sub = {} + data_sub["type"] = 0 + data_sub["params"] = [] + + # 创建测试子集 + sub_im = cv2.imread("wide_image.png") + sub_zero = np.zeros_like(sub_im) + _im_gray = cv2.cvtColor(sub_im, cv2.COLOR_BGR2GRAY) + _im_gray = cv2.GaussianBlur(_im_gray, (5, 5), 0) + _im_edge_sobel = _sobel(_im_gray) + _, _im_thresh = cv2.threshold(_im_edge_sobel, 5, 255, cv2.THRESH_BINARY) + cnts = _findContours(_im_thresh) + for contour in cnts: + x, y, w, h = cv2.boundingRect(contour) + cv2.rectangle(sub_zero, (x, y), (x + w, y + h), (255, 255, 255), -1) + _im_edge_sobel = _sobel(sub_zero) + _, _im_thresh = cv2.threshold(_im_edge_sobel, 5, 255, cv2.THRESH_BINARY) + cnts = _findContours(_im_thresh) + for contour in cnts: + x, y, w, h = cv2.boundingRect(contour) + # 由于定位框大小大于预埋件大小,因此这里需要做缩放处理 + k = int(h*0.2) # roi2 + k = int(h*0.01) # roi1 + x += k + y += k + w -= int(k) # + h -= int(k) # 2k + param = {} + param["x1"] = x + param["y1"] = y + param["x2"] = x + w + param["y2"] = y + param["x3"] = x + w + param["y3"] = y + h + param["x4"] = x + param["y4"] = y + h + param['x_center'] = int((param['x1'] + param['x2']) / 2) + param['y_center'] = int((param['y1'] + param['y3']) / 2) + param["w"] = param["x2"] - param["x1"] + param["h"] = param["y3"] - param["y1"] + param["x"] = int((param["x1"] + param["x2"]) / 2) + param['center'] = sub_im.shape[0] - int((param["y1"] + param["y3"]) / 2) + data_sub["params"].append(param) + cv2.rectangle(sub_zero, (x, y), (x + w, y + h), (0, 255, 0), 1) + + # cv2.imshow("1", sub_zero) + # cv2.waitKey(0) + + # data_sub = {} + # data_sub["type"] = 0 + # data_sub["params"] = get_params(data_bim["params"], 1,8) + # data_sub["point"] = [] + # data_sub["params"][0]["center"] += 20 + # data_sub["params"][0]["x"] += 13 + # data_sub["params"][0]["w"] += 40 + + ##################### 开始计算 #################### + # 1、计算sub的搜索路径 + ## 1.1 排序 y升序,x升序 + data_sub["params"] = sort_params(data_sub["params"]) + _sub_sort_params = data_sub["params"] + start_time = time.time() + + # sub_roi_height = int(max_y) #???? + # sub_roi_width = int(max_x) #???? + sub_roi_height = sub_im.shape[0] + sub_roi_width = sub_im.shape[1] + sub_roi_params_select_id = -1 + sub_roi_w_base_len = 0 # 选中预埋件的宽度作为基础长度 + sub_roi_divide_w_h = 1 + polar_origin_x = 0 # 极坐标原点 x + polar_origin_y = 0 # 极坐标原点 y + start_x = 0 + start_y = 0 + ## 1.2 选择一块完整的预埋件 + for i, param in enumerate(_sub_sort_params): + if 0 < param['x1'] and param['x2'] < sub_roi_width \ + and 0 < param['y1'] and param['y3'] < sub_roi_height: + sub_roi_params_select_id = i + sub_roi_w_base_len = param['x2'] - param['x1'] + sub_roi_divide_w_h = param['w'] / param['h'] + polar_origin_x = int(param['x1']) # 当前选择的预埋件的左上角 x 坐标 + polar_origin_y = int(param['y1']) # 当前选择的预埋件的左上角 y 坐标 + break + if sub_roi_params_select_id == -1 or sub_roi_w_base_len == 0 : + print("[ERROR]\t 拍摄的图像中没有完整的预埋件信息\n") + assert(0) + ## 1.2.2 将其他预埋件相对于它的极坐标进行填写 + for i, param in enumerate(_sub_sort_params): + if i != sub_roi_params_select_id: + param['r'], param['theta'] = cartesian_to_polar(_sub_sort_params[sub_roi_params_select_id]['x_center'], + _sub_sort_params[sub_roi_params_select_id]['y_center'], + param['x_center'],param['y_center']) + + ## 1.3计算所有点到该预埋件左上点的,点个数,平均极半径 和 平均极角度 + sum_r, sum_theta = 0.0,0 + count = 0 + pts = gen_points_from_params(_sub_sort_params) + polar_list = [] + for i, pt in enumerate(pts): + r, theta = cartesian_to_polar(polar_origin_x, polar_origin_y, pt[0], pt[1]) + sum_r += r + sum_theta += theta + count += 1 + polar_list.append([r, theta]) + sum_r /= count * sub_roi_w_base_len + sum_theta /= count + print(count, sum_r, sum_theta) + + # 初始化候选预埋件 + candi_params = [] + for i, param in enumerate(data_bim["params"]): + temp_div_w_h = param['w'] / param['h'] + if temp_div_w_h / sub_roi_divide_w_h < 1.5 and temp_div_w_h / sub_roi_divide_w_h > 0.66: + candi_params.append(param) + print(f"形状筛选后还剩下:{len(candi_params)} 个候选, w / h = {sub_roi_divide_w_h}") + + rst_params = [] + bim_all_pts = gen_points_from_params(data_bim["params"]) + bim_im = gen_im_from_params(data_bim["params"]) + # sub_im = gen_im_from_params(data_sub["params"])# 需要读取 + min_match_score = 999999 + for i, param in enumerate(candi_params): + tmp_roi_w_base_len = param['x2'] - param['x1'] + scale = tmp_roi_w_base_len / sub_roi_w_base_len + tmp_roi_width = int(scale * sub_roi_width) + tmp_roi_height = int(scale * sub_roi_height) + # 相对于bim图的坐标 + tmp_roi_start_x = int(param['x1'] - scale * polar_origin_x) + tmp_roi_end_x = tmp_roi_start_x + tmp_roi_width + tmp_roi_start_y = int(param['y1'] - scale * polar_origin_y) + tmp_roi_end_y = tmp_roi_start_y + tmp_roi_height + tmp_roi_conners = [[tmp_roi_start_x, tmp_roi_start_y], + [tmp_roi_end_x, tmp_roi_start_y], + [tmp_roi_end_x, tmp_roi_end_y], + [tmp_roi_start_x, tmp_roi_end_y]] + tmp_sum_r, tmp_sum_theta = 0.0, 0 + tmp_count = 0 + tmp_polar_list = [] + # 这里需要把选中的预埋件也提取出来 + param['effective_points'] = [] + for j, pt in enumerate(bim_all_pts): + if cv2.pointPolygonTest(np.asarray(tmp_roi_conners), (pt[0],pt[1]), False) > 0: + r, theta = cartesian_to_polar(param['x1'], param['y1'], pt[0], pt[1]) + tmp_sum_r += r + tmp_sum_theta += theta + tmp_count += 1 + tmp_polar_list.append([r, theta]) + # 搜集有效点,以供后续继续处理 + param['effective_points'].append(pt) + tmp_sum_r /= tmp_count * tmp_roi_w_base_len + tmp_sum_theta /= tmp_count + + # 预埋件数量相差 30%,则不进行计算 + # if tmp_count / count > 1.3 or tmp_count / count < 0.77: continue + + if abs(tmp_count - count) == 0: score = 0.5 + elif abs(tmp_count - count) <= 10: score = 0.3 + elif abs(tmp_count - count) <= 20: score = 0.2 + elif abs(tmp_count - count) <= 30: score = 0.1 + else: score = 0.0 + + # else: score = (1 / abs(tmp_count - count) ) * 0.7 + score += (1 - abs(tmp_sum_r - sum_r) / sub_roi_width) * 0.25 + score += (1 - abs(tmp_sum_theta - sum_theta) / 3.14) * 0.25 + + if score > 0.6: #???? + cartesian_points1 = polar_to_cartesian(np.asarray(tmp_polar_list)) + cartesian_points2 = polar_to_cartesian(np.asarray(polar_list)) + sc1 = compute_shape_context(cartesian_points1) + sc2 = compute_shape_context(cartesian_points2) + match_score = match_shapes(sc1, sc2) + print(score, match_score, tmp_count, tmp_sum_r, tmp_sum_theta) + if match_score < 5.0: #???? + param["start_point"] = (tmp_roi_start_x, tmp_roi_start_y) + param["end_point"] = (tmp_roi_end_x, tmp_roi_end_y) + param["score"] = (score, tmp_count, tmp_sum_r*tmp_roi_w_base_len, tmp_sum_theta) + param['match_score'] = match_score + if min_match_score > match_score: + min_match_score = match_score + rst_params.append(param) + + # 预埋件匹配 + for i, param in enumerate(rst_params): + score = param["score"] + match_score = param["match_score"] + id = param["code"] + if min_match_score == match_score or match_score < 0.5: #???? + # if True: + index_list = [] + for j in range(len(param['effective_points'])): + pt = param['effective_points'][j] + if pt[2] not in index_list: + index_list.append(param['effective_points'][j][2]) + # for i, param in enumerate(_sub_sort_params): + # param[] + print(f"起始预埋件ID:{id},置信度为:{score[0]},点数量:{score[1]},平均长度为:{score[2]},平均角度为:{score[3]}") + print(f"match_sscore为:{match_score}") + bim_im = cv2.rectangle(bim_im, param["start_point"], \ + param["end_point"], 255, 6) + + elapsed_time = time.time() - start_time + print(f"Execution time: {elapsed_time:.4f} seconds") + img_matches = cv2.resize(bim_im, (int(bim_im.shape[1]/6), int(bim_im.shape[0]/6))) + # sub_im = cv2.resize(sub_im, (int(sub_im.shape[1]/10), int(sub_im.shape[0]/10))) + cv2.imshow("1", img_matches) + cv2.imshow("2", sub_im) + cv2.waitKey(0) \ No newline at end of file diff --git a/wide_image.png b/wide_image.png new file mode 100644 index 0000000..130ff08 Binary files /dev/null and b/wide_image.png differ