动态规划最佳缝合线查找(Image Stitching 3)

本文介绍了一种用于图像拼接的最优缝合线查找算法,该算法通过动态规划方法找到能量最小的路径,解决了传统方法无法找到全局最优解的问题。文章详细解释了算法原理,并给出了C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 存在的问题

之前最佳缝合线查找存在一定的问题:查找不到最小能量和的缝合线路径。举一个简单的例子如图1.1所示:

图1.1

如果从上至下求和选择最小能量函数,则选择的路径为蓝色,但是蓝色路径不是最小能量和路径。因为从上至下只是考虑了下一步对于上一步的能量和最小,但是没有考虑到全局的能量和最小。上图中的最小能量和路径应该为红色。因此需要有一个新的思路求取最佳缝合线。

2. 新的思路

(也是OpenCV中缝合线查找思想):我们反过来对最小能量做选择,不在从多个像素中选择一个作为缝合线的延伸方向,而是从多个缝合线中选择一条最优的来连接当前点。思路如图2.1所示

图2.1

如果存在3x3的能量矩阵,把第一行能量值作为三条最小能量和路径,那么能量化去向可以表示为如图2.2所示。

图2.2

算法步骤:

     (1) 初始化。第一行作为第一步的最小能量和路径;

     (2) 最小能量和迭代。依次遍历每一行,得到最小能量和路径来源的位置:左上、顶上、右上。在遍历的时候需要记录抵达每一行每一列的最小能量和向量,以及抵达每行每列路径来源的位置。假设左上(1)、顶上(2)、右上(3),供回溯时使用。

     (3) 缝合线回溯。最后通过记录来源的位置矩阵从最后一行回溯缝合线。在X方向上,如果是1则减1,如果是3则加1,如果是2则不变,Y方向上减1。

3. 实验结果

图3.1 重叠区域
图3.2 最佳缝合线与不同终点缝合线
图3.3 缝合线诱导融合

4. C++代码

void OptimalSeam::DP_find_seam(Mat I1, Mat I2, vector<int>& seam_paths)
{
	
	Mat_<float> E;
    // 能量函数的计算,参考image stitching 2
	energy_function(I1, I2, E);
	
	E.convertTo(E, CV_32F);
	Mat_<uchar> control = Mat::zeros(E.size(), CV_8U); 
	Mat_<float> sum_cost = E.rowRange(0, 1); 

	for (int i = 1; i < E.rows; i++) {
		float* E_ptr = E.ptr<float>(i);
		Mat_<float> cost_tmp = sum_cost.clone();
		for (int j = 0; j < E.cols; j++) {
			float min_e = sum_cost(0, j);
			int c_x = 2; 
			if (j > 0 && min_e > sum_cost(0, j - 1)) {
				min_e = sum_cost(0, j - 1);
				c_x = 1;
			}
			if (j < E.cols - 1 && min_e > sum_cost(0, j + 1)) {
				min_e = sum_cost(0, j + 1);
				c_x = 3;
			}
			
			cost_tmp(0, j) = min_e + E_ptr[j];
			control(i, j) = c_x;
		}
		sum_cost = cost_tmp;
	}


	float minE = sum_cost(0, 0);
	int end_x = 0;
	for (int i = 0; i < sum_cost.cols; i++) {
		if (sum_cost(0, i) < minE) {
			end_x = i;
		}
	}
	
	Point current_p(end_x, control.rows - 1), top_p(end_x, control.rows - 1);
	seam_paths.push_back(end_x);
	for (; top_p.y != 0; seam_paths.push_back(top_p.x)) {
		if (control(current_p) == 1) top_p.x--;
		else if (control(current_p) == 3) top_p.x++;
		top_p.y--;
		current_p = top_p;
	}
	reverse(seam_paths.begin(), seam_paths.end());

}

5. 参考

https://github.com/xitu/gold-miner/blob/master/TODO1/real-world-dynamic-programming-seam-carving.md

https://medium.com/swlh/real-world-dynamic-programming-seam-carving-9d11c5b0bfca  原文

### 关于最优缝合线算法的实现与资料 #### 图像拼接中的最佳缝合线图像拼接领域,最佳缝合线的选择对于减少拼接痕迹至关重要。一种常见的方法是基于图切割(Graph Cut)技术来寻找最优路径[^4]。这种方法通过构建一个加权无向图 \( G=<V, E> \),其中节点表示像素位置,边权重反映相邻像素之间的相似度或能量函数值。最终目标是最小化全局能量函数,从而找到一条能够平衡视觉效果和平滑性的缝合线。 以下是利用 Graph Cut 寻找最佳缝合线的一个简化 Python 实现: ```python import numpy as np from scipy.sparse import csr_matrix from scipy.optimize import linprog def graph_cut_seam(image_left, image_right): """ 使用 Graph Cut 找到两幅图像间的最佳缝合线 :param image_left: 左侧输入图像 (H x W x 3) :param image_right: 右侧输入图像 (H x W x 3) :return: 最佳缝合线的位置数组 (长度为 H 的一维数组) """ height, width, _ = image_left.shape seam = [] # 构建能量矩阵 energy_map = compute_energy(image_left, image_right) # 初始化图结构 V = height * width edges = [] for y in range(height): for x in range(width): current_node = y * width + x # 添加水平连接 if x < width - 1: weight_horizontal = abs(energy_map[y][x] - energy_map[y][x+1]) edges.append((current_node, current_node + 1, weight_horizontal)) # 添加垂直连接 if y < height - 1: weight_vertical = abs(energy_map[y][x] - energy_map[y+1][x]) edges.append((current_node, current_node + width, weight_vertical)) # 将边缘转换成稀疏矩阵形式并求解 min-cut source_nodes, target_nodes, weights = zip(*edges) adjacency_matrix = csr_matrix((weights, (source_nodes, target_nodes)), shape=(V, V)) result = linprog(c=np.ones(V), A_ub=-adjacency_matrix.T, b_ub=None, bounds=(0, None)).x.reshape((height, width)) # 提取缝合线 for row in range(height): col = int(np.argmax(result[row])) seam.append(col) return np.array(seam) def compute_energy(img_l, img_r): """计算两个图像能量差异""" diff = np.abs(img_l.astype(float) - img_r.astype(float)) / 255. return np.sum(diff, axis=2).astype(float) ``` 上述代码展示了如何定义能量函数以及使用线性规划工具解决最小割问题。实际应用中可能还需要考虑更多约束条件以优化性能。 #### 开源资源推荐 除了自研外,《全景图像拼接关键技术研究》提供了另一种视角下的解决方案[^1]。该文中提到的方法侧重实验验证,并对比了多种现有技术的效果。此外,在 OpenCV 官方文档及其社区贡献项目中也能发现大量有关图像处理的具体案例[^3]。例如官方教程详细介绍了基础操作流程,包括特征匹配、变换估计直至最后一步融合阶段的操作指南。 #### 学术论文建议阅读清单 针对深入理解此主题的需求,可参考如下几篇经典文献: - **《Image Stitching Using Graph Cuts》**:首次提出将图形模型应用于图像拼接任务的经典之作。 - **《A Comparative Study of Image Blending Techniques》**:全面比较了几种主流混合策略优劣的文章。 - **《Graph-Based Parallel Large Scale Structure from Motion》**[^2]虽然主要讨论大规模三维重建框架设计思路,但也间接涉及到了一些相关内容值得借鉴学习之处。 ---
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值