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

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

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

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

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

 import edu.princeton.cs.algs4.Picture;

 public class SeamCarver {
private int[][] picture;
private double[][] energy;
private int width;
private int height; public SeamCarver(Picture picture) // create a seam carver object based on the given picture
{
if (picture == null)
throw new IllegalArgumentException();
width = picture.width();
height = picture.height();
energy = new double[width][height];
this.picture = new int[width][height]; for (int i = 0; i < width(); i++)
{
for (int j = 0; j < height(); j++)
this.picture[i][j] = picture.getRGB(i, j);
} for (int i = 0; i < width(); i++)
{
for (int j = 0; j < height(); j++)
energy[i][j] = computeEnergy(i, j);
}
} private double computeEnergy(int x, int y)
{
if (x == 0 || x == width() - 1 || y == 0 || y == height() - 1)
return 1000.0; int rgbUp = picture[x][y - 1];
int rgbDown = picture[x][y + 1];
int rgbLeft = picture[x - 1][y];
int rgbRight = picture[x + 1][y];
double rx = Math.pow(((rgbLeft >> 16) & 0xFF) - ((rgbRight >> 16) & 0xFF), 2);
double gx = Math.pow(((rgbLeft >> 8) & 0xFF) - ((rgbRight >> 8) & 0xFF), 2);
double bx = Math.pow(((rgbLeft >> 0) & 0xFF) - ((rgbRight >> 0) & 0xFF), 2); double ry = Math.pow(((rgbUp >> 16) & 0xFF) - ((rgbDown >> 16) & 0xFF), 2);
double gy = Math.pow(((rgbUp >> 8) & 0xFF) - ((rgbDown >> 8) & 0xFF), 2);
double by = Math.pow(((rgbUp >> 0) & 0xFF) - ((rgbDown >> 0) & 0xFF), 2); return Math.sqrt(rx + gx + bx + ry + gy + by);
} public Picture picture() // current picture
{
Picture pic = new Picture(width, height);
for (int i = 0; i < width; i++)
for (int j = 0; j < height; j++)
pic.setRGB(i, j, picture[i][j]); return pic;
} public int width() // width of current picture
{
return width;
} public int height() // height of current picture
{
return height;
} public double energy(int x, int y) // energy of pixel at column x and row y
{
if (x < 0 || x > width - 1 || y < 0 || y > height - 1)
throw new IllegalArgumentException();
return energy[x][y];
} private void relaxvertical(double[][] distTo, int[][] edgeTo, int x, int y)
{
if (distTo[x][y + 1] > distTo[x][y] + energy[x][y + 1])
{
distTo[x][y + 1] = distTo[x][y] + energy[x][y + 1];
edgeTo[x][y + 1] = x;
}
if (x > 0 && distTo[x - 1][y + 1] > distTo[x][y] + energy[x - 1][y + 1])
{
distTo[x - 1][y + 1] = distTo[x][y] + energy[x - 1][y + 1];
edgeTo[x - 1][y + 1] = x;
}
if (x < width() - 1 && distTo[x + 1][y + 1] > distTo[x][y] + energy[x + 1][y + 1])
{
distTo[x + 1][y + 1] = distTo[x][y] + energy[x + 1][y + 1];
edgeTo[x + 1][y + 1] = x;
}
} private void transpose()
{
int temp = width;
width = height;
height = temp; double[][] energy2 = new double[width][height];
int[][] picture2 = new int[width][height]; for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
energy2[i][j] = energy[j][i];
picture2[i][j] = picture[j][i];
}
} energy = energy2;
picture = picture2;
} public int[] findHorizontalSeam() // sequence of indices for horizontal seam
{
transpose();
int[] array = findVerticalSeam();
transpose();
return array;
} public int[] findVerticalSeam() // sequence of indices for vertical seam
{
int[] seam = new int[height];
double[][] distTo = new double[width][height];
int[][] edgeTo = new int[width][height]; for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
if (j == 0) distTo[i][j] = energy[i][j];
else distTo[i][j] = Double.POSITIVE_INFINITY;
}
}
for (int j = 0; j < height - 1; j++)
{
for (int i = 0; i < width; i++)
{
relaxvertical(distTo, edgeTo, i, j);
}
} double min = Double.MAX_VALUE;
int minIndex = 0;
for (int i = 0; i < width; i++)
{
if (distTo[i][height - 1] < min)
{
min = distTo[i][height - 1];
minIndex = i;
}
} seam[height - 1] = minIndex;
for (int j = height - 2; j >= 0; j--)
{
seam[j] = edgeTo[seam[j + 1]][j + 1];
} return seam;
} public void removeHorizontalSeam(int[] seam) // remove horizontal seam from current picture
{
checkSeam(seam); int min = Integer.MAX_VALUE;
int max = 0; for (int i = 0; i < width; i++)
{
if (seam[i] > max) max = seam[i];
if (seam[i] < min) min = seam[i]; for (int j = seam[i]; j < height - 1; j++)
{
picture[i][j] = picture[i][j + 1];
}
} height--;
if (min > 0) min--;
if (max > height - 1) max = height - 1; for (int i = 0; i < width; i++)
{
for (int j = min; j <= max; j++)
energy[i][j] = computeEnergy(i, j);
for (int j = max + 1; j < height - 1; j++)
energy[i][j] = energy[i][j + 1];
} } private void checkSeam(int[] seam)
{
if (height <= 1 || seam == null || seam.length != width)
throw new IllegalArgumentException();
for (int i = 0; i < width; i++)
{
if (seam[i] < 0 || seam[i] > height - 1)
throw new IllegalArgumentException();
if (i > 0 && Math.abs(seam[i] - seam[i - 1]) > 1)
throw new IllegalArgumentException();
}
}
public void removeVerticalSeam(int[] seam) // remove vertical seam from current picture
{
transpose();
removeHorizontalSeam(seam);
transpose();
}
}

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. .net core webapi +ddd(领域驱动)+nlog配置+swagger配置 学习笔记(2)

    DDD领域驱动模型设计 什么是DDD 软件开发不是一蹴而就的事情,我们不可能在不了解产品(或行业领域)的前提下进行软件开发,在开发前,通常需要进行大量的业务知识梳理,而后到达软件设计的层面,最后才是开 ...

  2. Note: Secure Deduplication with Efficient and Reliable Convergent Key Management (Dekey)

    原文献:Secure Deduplication with Efficient and Reliable Convergent Key Management Dekey包含三个实体:用户(Users) ...

  3. struts2学习笔记——第一个struts2应用配置

    说实在的,随着Java学习的不断深入,特别是Java web框架部分,调bug让人很心累,但是每征服一个bug,内心的成就感也是难以言说的.第一个struts2应用的配置,我昨天折腾了快2个小时,最后 ...

  4. sqoop 安装与命令

    1. 下载:   wget http://mirrors.shu.edu.cn/apache/sqoop/1.4.7/sqoop-1.4.7.bin__hadoop-2.6.0.tar.gz 2. 解 ...

  5. 图解Linux安装jdk

    测试是否安装成功: 查看Java的版本命令:java -version Windows:查看java版本的方法是:运行--->cmd,输入java –version.注意: linux:终端中输 ...

  6. InfoQ —— 腾讯游戏大数据服务场景与应用

    简介 周东祥,本人从2010年毕业进入腾讯互动娱乐部门工作,一直致力在腾讯游戏运营开发工作.先后负责SAP业务受理系统,盗号自助系统,元数据系统以及近2年在腾讯游戏大数据运营开发中积累大量的大数据开发 ...

  7. DMZ主机

    DMZ称为"隔离区",也称"非军事化区".为了解决安装防火墙后外部网络不能访问内部网络服务器的问题,而设立的一个非安全系统与安全系统之间的缓冲区.这个缓冲区位于 ...

  8. iOS常用设计模式——工厂方法(简单工厂模式,工厂方法模式, 抽象工厂模式)

    1. 简单工厂模式 如何理解简单工厂,工厂方法, 抽象工厂三种设计模式? 简单工厂方法包含:父类拥有共同基础接口,具体子类实现子类特殊功能,工厂类根据参数区分创建不同子类实例.该场景对应的UML图如下 ...

  9. 《SQL 进阶教程》 自连接分组排序:练习题1-2-2

    分组排序 SELECT d1.district, d1. NAME, (SELECT COUNT(d2.price) FROM district_products d2 WHERE d2.price ...

  10. Angular学习笔记之组件之间的交互

    1.@Input:可设置属性 当它通过属性绑定的形式被绑定时,值会“流入”这个属性. 在子组件中使用,例如:@Input()name:string 父组件定义宾亮,并在父组件的模板中绑定,例如: 子组 ...