diff --git a/stitching/10pct_stitch_data.json b/stitching/10pct_stitch_data.json new file mode 100644 index 0000000000000000000000000000000000000000..a480156a7730312f40162e70d9db6ad54c431114 --- /dev/null +++ b/stitching/10pct_stitch_data.json @@ -0,0 +1 @@ +[{"src_name": "10.jpg", "src_shape": [916, 630], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -0.08323251825809101, "scale": 0.9987168967645754, "x": 724.937576965776, "y": -0.2724258105480133}, {"src_name": "11.jpg", "src_shape": [908, 758], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -0.47064110395516434, "scale": 0.99932858086887, "x": 1452.0367084024429, "y": 1.5122426728092173}, {"src_name": "12.jpg", "src_shape": [884, 756], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -0.3934912301887074, "scale": 0.999136761213508, "x": 2204.0481973340998, "y": 9.396687861442064}, {"src_name": "13.jpg", "src_shape": [924, 703], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -0.434097036012544, "scale": 0.9986708756016456, "x": 2974.4064499184497, "y": -56.29346567727545}, {"src_name": "14.jpg", "src_shape": [1179, 824], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": 18.600059627212573, "scale": 1.0020764862820368, "x": 3503.34632490913, "y": -102.40566486723438}, {"src_name": "15.jpg", "src_shape": [1176, 723], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": 30.68075628506069, "scale": 1.0009182704184914, "x": 4288.781547783238, "y": -384.15277625327826}, {"src_name": "16.jpg", "src_shape": [937, 640], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": 59.27279296555015, "scale": 0.9992142625551349, "x": 4991.783401733625, "y": -641.1667716306335}, {"src_name": "17.jpg", "src_shape": [1198, 741], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": 51.326905411831675, "scale": 1.0010873217153031, "x": 5334.963483085732, "y": -1397.8491176674052}, {"src_name": "18.jpg", "src_shape": [945, 635], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": 21.715292737953863, "scale": 0.999757157196785, "x": 6009.404999140806, "y": -2215.4850427819665}, {"src_name": "19.jpg", "src_shape": [1138, 702], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": 17.159085000640786, "scale": 0.999983424190333, "x": 6726.909179157137, "y": -2569.1579288984294}, {"src_name": "20.jpg", "src_shape": [1053, 640], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -4.474011069028673, "scale": 1.0042889574059193, "x": 7634.630837206781, "y": -2872.3062646943886}, {"src_name": "21.jpg", "src_shape": [1116, 674], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -1.5941355993687503, "scale": 1.0044268123047049, "x": 8398.131364748531, "y": -2804.108710051584}, {"src_name": "22.jpg", "src_shape": [1026, 741], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": 13.907035689973842, "scale": 1.0045197023304284, "x": 9164.94258836202, "y": -2822.087249257736}, {"src_name": "23.jpg", "src_shape": [1259, 777], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": 8.319061556340293, "scale": 1.0053910816677443, "x": 9793.416611532226, "y": -3021.906048499889}, {"src_name": "24.jpg", "src_shape": [1072, 633], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -12.311740571320277, "scale": 1.0062618600454079, "x": 10900.269661053793, "y": -3129.09180213983}, {"src_name": "25.jpg", "src_shape": [977, 627], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -12.349979421999674, "scale": 1.0062865889960106, "x": 11655.537826246926, "y": -2962.6933795872283}, {"src_name": "26.jpg", "src_shape": [1322, 702], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -6.995648727695043, "scale": 1.0069199799008584, "x": 12337.214707340861, "y": -2806.6469301026586}, {"src_name": "27.jpg", "src_shape": [1007, 632], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": 33.201443265689804, "scale": 1.0079288168155593, "x": 13061.612058567873, "y": -2519.0813916557436}, {"src_name": "28.jpg", "src_shape": [1020, 627], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": 33.12402136483341, "scale": 1.0085621857854716, "x": 13767.579807939695, "y": -2977.625265123696}, {"src_name": "29.jpg", "src_shape": [960, 627], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": 33.20783481458347, "scale": 1.0083044803095986, "x": 14362.002105535716, "y": -3365.826594471863}, {"src_name": "30.jpg", "src_shape": [947, 627], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": 33.13070287734584, "scale": 1.008991951271489, "x": 15022.87882231445, "y": -3796.6048435431003}, {"src_name": "31.jpg", "src_shape": [1388, 739], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": 32.58237921254713, "scale": 1.0095200237397446, "x": 15706.543432591854, "y": -4244.895509755913}, {"src_name": "32.jpg", "src_shape": [1032, 679], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -57.280362702260184, "scale": 1.009714748542485, "x": 17162.760376936483, "y": -4567.3493591359675}, {"src_name": "33.jpg", "src_shape": [1030, 634], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -71.77371168132912, "scale": 1.0081230992816619, "x": 17624.426963716327, "y": -3915.693438458922}, {"src_name": "34.jpg", "src_shape": [932, 629], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -71.94103050073986, "scale": 1.0072945637427086, "x": 17891.652247256134, "y": -3106.4331378865572}, {"src_name": "35.jpg", "src_shape": [891, 627], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -71.83197135746067, "scale": 1.0088204745924598, "x": 18117.415071608473, "y": -2416.846861528226}, {"src_name": "42.jpg", "src_shape": [1083, 624], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -57.151971357460674, "scale": 1.0088204745924598, "x": 18298.229691123088, "y": -1717.030575499215}, {"src_name": "43.jpg", "src_shape": [949, 622], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -56.86258924913814, "scale": 1.0092888418924757, "x": 18725.19391995254, "y": -1051.332966694144}, {"src_name": "44.jpg", "src_shape": [1047, 684], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -58.37093187951716, "scale": 1.010075036150894, "x": 19170.78065555643, "y": -397.01920235604746}, {"src_name": "45.jpg", "src_shape": [1151, 851], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -74.69912000074456, "scale": 1.0099602599967992, "x": 19620.255673729294, "y": 224.56247792874285}, {"src_name": "46.jpg", "src_shape": [1300, 923], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -56.55992144352802, "scale": 1.0090856354650057, "x": 19709.47027608597, "y": 808.1736740098451}, {"src_name": "47.jpg", "src_shape": [1330, 1135], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -62.82462095691768, "scale": 1.0097173042179441, "x": 20511.200326539925, "y": 1549.578272648425}, {"src_name": "48.jpg", "src_shape": [1299, 1107], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -48.97236920402119, "scale": 1.0090740044004334, "x": 20782.03417679028, "y": 2333.96583116829}, {"src_name": "49.jpg", "src_shape": [932, 1235], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -32.52694592320658, "scale": 1.0022295035742146, "x": 21257.169614729155, "y": 2947.11297964966}, {"src_name": "50.jpg", "src_shape": [817, 1235], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -32.6514641928547, "scale": 1.0018671778967456, "x": 21916.61331601686, "y": 3365.6725909845595}, {"src_name": "39.jpg", "src_shape": [1121, 1352], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -12.121740571320277, "scale": 1.0183370023659528, "x": 10984.528088423816, "y": -4425.946925085604}, {"src_name": "40.jpg", "src_shape": [920, 1550], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -12.199348405703118, "scale": 1.0181802313166457, "x": 11996.279991634043, "y": -4481.088144280133}, {"src_name": "41.jpg", "src_shape": [945, 1559], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -12.699163227703027, "scale": 1.0184935111732853, "x": 12633.834968637137, "y": -4348.663289114105}, {"src_name": "36.jpg", "src_shape": [1045, 825], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -12.349979421999674, "scale": 1.009314532593792, "x": 11618.167864978492, "y": -2343.7085465040805}, {"src_name": "37.jpg", "src_shape": [1307, 1006], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": -12.365639862215458, "scale": 1.0087459997960804, "x": 12278.347213128478, "y": -2384.1146151566822}, {"src_name": "38.jpg", "src_shape": [1715, 1083], "dst_name": "9.jpg", "dst_shape": [845, 627], "angle": 33.12402136483341, "scale": 1.0151178399930771, "x": 12622.231874202234, "y": -3505.617907255542}] \ No newline at end of file diff --git a/stitching/scan.py b/stitching/scan.py index 726a5eac4ca780f0aa16458b8a8745df7a1aaf4a..50b079ecdfa366e751ddd4638e21e16d1c659762 100644 --- a/stitching/scan.py +++ b/stitching/scan.py @@ -8,6 +8,8 @@ import cv2 as cv import numpy as np import matplotlib.pyplot as plt import json +import pathlib +import copy def resize_image(img, scale): @@ -334,10 +336,28 @@ def extract_from_R_mat(R_mat): return angle, scale, t_x, t_y +def compose_R_mat(angle, scale, t_x, t_y): + rad = angle * np.pi / 180 + R = np.zeros((3, 3), np.float32) + R[0, 0] = np.cos(rad) * scale + R[0, 1] = - np.sin(rad) * scale + R[0, 2] = t_x + R[1, 0] = np.sin(rad) * scale + R[1, 1] = np.cos(rad) * scale + R[1, 2] = t_y + R[2, 2] = 1 + return R + + def truncate_path(s): return s.replace('imgs/danube_10_pct/', '') +def get_img_shape(img_name): + img = cv.imread(img_name) + return img.shape[1], img.shape[0] + + def get_match_details(img_names, matches_lis): details_lis = [] for match in matches_lis: @@ -357,9 +377,266 @@ def get_match_details(img_names, matches_lis): return details_lis -def get_img_shape(img_name): - img = cv.imread(img_name) - return img.shape[1], img.shape[0] +def get_3x3_id(): + K = np.zeros((3, 3), np.float32) + K[0, 0] = 1.0 + K[1, 1] = 1.0 + K[2, 2] = 1.0 + return K + + +def rotate_vec(pt, angle, center): + x, y = pt[0] - center[0], pt[1] - center[1] + rad = angle * np.pi / 180 + rot_x, rot_y = x * np.cos(rad) - y * np.sin(rad), x * np.sin(rad) + y * np.cos(rad) + return rot_x + center[0], rot_y + center[1] + + +def get_seam_mask(img_name, data): + subset_data = [] + nsh_lis = {} + for data_set in data: + if data_set['src_name'] == img_name or data_set['dst_name'] == img_name: + subset_data.append(data_set) + nsh_lis[data_set['src_name']] = data_set['src_shape'] + nsh_lis[data_set['dst_name']] = data_set['dst_shape'] + masks = {} + for name, shape in nsh_lis.items(): + masks[name] = cv.UMat(255 * np.ones((shape[1], shape[0]), np.uint8)) + if subset_data[0]['src_name'] == img_name: # start of the chain + warper2 = cv.PyRotationWarper('affine', 1 / subset_data[0]['scale']) + R_2 = compose_R_mat(subset_data[0]['angle'], 1, 0, 0) + corner2, mask_w_2 = warper2.warp(masks[subset_data[0]['dst_name']], get_3x3_id(), R_2, cv.INTER_LINEAR, + cv.BORDER_CONSTANT) + rot_x, rot_y = rotate_vec((-subset_data[0]['x'] / subset_data[0]['scale'], + -subset_data[0]['y'] / subset_data[0]['scale']), + -subset_data[0]['angle'], (0, 0)) + corner2 = (corner2[0] + rot_x, corner2[1] + rot_y) + corners = [(0, 0), corner2] + masks_w = [masks[subset_data[0]['src_name']], mask_w_2] + seam_finder = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_VORONOI_SEAM) + updated_masks = seam_finder.find(masks_w, corners, masks_w) + return updated_masks[0].get() + elif (len(nsh_lis) == 2) and (subset_data[0]['dst_name'] == img_name): # end of the chain + warper1 = cv.PyRotationWarper('affine', subset_data[0]['scale']) + R_1 = compose_R_mat(-subset_data[0]['angle'], 1, 0, 0) + corner1, mask_w_1 = warper1.warp(masks[subset_data[0]['src_name']], get_3x3_id(), R_1, cv.INTER_LINEAR, + cv.BORDER_CONSTANT) + corner1 = (corner1[0] + subset_data[0]['x'], corner1[1] + subset_data[0]['y']) + corners = [corner1, (0, 0)] + masks_w = [mask_w_1, masks[subset_data[0]['dst_name']]] + seam_finder = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_VORONOI_SEAM) + updated_masks = seam_finder.find(masks_w, corners, masks_w) + return updated_masks[1].get() + else: # middle of the chain + warper1 = cv.PyRotationWarper('affine', subset_data[0]['scale']) + R_1 = compose_R_mat(-subset_data[0]['angle'], 1, 0, 0) + corner1, mask_w_1 = warper1.warp(masks[subset_data[0]['src_name']], get_3x3_id(), R_1, cv.INTER_LINEAR, + cv.BORDER_CONSTANT) + corner1 = (corner1[0] + subset_data[0]['x'], corner1[1] + subset_data[0]['y']) + warper2 = cv.PyRotationWarper('affine', 1/subset_data[1]['scale']) + R_2 = compose_R_mat(subset_data[1]['angle'], 1, 0, 0) + corner2, mask_w_2 = warper2.warp(masks[subset_data[1]['dst_name']], get_3x3_id(), R_2, cv.INTER_LINEAR, + cv.BORDER_CONSTANT) + rot_x, rot_y = rotate_vec((-subset_data[1]['x']/subset_data[1]['scale'], + -subset_data[1]['y']/subset_data[1]['scale']), + -subset_data[1]['angle'], (0, 0)) + corner2 = (corner2[0] + rot_x, corner2[1] + rot_y) + corners = [corner1, (0, 0), corner2] + masks_w = [mask_w_1, masks[subset_data[0]['dst_name']], mask_w_2] + seam_finder = cv.detail.SeamFinder_createDefault(cv.detail.SeamFinder_VORONOI_SEAM) + updated_masks = seam_finder.find(masks_w, corners, masks_w) + return updated_masks[1].get() + + +def transform_data_relative_to_first(data): + new_data = [] + angle, scale, x, y = 0, 1, 0, 0 + first_name = data[0]['src_name'] + first_shape = data[0]['src_shape'] + for dat in data: + scale *= 1 / dat['scale'] + angle += dat['angle'] + xr, yr = rotate_vec((- dat['x'] * scale, - dat['y'] * scale), - angle, (0, 0)) + x += xr + y += yr + new_dat = {'src_name': dat['dst_name'], + 'src_shape': dat['dst_shape'], + 'dst_name': first_name, + 'dst_shape': first_shape, + 'angle': angle, + 'scale': scale, + 'x': x, + 'y': y} + new_data.append(new_dat) + return new_data + + +def get_vertices(shape, angle, x, y): + center = [shape[0]/2, shape[1]/2] + pts = [(0, 0), (shape[0], 0), (shape[0], shape[1]), (0, shape[1])] + vertices = [] + x0, y0 = rotate_vec(pts[0], - angle, center) + for i in range(0, 4): + vert = rotate_vec(pts[i], - angle, center) + vert = [round(vert[0] + x - x0), round(vert[1] + y - y0)] + vertices.append(vert) + vertices = np.array(vertices, np.int32).reshape((-1, 1, 2)) + return vertices + + +def get_roi(data, incl_first=True): + if incl_first: + points = [get_vertices(data[0]['dst_shape'], 0, 0, 0)] + else: + points = [] + for dat in data: + rect = get_vertices(np.array(dat['src_shape']) * dat['scale'], dat['angle'], dat['x'], dat['y']) + points.append(rect) + points = np.reshape(points, (-1, 2)) + pt_max = np.max(points, axis=0) + pt_min = np.min(points, axis=0) + x, y = pt_min[0], pt_min[1] + w, h = pt_max[0] - pt_min[0], pt_max[1] - pt_min[1] + return x, y, w, h + + +def scale_data(data, factor): + new_data = copy.deepcopy(data) + for dat in new_data: + dat['src_shape'] = [dat['src_shape'][0] * factor, dat['src_shape'][1] * factor] + dat['dst_shape'] = [dat['dst_shape'][0] * factor, dat['dst_shape'][1] * factor] + dat['x'] = dat['x'] * factor + dat['y'] = dat['y'] * factor + return new_data + + +def draw_rectangles_from_data(data, draw_first=True): + dst_sz = get_roi(data, draw_first) + new_img = 255 * np.ones((dst_sz[3], dst_sz[2]), np.uint8) + if draw_first: + new_img = cv.rectangle(new_img, (- dst_sz[0], - dst_sz[1]), + (data[0]['dst_shape'][0] - dst_sz[0], data[0]['dst_shape'][1] - dst_sz[1]), + 128, thickness=10, lineType=cv.LINE_8) + for dat in data: + new_img = cv.polylines(img=new_img, pts=[get_vertices(np.array(dat['src_shape']) * dat['scale'], + dat['angle'], dat['x'] - dst_sz[0], + dat['y'] - dst_sz[1])], + isClosed=True, color=128, thickness=10) + new_img = cv.resize(new_img, None, fx=0.15, fy=0.15, interpolation=cv.INTER_AREA) + cv.imwrite('test.jpg', new_img) + + +def draw_images_from_data(data, draw_first=True): + dst_sz = get_roi(data, draw_first) + print(dst_sz) + blender = cv.detail_MultiBandBlender() + # blend_strength = 5 + # blend_width = np.sqrt(dst_sz[2] * dst_sz[3]) * blend_strength / 100 + blend_width = 10 + num_bands = np.log(blend_width) / np.log(2.) - 1. + print(num_bands) + blender.setNumBands(num_bands.astype(np.int32)) + blender.prepare(dst_sz) + if draw_first: + img = cv.imread('imgs/danube_10_pct/9.jpg').astype(np.int16) + mask = cv.imread('imgs/danube_10_pct/masks/mask_9.png', flags=cv.IMREAD_GRAYSCALE) + blender.feed(cv.UMat(img), cv.UMat(mask), (0, 0)) + for dat in data: + print(dat['src_name']) + warper = cv.PyRotationWarper('affine', dat['scale']) + img = cv.imread(f'imgs/danube_10_pct/{dat["src_name"]}').astype(np.int16) + corner, img = warper.warp(img, get_3x3_id(), compose_R_mat(dat['angle'], 1, 0, 0), + cv.INTER_LINEAR, cv.BORDER_REFLECT) + # cv.INTER_NEAREST, cv.BORDER_CONSTANT) + mask_path = pathlib.Path(f'imgs/danube_10_pct/masks/mask_{dat["src_name"]}'.replace('.jpg', '_cropped.jpg')) + mask_png = pathlib.Path(f'imgs/danube_10_pct/masks/mask_{dat["src_name"]}'.replace('.jpg', '.png')) + if mask_png.exists(): + mask = cv.imread(mask_png.as_posix(), flags=cv.IMREAD_GRAYSCALE) + elif mask_path.exists(): + mask = cv.imread(mask_path.as_posix(), flags=cv.IMREAD_GRAYSCALE) + else: + mask = cv.imread(f'imgs/danube_10_pct/masks/mask_{dat["src_name"]}', flags=cv.IMREAD_GRAYSCALE) + mask = cv.UMat(mask) + corner, mask = warper.warp(mask, get_3x3_id(), compose_R_mat(dat['angle'], 1, 0, 0), + cv.INTER_NEAREST, cv.BORDER_CONSTANT) + corner = (corner[0] + round(dat['x']), corner[1] + round(dat['y'])) + blender.feed(cv.UMat(img), mask, corner) + result, result_mask = blender.blend(None, None) + result = cv.resize(result, None, fx=0.15, fy=0.15, interpolation=cv.INTER_AREA) + result_mask = cv.resize(result_mask, None, fx=0.15, fy=0.15, interpolation=cv.INTER_AREA) + cv.imwrite('test_draw_images.png', result) + cv.imwrite('test_draw_images_mask.png', result_mask) + + +def connections_between_components(): + conn_1_2 = {'src_name': '42.jpg', 'src_shape': [1083, 624], + 'dst_name': '35.jpg', 'dst_shape': [891, 627], + 'angle': 14.68, 'scale': 1.0, + 'x': 715.0, 'y': 46.0} + conn_1_3 = {'src_name': '39.jpg', 'src_shape': [1121, 1352], + 'dst_name': '24.jpg', 'dst_shape': [1072, 633], + 'angle': 0.190, 'scale': 1.012, + 'x': -193.0, 'y': -1277.0} + conn_1_3_old = {'src_name': '39.jpg', 'src_shape': [1121, 1352], + 'dst_name': '24.jpg', 'dst_shape': [1072, 633], + 'angle': 0.0, 'scale': 1.00, + 'x': -183.0, 'y': -1260.0} + conn_1_4 = {'src_name': '25.jpg', 'src_shape': [977, 627], + 'dst_name': '36.jpg', 'dst_shape': [1045, 825], + 'angle': 0.0, 'scale': 0.997, + 'x': -95.0, 'y': -607.0} + conn_1_4_old = {'src_name': '25.jpg', 'src_shape': [977, 627], + 'dst_name': '36.jpg', 'dst_shape': [1045, 825], + 'angle': 0.0, 'scale': 1.0, + 'x': -96.0, 'y': -601.0} + conn_1_5 = {'src_name': '38.jpg', 'src_shape': [1715, 1083], + 'dst_name': '28.jpg', 'dst_shape': [1020, 627], + 'angle': 0.0, 'scale': 1.0065, + 'x': -665.0, 'y': -1059.0} + conn_1_5_old = {'src_name': '38.jpg', 'src_shape': [1715, 1083], + 'dst_name': '28.jpg', 'dst_shape': [1020, 627], + 'angle': 0.0, 'scale': 1.0, + 'x': -660.0, 'y': -1051.0} + return [conn_1_2, conn_1_3, conn_1_4, conn_1_5] + + +def invert_coord_frame(dat): + xr, yr = rotate_vec((dat['x'] / dat['scale'], dat['y'] / dat['scale']), dat['angle'], (0, 0)) + new_dat = {'src_name': dat['dst_name'], 'src_shape': dat['dst_shape'], + 'dst_name': dat['src_name'], 'dst_shape': dat['src_shape'], + 'angle': dat['angle'], 'scale': 1 / dat['scale'], + 'x': -xr, 'y': -yr} + return new_dat + + +def create_matches_data(): + path = 'imgs/danube_10_pct' + comp_1 = [f'{path}/{i}.jpg' for i in range(9, 36)] + comp_2 = [f'{path}/{i}.jpg' for i in range(42, 51)] + comp_3 = [f'{path}/39.jpg', f'{path}/40.jpg', f'{path}/41.jpg'] + comp_4 = [f'{path}/36.jpg', f'{path}/37.jpg'] + comp_5 = [f'{path}/38.jpg'] + all_matches = [match_sift_features(eval(f'comp_{i}'), match_conf=0.4) for i in range(1, 5)] + match_details = [get_match_details(eval(f'comp_{i+1}'), all_matches[i]) for i in range(0, 4)] + components = [{'component': i+1, 'data': match_details[i]} for i in range(0, 4)] + with open('stitch_data.json', 'w') as fp: + json.dump(components, fp) + + +def collect_all_components(components): + conn = connections_between_components() + connect_1_2 = invert_coord_frame(conn[0]) + comp_1_2 = components[0]['data'] + [connect_1_2] + components[1]['data'] + comp_1_2_abs = transform_data_relative_to_first(comp_1_2) + comp_1_3 = [invert_coord_frame(comp_1_2_abs[14]), invert_coord_frame(conn[1])] + components[2]['data'] + comp_1_3_abs = transform_data_relative_to_first(comp_1_3) + comp_1_4 = [invert_coord_frame(comp_1_2_abs[15]), conn[2]] + components[3]['data'] + comp_1_4_abs = transform_data_relative_to_first(comp_1_4) + comp_1_5 = [invert_coord_frame(comp_1_2_abs[18]), invert_coord_frame(conn[3])] + comp_1_5_abs = transform_data_relative_to_first(comp_1_5) + all_comp = comp_1_2_abs + comp_1_3_abs[1:] + comp_1_4_abs[1:] + comp_1_5_abs[1:] + return all_comp if __name__ == '__main__': @@ -374,54 +651,16 @@ if __name__ == '__main__': debug_mode = True try: if debug_mode: - # test_scale = ['imgs/danube_10_pct/13.jpg', 'imgs/danube_10_pct/14_scaled_down.jpg'] - all_matches = [match_sift_features(eval(f'comp_{i}'), match_conf=0.4) for i in range(1, 5)] - match_details = [get_match_details(eval(f'comp_{i+1}'), all_matches[i]) for i in range(0, 4)] - components = [{'component': i+1, 'data': match_details[i]} for i in range(0, 4)] - for comp in components: - print(comp) - with open('stitch_data.json', 'w') as fp: - json.dump(components, fp) - # with open('stitch_data.json', 'r') as fp: - # components = json.load(fp) - # H_2 = feature_testing(comp_2, 2, match_conf=0.4) - # H_3 = feature_testing(comp_3, 3, match_conf=0.4) - # H_4 = feature_testing(comp_4, 4, match_conf=0.4) - # conf_1 = feature_testing(comp_1, 1, match_conf=0.8) - # conf_2 = feature_testing(comp_2, 2, match_conf=0.8) - # conf_3 = feature_testing(comp_3, 3, match_conf=0.8) - # conf_4 = feature_testing(comp_4, 4, match_conf=0.8) - # with open('confs_match_conf_0.8.csv', 'w') as file: - # json.dump([conf_1, conf_2, conf_3, conf_4], file) - # confs = [] - # for i in range(2, 9): - # with open(f'confs_match_conf_0.{i}.csv', 'r') as file: - # lis = json.load(file) - # flat_lis = [item for sublist in lis for item in sublist] - # avg_conf = np.mean(flat_lis, axis=0) - # confs.append(avg_conf) - # plt.plot(np.arange(0.2, 0.8, 0.1), confs) - # plt.legend(['AKAZE', 'BRISK', 'KAZE', 'ORB', 'SIFT']) - # plt.title('Average confidence for different match_conf') - # plt.savefig('avg_conf.png') - # orb = cv.ORB.create() - # crop1 = imgs[0][0:2765, 1920:3246] - # crop2 = imgs[1][0:3089, 0:1170] - # imgs = [crop1, crop2] - # debug_stitching_pipeline(imgs, img_names) - # kp1, des1 = orb.detectAndCompute(imgs[0], None) - # kp2, des2 = orb.detectAndCompute(imgs[1], None) - # feat1 = cv.detail.computeImageFeatures2(orb, imgs[0]) - # feat2 = cv.detail.computeImageFeatures2(orb, imgs[1]) - # afm = cv.detail_AffineBestOf2NearestMatcher.create() - # matches_info = afm.apply(feat1, feat2) - # matches = matches_info.getMatches() - # matches = sorted(matches, key=lambda x: x.distance) - # img = cv.drawMatches(imgs[0], kp1, imgs[1], kp2, matches[:20], None) - # cv.imwrite('imgs_out/matches3.jpg', img) + # create_matches_data() + with open('stitch_data.json', 'r') as fp: + components = json.load(fp) + all_comp = collect_all_components(components) + # with open('10pct_stitch_data.json', 'w') as fp: + # json.dump(all_comp, fp) + draw_images_from_data(all_comp) else: - imgs = [cv.imread(name) for name in img_names] - result = full_stitching_pipeline(imgs, img_names) + imgs = [cv.imread(name) for name in comp_2] + result = full_stitching_pipeline(imgs, comp_2) res_name = 'area.jpg' cv.imwrite(res_name, result) except SystemExit: