算法导论 接缝裁剪

来源:互联网 发布:天国王朝 史实 知乎 编辑:程序博客网 时间:2024/05/02 04:34
  给定一副彩色图像,它由一个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?
  1. #include <iostream>  
  2. using namespace std;  
  3. #define n 6//自定义数组行  
  4. #define m 5//自定义数组列  
  5. void OP_SEQUENCE(int **A,int i,int j);//i行j列;  
  6. int Min(int **A,int i,int j)  
  7. {  
  8.     int temp=0;  
  9.     if (j==1)  
  10.     {  
  11.         temp=A[i-1][j]>A[i-1][j+1]?A[i-1][j+1]:A[i-1][j];  
  12.     }  
  13.     else if (j==m)  
  14.     {  
  15.         temp=A[i-1][j]>A[i-1][j-1]?A[i-1][j-1]:A[i-1][j];  
  16.     }  
  17.     else  
  18.     {  
  19.         if (A[i-1][j]>A[i-1][j-1])  
  20.         {  
  21.             temp=A[i-1][j-1];  
  22.             if (A[i-1][j-1]>A[i-1][j+1])  
  23.             {  
  24.                 temp=A[i-1][j+1];  
  25.             }   
  26.         }   
  27.         else  
  28.         {  
  29.             temp=A[i-1][j];  
  30.             if (A[i-1][j]>A[i-1][j+1])  
  31.             {  
  32.                 temp=A[i-1][j+1];  
  33.             }  
  34.         }  
  35.     }  
  36.     return temp;  
  37. }  
  38. void seam_carving(int **d)  
  39. {  
  40.     int **A,i;//二维数组A表示破坏度之和。  
  41.     A=new int*[n+1];  
  42.     for (  i=0;i<=n;i++)  
  43.     {  
  44.         A[i]=new int[m+1];  
  45.     }  
  46.     for ( i=1;i<=m;i++)  
  47.     {  
  48.         A[1][i]=d[1][i];  
  49.     }  
  50.     for ( i=2;i<=n;i++)  
  51.     {  
  52.         for (int j=1;j<=m;j++)  
  53.         {  
  54.             A[i][j]=d[i][j]+Min(A,i,j);//递推式  
  55.         }  
  56.     }  
  57.     int MIN=0x7fffffff,t=0;  
  58.     for (i=1;i<=m;i++)  
  59.     {  
  60.         if(A[n][i]<MIN)  
  61.         {  
  62.             MIN=A[n][i];  
  63.             t=i;  
  64.         }  
  65.     }  
  66.     cout<<"MIN破坏点之和="<<MIN<<endl;  
  67.     OP_SEQUENCE(A,n,t);  
  68.     for ( i = 0; i <=m;  i++)    
  69.           delete[] A[i];                    
  70.     delete[] A;                       
  71.   
  72. }  
  73. void OP_SEQUENCE(int **A,int i,int j)//i行j列  
  74. {//输出一条接缝  
  75.     int T;  
  76.     if (i==0)return;  
  77.     else  
  78.     {  
  79.         if (j==n)  
  80.         {  
  81.             T=A[i][j]>A[i][j-1]?j-1:j;  
  82.         }  
  83.         else if (j==1)  
  84.         {  
  85.             T=A[i][j]>A[i][j+1]?j+1:j;  
  86.         }  
  87.         else  
  88.         {  
  89.             if (A[i][j]>A[i][j-1])  
  90.             {  
  91.                 T=j-1;  
  92.                 if (A[i][j-1]>A[i][j+1])  
  93.                 {  
  94.                     T=j+1;  
  95.                 }  
  96.             }  
  97.             else  
  98.             {  
  99.                 T=j;  
  100.                 if (A[i][j]>A[i][j+1])  
  101.                 {  
  102.                     T=j+1;  
  103.                 }  
  104.             }  
  105.         }  
  106.     }  
  107.     OP_SEQUENCE(A,i-1,T);  
  108.     cout<<"第"<<i<<"行"<<"第"<<T<<"列像素点->";  
  109. }  
  110. void main()  
  111. {  
  112.   int **d,i;  
  113.   d=new int*[n+1];  
  114.   for ( i=0;i<=n;i++)  
  115.   {  
  116.       d[i]=new int[m+1];  
  117.   }  
  118.   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}};  
  119.   for ( i=0;i<=n;i++)  
  120.   {  
  121.       for (int j=0;j<=m;j++)  
  122.       {  
  123.           d[i][j]=dd[i][j];  
  124.       }  
  125.   }  
  126.   seam_carving(d);  
  127. }  
0 0