题目来源:http://poj.org/problem?id=1009

题目大意:

  某图像公司用run length encoding(RLE)的方式记录和存储了大量的图像。程序的目标是读入压缩后的图像,对图像进行边缘检测,然后输出另一幅压缩后的图片。具体形式见下面的图片和描述。

  一种最简单的边缘检测算法就是使输出图片像素点的值为输入图片中该像素点与其周围像素点值之间差值的最大值。考虑下面的例子:

Output image中左上角的像素点的值是|15-15|,|15-100|和|15-100|的最大值85.第4行第2列的像素点值是|175-100|,|175-100|,|175-100|,|175-175|,|175-25|,|175-175|,|175-175|和|175-25|的最小值150.

图像的像素点数在2至1,000,000,000(109)之间。所有的图片以RLE(run length encoding)的方式进行压缩编码。RLE是一些数据对,每对含一个像素值v和一个run length,即有连续多少个点的像素点的值为v。每幅图像最多含有1000个RLE对。连续的数据对的像素值都不相同。图像的每行像素点数相同。

输入:含一张或多张图像,每张图像信息的第一行为图像的宽度,接下来的每行为一个RLE对,以0 0结尾。图像宽度为0时表示图像数据输入完毕。Example Input展示的即为上图所示的图像。

输出:一系列边缘检测后的图像。与输入图像的格式相同,但运行RLE的数目多于1000.


Sample Input

7
15 4
100 15
25 2
175 2
25 5
175 2
25 5
0 0
10
35 500000000
200 500000000
0 0
3
255 1
10 1
255 2
10 1
255 2
10 1
255 1
0 0
0

Sample Output

7
85 5
0 2
85 5
75 10
150 2
75 3
0 2
150 2
0 4
0 0
10
0 499999990
165 20
0 499999990
0 0
3
245 9
0 0
0

刚开始直接用暴力方法做,发现数据量大时计算时间过长,TLE了。后来看了牛人的方法表示无比佩服。

  对于本题有如下观察:

  1.由于图片的像素点数最大为10^9,而RLE对的数目最大为1000,所以,一定存在一些RLE的run length很长,使得图像中有比较多的连续像素值相等,也即对他们的很多点进行边缘检测后的值一定为0,所以不必再逐个计算。

  2.实际上我们只需要关注结果值会与其前面的点不一样的点即可(取名为关键点),由这些关键点即可得到输出图像的RLE对。

  对于第2点,哪些点会是关键点呢?大牛分析后发现,每个输入的RLE对的起点和终点以及这些点周围的点一定包含了所有的关键点。如何证明?我没有去想怎么从理论上严格的推倒,只是从直觉上,我觉得可以这样来想象这个问题:

  首先把整幅图想象成一张白纸(比如把全部像素点的值初始化为0)。每读入一个RLE对,就相当于用彩笔在纸上给指定数目的像素点涂上了颜色。而每多涂一次颜色,该次涂色的起点和终点处及其周边的点的输出值会受到影响,有可能会变得跟其前一个点的输出值不一样(这个在纸上试一试就能发现),也就是说有可能成为关键点。而其他点的输出值应该是跟其左边的点输出值相等。所以当处理完了每个RLE对,也就把所有可能成为关键点的点的输出值都计算出来了。然后按坐标将所有点排序,再把输出值相等的点合并起来,就可以得到输出的RLE对。

  具体实现可以下列参考代码,但是效率可能不是很高,应该还可以继续优化。

 //////////////////////////////////////////////////////////////////////////
