zoukankan      html  css  js  c++  java
  • Coursera 算法二 week2 Seam Carving

    这周作业设计到的算法是有向无环图的最短路径算法,只需要按照顶点的拓扑顺序去放松顶点即可。而在这个题目中拓扑顺序就是按照行的顺序或列的顺序。

    用到的数据结构为一个二维数组picture同来存储每个像素的颜色,一个二维数组energy用来存储每个像素的能量。开始我是用一个Picture类的对象来存储图像,但是在讨论区里发现用二维数组存储图像,可以占用更小的存储,且计算能量、removeseam时更快更方便。

    在检验各像素能量时发现计算结果不正确,后来发现是运算符优先级的问题,((rgbLeft >> 16) & 0xFF) - ((rgbRight >> 16) & 0xFF),即‘ - ’的优先级大于‘ & ’的优先级,因此需要加括号。

    在Checklist的Possible Progress Steps中发现计算seam以及removeseam时可以只写Horizontal和Vertical中的一个,然后另一个用矩阵转置的方法来完成。

    第一次提交时memory没有通过,原因是把二维数组distTo和二维数组edgeTo放到了成员变量里,后来把这两个数组放到局部变量,就通过了memory测试。

      1 import edu.princeton.cs.algs4.Picture;
      2 
      3 public class SeamCarver {
      4   private int[][] picture;
      5   private double[][] energy;
      6   private int width;
      7   private int height;
      8   
      9   public SeamCarver(Picture picture)                // create a seam carver object based on the given picture
     10   {
     11       if (picture == null)
     12           throw new IllegalArgumentException();
     13       width = picture.width();
     14       height = picture.height();
     15       energy = new double[width][height];
     16       this.picture = new int[width][height];
     17       
     18       for (int i = 0; i < width(); i++)
     19       {
     20           for (int j = 0; j < height(); j++)
     21               this.picture[i][j] = picture.getRGB(i, j);
     22       }
     23       
     24       for (int i = 0; i < width(); i++)
     25       {
     26           for (int j = 0; j < height(); j++)
     27               energy[i][j] = computeEnergy(i, j);
     28       }
     29   }
     30   
     31   private double computeEnergy(int x, int y)
     32   {
     33       if (x == 0 || x == width() - 1 || y == 0 || y == height() - 1)
     34           return 1000.0;
     35       
     36       int rgbUp = picture[x][y - 1];
     37       int rgbDown = picture[x][y + 1];
     38       int rgbLeft = picture[x - 1][y];
     39       int rgbRight = picture[x + 1][y];
     40       double rx = Math.pow(((rgbLeft >> 16) & 0xFF) - ((rgbRight >> 16) & 0xFF), 2);
     41       double gx = Math.pow(((rgbLeft >> 8) & 0xFF) - ((rgbRight >> 8) & 0xFF), 2);
     42       double bx = Math.pow(((rgbLeft >> 0) & 0xFF) - ((rgbRight >> 0) & 0xFF), 2);
     43                   
     44       double ry = Math.pow(((rgbUp >> 16) & 0xFF) - ((rgbDown >> 16) & 0xFF), 2);
     45       double gy = Math.pow(((rgbUp >> 8) & 0xFF) - ((rgbDown >> 8) & 0xFF), 2);
     46       double by = Math.pow(((rgbUp >> 0) & 0xFF) - ((rgbDown >> 0) & 0xFF), 2);
     47       
     48       return Math.sqrt(rx + gx + bx + ry + gy + by);
     49   }
     50   
     51   public Picture picture()                          // current picture
     52   {
     53       Picture pic = new Picture(width, height);
     54       for (int i = 0; i < width; i++)
     55           for (int j = 0; j < height; j++)
     56               pic.setRGB(i, j, picture[i][j]);
     57           
     58       return pic;
     59   }
     60   
     61   public int width()                            // width of current picture
     62   {
     63       return width;
     64   }
     65   
     66   public     int height()                           // height of current picture
     67   {
     68       return height;
     69   }
     70   
     71   public  double energy(int x, int y)               // energy of pixel at column x and row y
     72   {
     73       if (x < 0 || x > width - 1 || y < 0 || y > height - 1)
     74           throw new IllegalArgumentException();
     75       return energy[x][y];
     76   }
     77   
     78   private void relaxvertical(double[][] distTo, int[][] edgeTo, int x, int y)
     79   {
     80       if (distTo[x][y + 1] > distTo[x][y] + energy[x][y + 1])
     81       {
     82           distTo[x][y + 1] = distTo[x][y] + energy[x][y + 1];
     83           edgeTo[x][y + 1] = x;
     84       }
     85       if (x > 0 && distTo[x - 1][y + 1] > distTo[x][y] + energy[x - 1][y + 1])
     86       {
     87           distTo[x - 1][y + 1] = distTo[x][y] + energy[x - 1][y + 1];
     88           edgeTo[x - 1][y + 1] = x;
     89       }
     90       if (x < width() - 1 && distTo[x + 1][y + 1] > distTo[x][y] + energy[x + 1][y + 1])
     91       {
     92           distTo[x + 1][y + 1] = distTo[x][y] + energy[x + 1][y + 1];
     93           edgeTo[x + 1][y + 1] = x;
     94       }
     95   }
     96   
     97   private void transpose() 
     98   {
     99       int temp = width;
    100       width = height;
    101       height = temp;
    102       
    103       double[][] energy2 = new double[width][height];
    104       int[][] picture2 = new int[width][height];
    105       
    106       for (int i = 0; i < width; i++)
    107       {
    108           for (int j = 0; j < height; j++)
    109           {
    110               energy2[i][j] = energy[j][i];
    111               picture2[i][j] = picture[j][i];
    112           }
    113       }
    114       
    115       energy = energy2;
    116       picture = picture2;
    117   }
    118   
    119   public int[] findHorizontalSeam()               // sequence of indices for horizontal seam
    120   {
    121       transpose();
    122       int[] array = findVerticalSeam();
    123       transpose();
    124       return array;
    125   }
    126   
    127   public int[] findVerticalSeam()                 // sequence of indices for vertical seam
    128   {
    129       int[] seam = new int[height];
    130       double[][] distTo = new double[width][height];
    131       int[][] edgeTo = new int[width][height];
    132       
    133       for (int i = 0; i < width; i++)
    134       {
    135           for (int j = 0; j < height; j++)
    136           {
    137               if (j == 0) distTo[i][j] = energy[i][j];
    138               else distTo[i][j] = Double.POSITIVE_INFINITY;
    139           }
    140       }
    141       for (int j = 0; j < height - 1; j++)
    142       {
    143           for (int i = 0; i < width; i++)
    144           {
    145               relaxvertical(distTo, edgeTo, i, j);
    146           }
    147       }
    148       
    149       double min = Double.MAX_VALUE;
    150       int minIndex = 0;
    151       for (int i = 0; i < width; i++)
    152       {
    153           if (distTo[i][height - 1] < min)
    154           {
    155               min = distTo[i][height - 1];
    156               minIndex = i;
    157           }
    158       }
    159       
    160       seam[height - 1] = minIndex;
    161       for (int j = height - 2; j >= 0; j--)
    162       {
    163           seam[j] = edgeTo[seam[j + 1]][j + 1];
    164       }
    165       
    166       return seam;
    167   }
    168   
    169   public void removeHorizontalSeam(int[] seam)   // remove horizontal seam from current picture
    170   {
    171       checkSeam(seam);
    172       
    173       int min = Integer.MAX_VALUE;
    174       int max = 0;
    175       
    176       for (int i = 0; i < width; i++)
    177       {
    178           if (seam[i] > max) max = seam[i];
    179           if (seam[i] < min) min = seam[i];
    180           
    181           for (int j = seam[i]; j < height - 1; j++)
    182           {
    183               picture[i][j] = picture[i][j + 1];
    184           }
    185       }
    186       
    187       height--;
    188       if (min > 0) min--;
    189       if (max > height - 1) max = height - 1;
    190       
    191       for (int i = 0; i < width; i++)
    192       {
    193           for (int j = min; j <= max; j++)
    194               energy[i][j] = computeEnergy(i, j);
    195           for (int j = max + 1; j < height - 1; j++)
    196               energy[i][j] = energy[i][j + 1];
    197       }
    198 
    199   }
    200   
    201   private void checkSeam(int[] seam)
    202   {
    203       if (height <= 1 || seam == null || seam.length != width)
    204           throw new IllegalArgumentException();
    205       for (int i = 0; i < width; i++) 
    206       {
    207           if (seam[i] < 0 || seam[i] > height - 1)
    208               throw new IllegalArgumentException();
    209           if (i > 0 && Math.abs(seam[i] - seam[i - 1]) > 1)
    210               throw new IllegalArgumentException();
    211       }
    212   }
    213   public void removeVerticalSeam(int[] seam)     // remove vertical seam from current picture
    214   {
    215       transpose();
    216       removeHorizontalSeam(seam);
    217       transpose();
    218   }
    219 }
    View Code
  • 相关阅读:
    隐马尔可夫模型 机器学习
    机器学习——EM算法与GMM算法
    机器学习——贝叶斯算法
    SVM算法 机器学习
    机器学习——谱聚类
    机器学习——Canopy算法
    机器学习——密度聚类
    Identity(身份)
    hyperledger fabric 结构模型学习
    fabric v1.1.0部署准备工作
  • 原文地址:https://www.cnblogs.com/lxc1910/p/8320736.html
Copyright © 2011-2022 走看看