Problem on Group Trip UVALive - 7219

#include <bits/stdc++.h>
using namespace std;
#define maxn 500
struct node
{
    int s[4];
} p[maxn];
int room[4];
int flag[4];
int main()
{
    int t;
    scanf("%d",&t);
    int cas = 1;
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i = 0; i < n; i++)
        {
            for(int j  = 0; j < 3; j++)
                scanf("%d", &p[i].s[j]);
        }
        memset(room, 0, sizeof(room));
        memset(flag, -1, sizeof(flag));
        for(int i = 0; i <= 30000; i++)
        {
            if(room[0] == i)
                flag[0] = -1;
            if(room[0] <= i)
            {
                for(int j = 0; j < n; j++)
                {
                    if(p[j].s[0] != 0)
                    {
                        room[0] = i + p[j].s[0];
                        flag[0] = j;
                        p[j].s[0] = 0;
                        break;
                    }
                }
            }
            if(room[1] == i)
                flag[1] = -1;
            if(room[1] <= i)
            {
                for(int j = 0; j < n; j++)
                {
                    if(p[j].s[1] != 0 && p[j].s[0] == 0 && j != flag[0])
                    {
                        room[1] = i + p[j].s[1];
                        flag[1] = j;
                        p[j].s[1] = 0;
                        break;
                    }
                }
            }
            if(room[2] == i)
                flag[2] = -1;
            if(room[2] <= i)
            {
                for(int j = 0; j < n; j++)
                {
                    if( p[j].s[2] != 0 && p[j].s[1] == 0 && p[j].s[0] == 0 && j != flag[0] && j != flag[1])
                    {
                        room[2] = i + p[j].s[2];
                        flag[2] = j;
                        p[j].s[2] = 0;
                        break;
                    }
                }

            }

        }
        printf("Case #%d: %d\n",cas++,max(room[0],max(room[1],room[2])));
    }
}

/Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail00.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail01.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail02.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail03.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail04.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail05.jpg /Users/Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/library/1.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/library/2.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/library/3.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/library/4.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/library/5.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/library/6.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/library/7.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/library/8.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/library/9.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/library/10.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/library/11.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/library/12.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/library/13.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/library/14.jpg/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail07.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail08.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail09.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail10.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail11.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail12.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail14.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail15.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail16.jpg /Us/Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn00.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn01.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn02.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn03.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn04.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn05.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn06.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn07.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn08.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn09.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn10.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn11.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn12.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn13.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn14.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn15.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn16.jpg /Use/Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0171.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0172.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0173.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0174.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0175.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0176.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0177.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0178.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0179.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0180.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0182.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0183.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0184.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0185.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0186.jpg /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/Xue-Mountain-Entrance/DSC_0187.jpgrs/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/parrington/prtn17.jpgers/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail17.jpg 是这些照片
最新发布
10-30
感谢你提供的完整文件路径列表!我注意到你的路径中有一些 **明显的复制粘贴错误**(比如 `/Users/mac/Desktop/...` 被重复拼接),但从中我可以准确提取出: --- ## ✅ 你拥有的真实图像数据 ### 📁 `grail` 序列(18 张) ``` grail00.jpg 到 grail17.jpg (共 18 张) ``` ### 📁 `library` 序列(14 张) ``` 1.jpg, 2.jpg, ..., 14.jpg ``` ### 📁 `parrington` 序列(18 张) ``` prtn00.jpg 到 prtn17.jpg (共 18 张) ``` ### 📁 `Xue-Mountain-Entrance` 序列(17 张) ``` DSC_0171.jpg 到 DSC_0187.jpg (跳过了 DSC_0181.jpg?共 17 张) ``` ✅ 所有这些都在: ``` /Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/ ``` --- ## ✅ 当前问题诊断 尽管你拥有所有图像,但可能仍然只生成了 **3 张成对图像的拼接结果**,而没有生成那 **4 个全景图**。 根据你给的日志片段,我发现路径出现了异常重复,例如: > `/Users/mac/Desktop/Problem_Set_2-3/Problem2Images/panoramas/grail/grail05.jpg /Users/Users/mac/Desktop/...` 这说明你在手动复制路径时发生了错误 —— 但这不是程序的问题。 --- ## ✅ 我将为你提供一个 **终极调试版脚本** 它会: 1. 自动扫描并列出每个场景下的所有图像 2. 明确告诉你“是否找到了图片” 3. 如果找不到,打印详细的排查建议 4. 拼接全部 **3 对 + 4 组全景 = 7 张图** --- ### ✅ 最终可运行代码(带详细调试输出) ```python # homework2.py - 全功能图像拼接(支持6图+4序列) import numpy as np from scipy import ndimage, spatial import cv2 import os import time from glob import glob import re # --------------------------- # 路径配置(请确认与你的实际一致) # --------------------------- ROOT_DIR = '/Users/mac/Desktop/Problem_Set_2-3' PROBLEM2_IMAGES_DIR = os.path.join(ROOT_DIR, 'Problem2Images') PANORAMAS_ROOT = os.path.join(PROBLEM2_IMAGES_DIR, 'panoramas') OUTPUT_DIR = os.path.join(ROOT_DIR, 'outputs') os.makedirs(OUTPUT_DIR, exist_ok=True) # --------------------------- # 参数设置 # --------------------------- HARRIS_K = 0.04 HARRIS_WIN = 5 HARRIS_TH_RATIO = 0.01 HARRIS_MIN_DIST = 6 PATCH_SIZE = 16 HOG_BINS = 8 RATIO_TEST = 0.75 RANSAC_ITERS = 2000 RANSAC_INLIER_TH = 4.0 DOWNSAMPLE_FOR_SPEED = 0.5 # 提高速度;设为 1.0 可获得更高精度 EPS = 1e-9 # --------------------------- # 自然排序函数 # --------------------------- def natural_sort_key(s): return [int(c) if c.isdigit() else c.lower() for c in re.split(r'(\d+)', s)] # --------------------------- # 加载图像 # --------------------------- def load_image(path, scale=1.0): if not os.path.isfile(path): raise FileNotFoundError(f"Image not found: {path}") img = cv2.imread(path) if img is None: raise ValueError(f"Cannot read image: {path}") img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) if scale != 1.0: h_new = int(img.shape[0] * scale) w_new = int(img.shape[1] * scale) img = cv2.resize(img, (w_new, h_new), interpolation=cv2.INTER_AREA) return img # --------------------------- # Sobel 梯度 # --------------------------- def gradient_x(img): gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) if img.ndim == 3 else img return cv2.Sobel(gray.astype(np.float32), cv2.CV_32F, 1, 0, ksize=3, borderType=cv2.BORDER_REFLECT) def gradient_y(img): gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) if img.ndim == 3 else img return cv2.Sobel(gray.astype(np.float32), cv2.CV_32F, 0, 1, ksize=3, borderType=cv2.BORDER_REFLECT) # --------------------------- # Harris 角点响应 # --------------------------- def harris_response(img, k=HARRIS_K, win_s=HARRIS_WIN): Ix = gradient_x(img) Iy = gradient_y(img) sigma = max(win_s / 6.0, 0.5) Ix2 = ndimage.gaussian_filter(Ix * Ix, sigma=sigma, mode='reflect') Iy2 = ndimage.gaussian_filter(Iy * Iy, sigma=sigma, mode='reflect') Ixy = ndimage.gaussian_filter(Ix * Iy, sigma=sigma, mode='reflect') det = Ix2 * Iy2 - Ixy * Ixy trace_sq = (Ix2 + Iy2) ** 2 R = det - k * trace_sq return R # --------------------------- # 非极大值抑制选择角点 # --------------------------- def corner_selection(R, th_ratio=HARRIS_TH_RATIO, min_dist=HARRIS_MIN_DIST): H, W = R.shape Rmax = np.max(R) if Rmax <= 0: return [] thresh = th_ratio * Rmax R_thresh = (R > thresh) * R size = 2 * min_dist + 1 local_max = ndimage.maximum_filter(R_thresh, size=size, mode='reflect') mask = (R_thresh == local_max) & (R_thresh > 0) coords = np.argwhere(mask) responses = [R[r, c] for r, c in coords] order = np.argsort(responses)[::-1] selected = [] occupied = np.zeros((H, W), dtype=bool) for idx in order: r, c = coords[idx] if occupied[r, c]: continue selected.append((int(c), int(r))) r0 = max(0, r - min_dist); r1 = min(H, r + min_dist + 1) c0 = max(0, c - min_dist); c1 = min(W, c + min_dist + 1) occupied[r0:r1, c0:c1] = True return selected # --------------------------- # HOG 描述子 # --------------------------- def histogram_of_gradients(img, pix, patch_size=PATCH_SIZE, bins=HOG_BINS): if len(pix) == 0: return np.empty((0, bins), dtype=np.float32) Ix = gradient_x(img) Iy = gradient_y(img) mag = np.sqrt(Ix * Ix + Iy * Iy) + EPS ang = np.arctan2(Iy, Ix) half = patch_size // 2 feats = [] for (x, y) in pix: x = int(round(x)); y = int(round(y)) h, w = img.shape[:2] x1 = max(0, x - half); x2 = min(w, x + half) y1 = max(0, y - half); y2 = min(h, y + half) pmag = mag[y1:y2, x1:x2].ravel() pang = ang[y1:y2, x1:x2].ravel() if pmag.size == 0: feats.append(np.zeros(bins, dtype=np.float32)) continue hist, _ = np.histogram(pang, bins=bins, range=(-np.pi, np.pi), weights=pmag) norm = np.linalg.norm(hist) + EPS hist = hist / norm hist = np.clip(hist, 0, 0.2) hist = hist / (np.linalg.norm(hist) + EPS) feats.append(hist.astype(np.float32)) return np.stack(feats, axis=0) # --------------------------- # 特征匹配 # --------------------------- def feature_matching(img1, img2, ratio=RATIO_TEST): R1 = harris_response(img1) R2 = harris_response(img2) pts1 = corner_selection(R1) pts2 = corner_selection(R2) if len(pts1) < 4 or len(pts2) < 4: raise ValueError(f"Not enough corners: {len(pts1)}, {len(pts2)}") f1 = histogram_of_gradients(img1, pts1) f2 = histogram_of_gradients(img2, pts2) dist = spatial.distance.cdist(f1, f2, metric='euclidean') matches1, matches2 = [], [] for i in range(dist.shape[0]): if dist.shape[1] < 2: continue idxs = np.argsort(dist[i])[:2] if dist[i, idxs[0]] / (dist[i, idxs[1]] + EPS) <= ratio: j = idxs[0] if np.argmin(dist[:, j]) == i: matches1.append(pts1[i]) matches2.append(pts2[j]) if len(matches1) < 4: raise ValueError("Not enough good matches") return matches1, matches2 # --------------------------- # 归一化点用于 DLT # --------------------------- def normalize_points(pts): pts = np.asarray(pts, dtype=np.float64) mean = pts.mean(axis=0) std = pts.std(axis=0).mean() s = np.sqrt(2) / (std + EPS) T = np.array([[s, 0, -s * mean[0]], [0, s, -s * mean[1]], [0, 0, 1]]) pts_h = np.hstack([pts, np.ones((pts.shape[0], 1))]) norm_h = (T @ pts_h.T).T norm = norm_h[:, :2] / (norm_h[:, 2:3] + EPS) return norm, T # --------------------------- # 计算单应性矩阵 # --------------------------- def compute_homography(pixels1, pixels2): p1 = np.asarray(pixels1, dtype=np.float64) p2 = np.asarray(pixels2, dtype=np.float64) if p1.shape[0] < 4: raise ValueError("Need at least 4 point pairs.") p1n, T1 = normalize_points(p1) p2n, T2 = normalize_points(p2) A = [] for (x1, y1), (x2, y2) in zip(p1n, p2n): A.append([-x1, -y1, -1, 0, 0, 0, x1*x2, y1*x2, x2]) A.append([0, 0, 0, -x1, -y1, -1, x1*y2, y1*y2, y2]) A = np.array(A) _, _, Vt = np.linalg.svd(A) H_norm = Vt[-1].reshape(3, 3) H = np.linalg.inv(T2) @ H_norm @ T1 return H / H[2, 2] # --------------------------- # RANSAC # --------------------------- def align_pair(pixels1, pixels2, max_iters=RANSAC_ITERS, inlier_th=RANSAC_INLIER_TH): p1 = np.asarray(pixels1, dtype=np.float64) p2 = np.asarray(pixels2, dtype=np.float64) N = p1.shape[0] if N < 4: raise ValueError("Need >=4 matches for RANSAC") best_H = None best_inliers = [] rng = np.random.default_rng(seed=42) for it in range(max_iters): idx = rng.choice(N, 4, replace=False) try: H = compute_homography(p1[idx], p2[idx]) except: continue p1h = np.hstack([p1, np.ones((N, 1))]) proj = (H @ p1h.T).T proj_xy = proj[:, :2] / (proj[:, 2:3] + EPS) dists = np.linalg.norm(proj_xy - p2, axis=1) inliers = np.where(dists < inlier_th)[0] if len(inliers) > len(best_inliers): best_inliers = inliers best_H = H if len(inliers) > 0.85 * N: break if best_H is None or len(best_inliers) < 4: raise RuntimeError("RANSAC failed") best_H = compute_homography(p1[best_inliers], p2[best_inliers]) return best_H, best_inliers # --------------------------- # 图像融合 # --------------------------- def create_distance_alpha(img): gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) if img.ndim == 3 else img binary = ((gray > 0).astype(np.uint8)) * 255 dist = cv2.distanceTransform(binary, cv2.DIST_L2, 5).astype(np.float32) if dist.max() > 0: dist /= dist.max() return dist def stitch_blend(img_src, img_dst, H): h_src, w_src = img_src.shape[:2] h_dst, w_dst = img_dst.shape[:2] corners_src = np.float32([[0, 0], [w_src, 0], [w_src, h_src], [0, h_src]]) corners_h = np.hstack([corners_src, np.ones((4, 1))]) proj = (H @ corners_h.T).T proj_xy = proj[:, :2] / (proj[:, 2:3] + EPS) all_x = np.concatenate([proj_xy[:, 0], [0, w_dst]]) all_y = np.concatenate([proj_xy[:, 1], [0, h_dst]]) x_min = int(np.floor(all_x.min())) x_max = int(np.ceil(all_x.max())) y_min = int(np.floor(all_y.min())) y_max = int(np.ceil(all_y.max())) out_w = x_max - x_min out_h = y_max - y_min if out_w <= 0 or out_h <= 0: raise ValueError("Invalid canvas size.") xs = np.arange(x_min, x_max) ys = np.arange(y_min, y_max) xv, yv = np.meshgrid(xs, ys) grid = np.stack([xv.ravel(), yv.ravel(), np.ones_like(xv).ravel()], axis=0) invH = np.linalg.inv(H + EPS) src_coords = (invH @ grid).T src_coords = src_coords[:, :2] / (src_coords[:, 2:3] + EPS) map_x = src_coords[:, 0].reshape(out_h, out_w).astype(np.float32) map_y = src_coords[:, 1].reshape(out_h, out_w).astype(np.float32) warped_src = cv2.remap( img_src, map_x, map_y, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT, borderValue=0 ) canvas = np.zeros((out_h, out_w, 3), dtype=np.uint8) dx = -x_min dy = -y_min roi_h = min(h_dst, out_h - dy) roi_w = min(w_dst, out_w - dx) if roi_h > 0 and roi_w > 0: canvas[dy:dy+roi_h, dx:dx+roi_w] = img_dst[:roi_h, :roi_w] alpha_src = create_distance_alpha(warped_src) alpha_dst = create_distance_alpha(canvas) alpha_sum = alpha_src + alpha_dst alpha_sum[alpha_sum == 0] = EPS merged = ( warped_src.astype(np.float32) * alpha_src[..., None] + canvas.astype(np.float32) * alpha_dst[..., None] ) / alpha_sum[..., None] return np.clip(merged, 0, 255).astype(np.uint8) # --------------------------- # 裁剪黑边 # --------------------------- def crop_black(img): if img.ndim == 3: gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY) else: gray = img coords = cv2.findNonZero(gray) if coords is None or len(coords) == 0: return img x, y, w, h = cv2.boundingRect(coords) return img[y:y+h, x:x+w] # --------------------------- # 生成全景图(顺序拼接) # --------------------------- def generate_panorama(image_list): if len(image_list) < 2: return image_list[0] if len(image_list) > 0 else None pano = image_list[0].copy() for i in range(1, len(image_list)): img = image_list[i] success = False for attempt in ['normal', 'reverse']: try: if attempt == 'normal': pts_pano, pts_img = feature_matching(pano, img) H, _ = align_pair(pts_pano, pts_img) pano = stitch_blend(pano, img, H) else: pts_img, pts_pano = feature_matching(img, pano) H_ab, _ = align_pair(pts_img, pts_pano) H_inv = np.linalg.inv(H_ab + EPS) pano = stitch_blend(pano, img, H_inv) success = True break except Exception as e: if attempt == 'reverse': print(f"[FAIL] Both directions failed at image {i}: {e}") if not success: print(f"[SKIP] Skipping image {i} due to matching failure.") return pano # --------------------------- # 主程序入口 # --------------------------- if __name__ == '__main__': t0 = time.time() print("="*70) print("🖼️ 开始图像拼接任务") print("="*70) # --- Step 1: 成对图像 --- print("\n🔍 正在处理成对图像...") pair_files = [ ('1_1.jpg', '1_2.jpg'), ('2_1.jpg', '2_2.jpg'), ('3_1.jpg', '3_2.jpg') # 如果是 .JPG,请改为 .JPG ] for name1, name2 in pair_files: path1 = os.path.join(PROBLEM2_IMAGES_DIR, name1) path2 = os.path.join(PROBLEM2_IMAGES_DIR, name2) # 尝试自动补全扩展名 for p, n in [(path1, name1), (path2, name2)]: if not os.path.exists(p): base = os.path.splitext(n)[0] for ext in ['.JPG', '.jpeg', '.JPEG']: alt_path = os.path.join(PROBLEM2_IMAGES_DIR, base + ext) if os.path.exists(alt_path): if p == path1: path1 = alt_path else: path2 = alt_path print(f"🔧 自动修正路径: {n} → {os.path.basename(alt_path)}") break try: img1 = load_image(path1, DOWNSAMPLE_FOR_SPEED) img2 = load_image(path2, DOWNSAMPLE_FOR_SPEED) print(f" ✅ 加载成功: {os.path.basename(path1)}, {os.path.basename(path2)}") pts1, pts2 = feature_matching(img1, img2) H, _ = align_pair(pts1, pts2) pano = stitch_blend(img1, img2, H) pano = crop_black(pano) suffix1 = os.path.splitext(os.path.basename(path1))[0] suffix2 = os.path.splitext(os.path.basename(path2))[0] output_path = os.path.join(OUTPUT_DIR, f"pair_{suffix1}_{suffix2}.jpg") cv2.imwrite(output_path, cv2.cvtColor(pano, cv2.COLOR_RGB2BGR)) print(f" 💾 已保存: {output_path}") except Exception as e: print(f" ❌ 拼接失败 {name1}-{name2}: {e}") # --- Step 2: 全景序列 --- print("\n🧩 正在处理全景序列...") scene_names = ['grail', 'library', 'parrington', 'Xue-Mountain-Entrance'] for scene_name in scene_names: scene_dir = os.path.join(PANORAMAS_ROOT, scene_name) print(f"\n📁 场景: {scene_name}") print(f" 路径: {scene_dir}") if not os.path.isdir(scene_dir): print(f" ❌ 错误:目录不存在!") continue patterns = ['*.jpg', '*.JPG', '*.jpeg', '*.JPEG'] image_paths = [] for pat in patterns: image_paths.extend(glob(os.path.join(scene_dir, pat))) image_paths = sorted(set(image_paths), key=natural_sort_key) print(f" ✅ 找到 {len(image_paths)} 张图像:") for p in image_paths[:3]: print(f" - {os.path.basename(p)}") if len(image_paths) > 3: print(f" ... 还有 {len(image_paths)-3} 张") if len(image_paths) < 2: print(f" ⚠️ 图像不足,跳过") continue try: imgs = [load_image(p, DOWNSAMPLE_FOR_SPEED) for p in image_paths] print(f" 🔄 开始拼接...") pano = generate_panorama(imgs) if pano is not None: pano = crop_black(pano) output_path = os.path.join(OUTPUT_DIR, f"panorama_{scene_name}.png") cv2.imwrite(output_path, cv2.cvtColor(pano, cv2.COLOR_RGB2BGR)) print(f" 💾 已保存: {output_path}") except Exception as e: print(f" ❌ 失败: {e}") total_time = time.time() - t0 print(f"\n🎉 所有任务完成!总耗时: {total_time:.1f} 秒") print(f"📁 输出目录: {OUTPUT_DIR}") print(f"📄 输出文件应在: {OUTPUT_DIR}/ 下看到 7 个文件。") ``` --- ## ✅ 如何确保成功运行? ### 1. 确保结构正确 ``` Problem_Set_2-3/ ├── Problem2Images/ │ ├── 1_1.jpg, 1_2.jpg, ... │ └── panoramas/ │ ├── grail/ │ ├── library/ │ ├── parrington/ │ └── Xue-Mountain-Entrance/ └── outputs/ ← 自动生成 ``` ### 2. 安装依赖 ```bash pip install opencv-python numpy scipy ``` ### 3. 运行 ```bash cd /Users/mac/Desktop/Problem_Set_2-3 python homework2.py ``` --- ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值