// POJ1009 Edgee Detection
// Memory: 656K Time: 172MS
// Language: C++ Result: Accepted
////////////////////////////////////////////////////////////////////////// #include <iostream>
#include <map>
#include <math.h>
#include <stdlib.h> #define getBigger(a, b) ((a > b) ? a : b)
#define upLeft(i) (i - c - 1)
#define up(i) (i - c)
#define upRight(i) (i - c + 1)
#define left(i) (i - 1)
#define right(i) (i + 1)
#define downLeft(i) (i + c - 1)
#define down(i) (i + c)
#define downRight(i) (i + c + 1) using namespace std; class RLE {
public:
int color;
int length;
int startPoint;
int endPoint;
}; RLE RLEList[];
int n;//RLE表长度
int pointCount; //总点数
int c, r;//image的列数与行数
map<int, int> PVmap; int getColor(int index) {
for(int i = ; i < n; i++) {
if (index <= RLEList[i].endPoint) {
return RLEList[i].color;
} else {
continue;
}
}
} int getValue(int i) {
int value = ; if ((upLeft(i) >= ) && ((i % c) > )) {
value = getBigger(value, abs(getColor(i) - getColor(upLeft(i))));
}
if ((up(i) >= )) {
value = getBigger(value, abs(getColor(i) - getColor(up(i))));
}
if ((upRight(i) >= ) && ((i % c) < c - )) {
value = getBigger(value, abs(getColor(i) - getColor(upRight(i))));
}
if ((left(i) >= ) && ((i % c) > )) {
value = getBigger(value, abs(getColor(i) - getColor(left(i))));
}
if ((right(i) <= r * c - ) && ((i % c) < c - )) {
value = getBigger(value, abs(getColor(i) - getColor(right(i))));
}
if ((downLeft(i) <= r * c - ) && ((i % c) > )) {
value = getBigger(value, abs(getColor(i) - getColor(downLeft(i))));
}
if ((down(i) <= r * c - )) {
value = getBigger(value, abs(getColor(i) - getColor(down(i))));
}
if ((downRight(i) <= r * c - ) && ((i % c) < c - )) {
value = getBigger(value, abs(getColor(i) - getColor(downRight(i))));
}
return value;
} void processPos(int index) {
if (PVmap.find(index) == PVmap.end()) {
PVmap[index] = getValue(index);
}
if (upLeft(index) >= && upLeft(index) < pointCount) {
if (PVmap.find(upLeft(index)) == PVmap.end()) {
PVmap[upLeft(index)] = getValue(upLeft(index));
}
}
if (up(index) >= && up(index) < pointCount) {
if (PVmap.find(up(index)) == PVmap.end()) {
PVmap[up(index)] = getValue(up(index));
}
}
if (upRight(index) >= && upRight(index) < pointCount) {
if (PVmap.find(upRight(index)) == PVmap.end()) {
PVmap[upRight(index)] = getValue(upRight(index));
}
}
if (left(index) >= && left(index) < pointCount) {
if (PVmap.find(left(index)) == PVmap.end()) {
PVmap[left(index)] = getValue(left(index));
}
}
if (right(index) >= && right(index) < pointCount) {
if (PVmap.find(right(index)) == PVmap.end()) {
PVmap[right(index)] = getValue(right(index));
}
}
if (downLeft(index) >= && downLeft(index) < pointCount) {
if (PVmap.find(downLeft(index)) == PVmap.end()) {
PVmap[downLeft(index)] = getValue(downLeft(index));
}
}
if (down(index) >= && down(index) < pointCount) {
if (PVmap.find(down(index)) == PVmap.end()) {
PVmap[down(index)] = getValue(down(index));
}
}
if (downRight(index) >= && downRight(index) < pointCount) {
if (PVmap.find(downRight(index)) == PVmap.end()) {
PVmap[downRight(index)] = getValue(downRight(index));
}
}
} int main(void) {
c = ;
while (true) {
cin >> c;
if (c == ) {
cout << "" << endl;
return ;
}
pointCount = ;
int i = ;
while (true) {
int color, length;
cin >> color >> length;
if (length == ) {
break;
}
RLEList[i].color = color;
RLEList[i].length = length;
i++;
pointCount += length;
}
r = pointCount / c;
if (pointCount % c) {
r++;
RLEList[i].length = r * c - pointCount;
RLEList[i].color = ;
pointCount = r * c;
i++;
}
n = i;
RLEList[].startPoint = ;
RLEList[].endPoint = RLEList[].length - ;
for (int i = ; i < n; i++) {
RLEList[i].startPoint = RLEList[i - ].startPoint + RLEList[i - ].length;
RLEList[i].endPoint = RLEList[i - ].endPoint + RLEList[i].length;
}
cout << c << endl;
//处理每个RLE对的起点和终点产生的影响
for (int RLEIndex = ; RLEIndex < n; RLEIndex++) {
int startPos = RLEList[RLEIndex].startPoint;
int endPos = RLEList[RLEIndex].endPoint;
processPos(startPos);
processPos(endPos);
}
map<int, int>::iterator it1;
map<int, int>::iterator it2;
int l = ;
//合并output image中相同的关键点,输出RLE对
for (it1 = PVmap.begin(), it2 = it1, ++it2; it2 != PVmap.end(); ++it1, ++it2) {
if((*it2).second == (*it1).second) {
l += (*it2).first - (*it1).first;
} else {
cout << (*it1).second << " " << l << endl;
l = ;
}
}
--it2;
cout << (*it2).second << " " << l << endl;
cout << "0 0"<< endl;
PVmap.clear();
}
return ;
}

 

