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

用到的数据结构为一个二维数组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. }

Coursera 算法二 week2 Seam Carving的更多相关文章

  1. Coursera 算法二 week 5 BurrowsWheeler

    本打算周末完成这次作业,但没想到遇到了hard deadline,刚开始看不懂题意,后来发现算法4书上有个类似的问题,才理解了题意.最后晚上加班,上课加班,还好在11:35也就是课程结束前25分钟完成 ...

  2. Coursera 算法二 week 3 Baseball Elimination

    这周的作业不需要自己写算法,只需要调用库函数就行,但是有些难以理解,因此用了不少时间. import edu.princeton.cs.algs4.FlowEdge; import edu.princ ...

  3. Coursera 算法二 week 4 Boggle

    这次的作业主要用到了单词查找树和深度优先搜索. 1.在深度优先搜索中,在当前层的递归调用前,将marked数组标记为true.当递归调用返回到当前层时,应将marked数组标记为false.这样既可以 ...

  4. coursera 算法二 week 1 wordnet

    这周的作业可谓是一波三折,但是收获了不少,熟悉了广度优先搜索还有符号图的建立.此外还知道了Integer.MAX_VALUE. SAP: 求v和w的大概思路是对v和w分别广度优先搜索,然后遍历图中每一 ...

  5. Programming Assignment 2: Seam Carving

    编程作业二 作业链接:Seam Carving & Checklist 我的代码:SeamCarver.java 问题简介 接缝裁剪(Seam carving),是一个可以针对照片内容做正确缩 ...

  6. Seam carving 学习笔记

    今天首次接触了图像编辑中的seam carving知识,感觉挺神奇的.虽然我自己可能理解的不是很深刻,但是记录下来,总是好的. seam carving直接翻译过来是“线裁剪”的意思.它的主要用途是对 ...

  7. HDU5092——Seam Carving(动态规划+回溯)(2014上海邀请赛重现)

    Seam Carving DescriptionFish likes to take photo with his friends. Several days ago, he found that s ...

  8. 递推DP HDOJ 5092 Seam Carving

    题目传送门 /* 题意:从上到下,找最短路径,并输出路径 DP:类似数塔问题,上一行的三个方向更新dp,路径输出是关键 */ #include <cstdio> #include < ...

  9. TensorFlow 入门之手写识别(MNIST) softmax算法 二

    TensorFlow 入门之手写识别(MNIST) softmax算法 二 MNIST Fly softmax回归 softmax回归算法 TensorFlow实现softmax softmax回归算 ...

随机推荐

  1. Java学习笔记(一)语法

    基本语法 大小写敏感 类名:对于所有的类来说,类名的首字母应该大写 方法名:所有的方法名都应该以小写字母开头.如果方法名含有若干单词,则后面的每个单词首字母大写. 源文件名:源文件名必须和类名相同.当 ...

  2. Codeforces Round #522 Div2C(思维)

    #include<bits/stdc++.h>using namespace std;int a[200007];int b[200007][7];int ans[200007];int ...

  3. c#中ToString("yyyyMMdd") 与ToString("yyyymmdd")区别

    string a= DateTime.Now.ToString("yyyyMMdd") ; string b=DateTime.Now.ToString("yyyymmd ...

  4. SAP 权限层次

    此文可是没有维护过权限的人对权限有一个整体的认知,转来加以记忆. 一是系统权限 主要是对模块为单位的权限划分,具体就是用户对该模块可见不可见,能不能对该模块进行再授权的操作.表现在用户界面就是用户登录 ...

  5. Sqlyog问题

    Sqlyog没有架构设计器的解决方法 更换注册码即可

  6. vs获取最新时,提示签出解决方案

    项目中的文件有被意外去掉了只读属性的. VSS中签入状态的文件在本地都有只读属性. 如果VSS中是签入状态,而对应的本机文件没有只读状态,在获取最新版本的时候,就会弹出一个对话框提示签出还是用VSS中 ...

  7. BZOJ 1924 && Luogu P2403 [SDOI2010]所驼门王的宝藏 恶心建图+缩点DP

    记住:map一定要这么用: if(mp[x[i]+dx[j]].find(y[i]+dy[j])!=mp[x[i]+dx[j]].end()) add(i,mp[x[i]+dx[j]][y[i]+dy ...

  8. Helvetic Coding Contest 2016 online mirror F1

    Description Heidi has finally found the mythical Tree of Life – a legendary combinatorial structure ...

  9. LeetCode 179 Largest Number 把数组排成最大的数

    Given a list of non negative integers, arrange them such that they form the largest number.For examp ...

  10. dotnet core 命令行使用web deploy 部署项目到远程IIS

    众所周知dotnet cli可以用来编译和生成发布.net core,其实dotnet publish 还能进行WebDeploy.先解释一下使用场景一般是用于持续部署 dotnet publish进 ...