POJ1009 Edge Detection
题目来源: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的更多相关文章
- Edge detection using LoG
intensity梯度值分布跟图片的大小有关, 比如将一张小图片放大后会变得很模糊, 原先清晰的edge, 即大的梯度值变得模糊. 但是原有的边缘通常还是肉眼可分辨的. 但用Sobel 算子可能就检测 ...
- 计算机视觉中的边缘检测Edge Detection in Computer Vision
计算机视觉中的边缘检测 边缘检测是计算机视觉中最重要的概念之一.这是一个很直观的概念,在一个图像上运行图像检测应该只输出边缘,与素描比较相似.我的目标不仅是清晰地解释边缘检测是怎样工作的,同时也提 ...
- 【数字图像分析】基于Python实现 Canny Edge Detection(Canny 边缘检测算法)
Canny 边缘检测算法 Steps: 高斯滤波平滑 计算梯度大小和方向 非极大值抑制 双阈值检测和连接 代码结构: Canny Edge Detection | Gaussian_Smoothing ...
- Image Processing and Analysis_21_Scale Space:Edge Detection and Ridge Detection with Automatic Scale Selection——1998
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Image Processing and Analysis_8_Edge Detection:Edge Detection Revisited ——2004
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Image Processing and Analysis_8_Edge Detection:Local Scale Control for Edge Detection and Blur Estimation——1998
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Image Processing and Analysis_8_Edge Detection: Optimal edge detection in two-dimensional images ——1996
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Image Processing and Analysis_8_Edge Detection:Multiresolution edge detection techniques ——1995
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
- Image Processing and Analysis_8_Edge Detection:Scale-space and edge detection using anisotropic diffusion——1990
此主要讨论图像处理与分析.虽然计算机视觉部分的有些内容比如特 征提取等也可以归结到图像分析中来,但鉴于它们与计算机视觉的紧密联系,以 及它们的出处,没有把它们纳入到图像处理与分析中来.同样,这里面也有 ...
随机推荐
- [转]_int64、long long 的区别
大学生程序代写 C++的64位整数[原]by 赤兔 http://baike.baidu.com/view/1235293.htm 在做ACM题时,经常都会遇到一些比较大的整数.而常用的内置整数类型常 ...
- 基于v4l2 ffmpeg x264的视频远程监控(附上编译好的库文件)
说明:主要是基于ghostyu网友整理的< arm mini2440 基于v4l2 ffmpeg x264的视频远程监控>.自己做了一遍,遇到不少问题,就整理记录下来. 1.平台 硬件:a ...
- linux 在后台运行数据库导入导出命令
nohup imp dbusername/password@orcl file=/home/20170928.dmp ignore=y log=/home/oracle/20170928.log fu ...
- LeetCode 510. Inorder Successor in BST II
原题链接在这里:https://leetcode.com/problems/inorder-successor-in-bst-ii/ 题目: Given a binary search tree an ...
- ACM学习历程—SGU 275 To xor or not to xor(xor高斯消元)
题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=275 这是一道xor高斯消元. 题目大意是给了n个数,然后任取几个数,让他们xor和 ...
- bzoj 4199: [Noi2015]品酒大会 后缀树
题目大意: 给定一个长为n的字符串,每个下标有一个权\(w_i\),定义下标\(i,j\)是r相似的仅当\(r \leq LCP(suf(i),suf(j))\)且这个相似的权为\(w_i,w_j\) ...
- shell批量创建文件及改名
批量创建文件及改名企业面试题2:使用for循环在/usr/sunzy目录下通过随机小写10个字母,批量创建10个html文件. #!/bin/bash Path=/usr/sunzy [ -d $Pa ...
- NodeJS”热部署“代码,实现动态调试(hotnode,可以实现热更新)
NodeJS”热部署“代码,实现动态调试 开发中遇到的问题 如果你有 PHP 开发经验,会习惯在修改 PHP 脚本后直接刷新浏览器以观察结果,而你在开发 Node.js 实现的 HTTP 应用时会 ...
- 从Github远程库安装Node.JS
3)从Github远程库安装Node.JS在这个方法中我们需要一些步骤来把Node.js的从Github上的远程的仓库克隆到本地仓库目录 在开始克隆(克隆)包到本地并且配制之前,我们要先安装以下依赖包 ...
- Flask07 Jinja2模板测试器、控制语句IF/FOR、变量/块 赋值、作用域、块级作用域
1 测试器及其使用 在模板中的 {{}} 可以书写测试器,格式如下 {{ 变量 is 测试器名称 }} 1.1 在python中导入 Jinja2 的模板 from jinja2 import te ...