POJ1009 Edge Detection的更多相关文章

  1. Edge detection using LoG

    intensity梯度值分布跟图片的大小有关, 比如将一张小图片放大后会变得很模糊, 原先清晰的edge, 即大的梯度值变得模糊. 但是原有的边缘通常还是肉眼可分辨的. 但用Sobel 算子可能就检测 ...

  2. 计算机视觉中的边缘检测Edge Detection in Computer Vision

    计算机视觉中的边缘检测   边缘检测是计算机视觉中最重要的概念之一.这是一个很直观的概念,在一个图像上运行图像检测应该只输出边缘,与素描比较相似.我的目标不仅是清晰地解释边缘检测是怎样工作的,同时也提 ...

  3. 【数字图像分析】基于Python实现 Canny Edge Detection(Canny 边缘检测算法)

    Canny 边缘检测算法 Steps: 高斯滤波平滑 计算梯度大小和方向 非极大值抑制 双阈值检测和连接 代码结构: Canny Edge Detection | Gaussian_Smoothing ...

  4. Image Processing and Analysis_21_Scale Space:Edge Detection and Ridge Detection with Automatic Scale Selection——1998

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

  5. Image Processing and Analysis_8_Edge Detection:Edge Detection Revisited ——2004

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

  6. Image Processing and Analysis_8_Edge Detection:Local Scale Control for Edge Detection and Blur Estimation——1998

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

  7. Image Processing and Analysis_8_Edge Detection: Optimal edge detection in two-dimensional images ——1996

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

  8. Image Processing and Analysis_8_Edge Detection:Multiresolution edge detection techniques ——1995

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

  9. Image Processing and Analysis_8_Edge Detection:Scale-space and edge detection using anisotropic diffusion——1990

    此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...

随机推荐

  1. ACM学习历程—HDU5422 Rikka with Graph(贪心)

    Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, so he ...

  2. bzoj 2553: [BeiJing2011]禁忌 AC自动机+矩阵乘法

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=2553 题解: 利用AC自动机的dp求出所有的转移 然后将所有的转移储存到矩阵中,进行矩阵 ...

  3. bzoj 3232: 圈地游戏 01分数规划

    题目大意: http://www.lydsy.com/JudgeOnline/problem.php?id=3232 题解: 首先我们看到这道题让我们最优化一个分式. 所以我们应该自然而然地想到01分 ...

  4. Marionettejs

    Marionette是牵线木偶的意思,这个库是对Backbone的一次更高层次封装.这样的封装有两个目标: 减少重复的工作,提高使用Backbonejs时的生产效率给复杂应用页面提供更多的结构,以支撑 ...

  5. navicat导入sql文件

    Hello,大家好.Navicat是我们平时使用较多的一个数据库客户端工具,平时小天我主要是用来连接mysql的,使用的时候还是很方便的. 今天小天我就给大家分享一个Navicat如何导入导出sql文 ...

  6. Poj 2136 Vertical Histogram(打印垂直直方图)

    一.Description Write a program to read four lines of upper case (i.e., all CAPITAL LETTERS) text inpu ...

  7. 与input有关的一些操作

    单选 : 通过name指定为一组,只能选择一个  一组一个选项 <input type=" name="sex"/>男 <input type=&quo ...

  8. SpringMvc之参数绑定注解详解之二

    2 consumes.produces 示例 cousumes的样例: 1 @Controller   2 @RequestMapping(value = "/pets", met ...

  9. Queue——C#浅谈

    1.Queue定义 System.Collections.Queue类表示对象的先进先出集合,存储在 Queue(队列) 中的对象在一端插入,从另一端移除. 2.优点 1.能对集合进行顺序处理(先进先 ...

  10. 网站跳转到Apache 2 Test Page powered by CentOS

    原来是80端口被占用的问题 解决80端口占用问题 sudo fuser -n tcp -k 覆盖原来的httpd cp /usr/local/apache2/bin/apachectl /etc/in ...