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

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  原文

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值