算法导论 接缝裁剪
2014-12-24 19:53
169 查看
给定一副彩色图像,它由一个mxn的像素数组A[1..m,1..n]构成,每个像素是一个红绿蓝(RGB)亮度的三元组。假定我们希望轻度压缩这幅图像。具体地,我们希望从每一行中删除一个像素,使得图像变窄一个像素。但为了避免影响视觉效果,我们要求相邻两行中删除的像素必须位于同一列或相邻列。也就是说,删除的像素构成从顶端行到底端行的一条“接缝”(seam),相邻像素均在垂直或对角线方向上相邻。
a.证明:可能的接缝数量是m的指数函数,假定n>1.
第一行有n种可能选取像素点方式,第二到m行中每行有2-3种可能选中A[i][j-1],A[i][j],A[i][j+1].(j=1 or j=n时,是2种可能),所以总共有至少大于n*2^(m-1).
b 假定现在对每个像素A[i,j]我们都已计算出一个实型的“破坏度”d[i,j],表示删除像素A[i,j]对图像可视效果的破坏程度。直观地,一个像素的破坏度越低,它与相邻像素的相似度越高。再假定一条接缝的破坏度定义为包含的响度的破坏度之和。设计算法,寻找破坏度最低的接缝。分析算法的时间复杂度。
思考分析:按照要求需要删除的像素是同一列或相邻列。那么就可能删除A[i-1][j-1],A[i-1][j],A[i-1][j+1]之中的任意一个像素点。所以可得递归式:A[i][j]=d[i][j]+min{A[i-1][j-1],A[i-1][j],A[i-1][j+1]}.
代码如下:
[cpp] view
plaincopyprint?
#include <iostream>
using namespace std;
#define n 6//自定义数组行
#define m 5//自定义数组列
void OP_SEQUENCE(int **A,int i,int j);//i行j列;
int Min(int **A,int i,int j)
{
int temp=0;
if (j==1)
{
temp=A[i-1][j]>A[i-1][j+1]?A[i-1][j+1]:A[i-1][j];
}
else if (j==m)
{
temp=A[i-1][j]>A[i-1][j-1]?A[i-1][j-1]:A[i-1][j];
}
else
{
if (A[i-1][j]>A[i-1][j-1])
{
temp=A[i-1][j-1];
if (A[i-1][j-1]>A[i-1][j+1])
{
temp=A[i-1][j+1];
}
}
else
{
temp=A[i-1][j];
if (A[i-1][j]>A[i-1][j+1])
{
temp=A[i-1][j+1];
}
}
}
return temp;
}
void seam_carving(int **d)
{
int **A,i;//二维数组A表示破坏度之和。
A=new int*[n+1];
for ( i=0;i<=n;i++)
{
A[i]=new int[m+1];
}
for ( i=1;i<=m;i++)
{
A[1][i]=d[1][i];
}
for ( i=2;i<=n;i++)
{
for (int j=1;j<=m;j++)
{
A[i][j]=d[i][j]+Min(A,i,j);//递推式
}
}
int MIN=0x7fffffff,t=0;
for (i=1;i<=m;i++)
{
if(A
[i]<MIN)
{
MIN=A
[i];
t=i;
}
}
cout<<"MIN破坏点之和="<<MIN<<endl;
OP_SEQUENCE(A,n,t);
for ( i = 0; i <=m; i++)
delete[] A[i];
delete[] A;
}
void OP_SEQUENCE(int **A,int i,int j)//i行j列
{//输出一条接缝
int T;
if (i==0)return;
else
{
if (j==n)
{
T=A[i][j]>A[i][j-1]?j-1:j;
}
else if (j==1)
{
T=A[i][j]>A[i][j+1]?j+1:j;
}
else
{
if (A[i][j]>A[i][j-1])
{
T=j-1;
if (A[i][j-1]>A[i][j+1])
{
T=j+1;
}
}
else
{
T=j;
if (A[i][j]>A[i][j+1])
{
T=j+1;
}
}
}
}
OP_SEQUENCE(A,i-1,T);
cout<<"第"<<i<<"行"<<"第"<<T<<"列像素点->";
}
void main()
{
int **d,i;
d=new int*[n+1];
for ( i=0;i<=n;i++)
{
d[i]=new int[m+1];
}
int dd[n+1][m+1]={{0,0,0,0,0,0},{0,3,2,2,3,3},{0,1,2,1,2,1},{0,3,2,1,3,1},{0,2,1,1,2,2},{0,1,2,2,3,3},{0,2,2,2,1,1}};
for ( i=0;i<=n;i++)
{
for (int j=0;j<=m;j++)
{
d[i][j]=dd[i][j];
}
}
seam_carving(d);
}
a.证明:可能的接缝数量是m的指数函数,假定n>1.
第一行有n种可能选取像素点方式,第二到m行中每行有2-3种可能选中A[i][j-1],A[i][j],A[i][j+1].(j=1 or j=n时,是2种可能),所以总共有至少大于n*2^(m-1).
b 假定现在对每个像素A[i,j]我们都已计算出一个实型的“破坏度”d[i,j],表示删除像素A[i,j]对图像可视效果的破坏程度。直观地,一个像素的破坏度越低,它与相邻像素的相似度越高。再假定一条接缝的破坏度定义为包含的响度的破坏度之和。设计算法,寻找破坏度最低的接缝。分析算法的时间复杂度。
思考分析:按照要求需要删除的像素是同一列或相邻列。那么就可能删除A[i-1][j-1],A[i-1][j],A[i-1][j+1]之中的任意一个像素点。所以可得递归式:A[i][j]=d[i][j]+min{A[i-1][j-1],A[i-1][j],A[i-1][j+1]}.
代码如下:
[cpp] view
plaincopyprint?
#include <iostream>
using namespace std;
#define n 6//自定义数组行
#define m 5//自定义数组列
void OP_SEQUENCE(int **A,int i,int j);//i行j列;
int Min(int **A,int i,int j)
{
int temp=0;
if (j==1)
{
temp=A[i-1][j]>A[i-1][j+1]?A[i-1][j+1]:A[i-1][j];
}
else if (j==m)
{
temp=A[i-1][j]>A[i-1][j-1]?A[i-1][j-1]:A[i-1][j];
}
else
{
if (A[i-1][j]>A[i-1][j-1])
{
temp=A[i-1][j-1];
if (A[i-1][j-1]>A[i-1][j+1])
{
temp=A[i-1][j+1];
}
}
else
{
temp=A[i-1][j];
if (A[i-1][j]>A[i-1][j+1])
{
temp=A[i-1][j+1];
}
}
}
return temp;
}
void seam_carving(int **d)
{
int **A,i;//二维数组A表示破坏度之和。
A=new int*[n+1];
for ( i=0;i<=n;i++)
{
A[i]=new int[m+1];
}
for ( i=1;i<=m;i++)
{
A[1][i]=d[1][i];
}
for ( i=2;i<=n;i++)
{
for (int j=1;j<=m;j++)
{
A[i][j]=d[i][j]+Min(A,i,j);//递推式
}
}
int MIN=0x7fffffff,t=0;
for (i=1;i<=m;i++)
{
if(A
[i]<MIN)
{
MIN=A
[i];
t=i;
}
}
cout<<"MIN破坏点之和="<<MIN<<endl;
OP_SEQUENCE(A,n,t);
for ( i = 0; i <=m; i++)
delete[] A[i];
delete[] A;
}
void OP_SEQUENCE(int **A,int i,int j)//i行j列
{//输出一条接缝
int T;
if (i==0)return;
else
{
if (j==n)
{
T=A[i][j]>A[i][j-1]?j-1:j;
}
else if (j==1)
{
T=A[i][j]>A[i][j+1]?j+1:j;
}
else
{
if (A[i][j]>A[i][j-1])
{
T=j-1;
if (A[i][j-1]>A[i][j+1])
{
T=j+1;
}
}
else
{
T=j;
if (A[i][j]>A[i][j+1])
{
T=j+1;
}
}
}
}
OP_SEQUENCE(A,i-1,T);
cout<<"第"<<i<<"行"<<"第"<<T<<"列像素点->";
}
void main()
{
int **d,i;
d=new int*[n+1];
for ( i=0;i<=n;i++)
{
d[i]=new int[m+1];
}
int dd[n+1][m+1]={{0,0,0,0,0,0},{0,3,2,2,3,3},{0,1,2,1,2,1},{0,3,2,1,3,1},{0,2,1,1,2,2},{0,1,2,2,3,3},{0,2,2,2,1,1}};
for ( i=0;i<=n;i++)
{
for (int j=0;j<=m;j++)
{
d[i][j]=dd[i][j];
}
}
seam_carving(d);
}
相关文章推荐
- 算法导论 思考题 15-8(基于接缝裁剪的图像压缩)
- 图像接缝裁剪(seam carving)算法实现-SIGGRAPH 2007
- 基于接缝裁剪的图像压缩
- 动态规划之基于接缝裁剪的图像压缩
- Oracle本地网络分表模拟分区裁剪
- 上传头像时圆形裁剪框
- ucos代码裁剪
- Android - Android 7.0 拍照,相册选择和系统图片裁剪和删除适配
- 视锥体(frustum)裁剪
- 《算法导论》第五章-第1节_练习(参考答案)
- 用开源项目CropImage实现图片的裁剪(不推荐)
- linux驱动内核裁剪及烧录
- 算法导论——快速排序(Quick-Sort)
- 多尺度图片滑动窗口输出裁剪
- uiview的裁剪
- 算法导论习题自做2.1-3
- Android大图片裁剪 拍照 截图
- 在线裁剪图片 Jcrop
- 算法导论之三最大子数组问题
- 《算法导论》pdf