Edge Detection
Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 22604   Accepted: 5311

Description

IONU Satellite Imaging, Inc. records and stores very large images using run length encoding. You are to write a program that reads a compressed image, finds the edges in the image, as described below, and outputs another compressed image of the detected edges. 
A simple edge detection algorithm sets an output pixel's value to be the maximum absolute value of the differences between it and all its surrounding pixels in the input image. Consider the input image below: 

The upper left pixel in the output image is the maximum of the values |15-15|,|15-100|, and |15-100|, which is 85. The pixel in the 4th row, 2nd column is computed as the maximum of |175-100|, |175-100|, |175-100|, |175-175|, |175-25|, |175-175|,|175-175|, and |175-25|, which is 150. 
Images contain 2 to 1,000,000,000 (109) pixels. All images are encoded using run length encoding (RLE). This is a sequence of pairs, containing pixel value (0-255) and run length (1-109). Input images have at most 1,000 of these pairs. Successive pairs have different pixel values. All lines in an image contain the same number of pixels. 

Input

Input consists of information for one or more images. Each image starts with the width, in pixels, of each image line. This is followed by the RLE pairs, one pair per line. A line with 0 0 indicates the end of the data for that image. An image width of 0 indicates there are no more images to process. The first image in the example input encodes the 5x7 input image above. 

Output

Output is a series of edge-detected images, in the same format as the input images, except that there may be more than 1,000 RLE pairs. 

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

Hint

A brute force solution that attempts to compute an output value for every individual pixel will likely fail due to space or time constraints. 

Source

题意

  使用一种叫做“run length encoding”的方式来储存大尺寸图片,该方法是通过记录编码值和编码长度的对(number,length)来存储图片。有一种简单的edge detection算法是将图像中的每一个点的值与他周围的八个点求差,然后取绝对值的最大值。

现在的任务就是实现这个算法,输入的图片是以run length encoding的形式表示的,同时也要求转换后的图片也以run length encoding的形式表示。

思路

  题意中说明图片的长度为10^9,因此不可能采用暴力计算法。从答案中可以看出,会有连续一段的相同输入输出,输入的pair number不超过1000,数量上是很少的,因此可以采用跳跃编码。

  run length encoding编码方法是记录编码值和该值的编码长度,这里长度可以用开始和结束位置代替,结束位置可以用下一个值的开始位置表示。这样就变成记录每一个出现的新值和出现的位置即可。

  而edge detection中每一个新值的出现都是因为输入图片中新值的出现。因此,只要对输入图片的每一个pair计算这个新值开始位置周围8个像素值,并记录位置即可。然后对所有计算的像素值根据位置排序,并且对像素值相同的格子进行合并就是所求结果。

上图来自 POJ 1009 Edge Detection(图像边缘检测)

  我们使用跳跃编码,记录起始格子的num值和它的长度len,自然可以通过计算得到一个虚拟很长的输入或是输出数组(一维),再将一维数组转换为虚拟二维数组,即对len进行累加,即为一维数组的索引值,像素值num即为一位数组中存储的值,而转换为二维数组,即为一位数组索引值对n取余或是取整,之所以说是虚拟,就是不开辟空间进行存储……

  考虑到这里,想到了使用map,map<int,int>,其中只存储连续段的起始格,对于输入map<int,int> InMap和输出map<int,int> OutMap,其key值用来存储一位数组的索引值,value则用来存储像素值num,为什么用map呢,最重要的是它可以按照key值自动升序排列,计算每一个连续段起始格周围的8个格子后,将计算得到的像素值和数组索引值插入map,他自动帮我们按照数组索引值排序了,这样,当我们计算完毕之后,向前迭代输出,省去了排序吧啦吧啦的麻烦,只要向前迭代,并把像素值相同的格子忽略掉(因为他们应该属于同一连续段的)就可以了。本小白感觉map大法好!

  关于map==》C++ STL 中 map 容器

  这时候,需要考虑一下特殊的格子,对于在二维数组边界的格子,他的周围不足8个格子,计算的时候当然要注意。

我们可以用简单的取余运算就把在最左边一列、最右边一列给筛选出来。这里我们把连续段的长度进行求和为Max,即数组索引从0开始,且最大索引值不会超过Max,所以可以把最上面一行和最下面一行计算中的越界格子排掉。这里需要考虑到每行只有一列和两列的情况!!

  还有更值得我们注意的!!这里也让本小白WA了几次,百思不得其解了好久……

  那就是最后一行的第一个格子,由于它没有下一行,所以它的像素值会发生变化

  有朋友问为什么最后一行的第一个格子需要考虑而别的行的第一个格子不需要考虑呢?

  首先,如果像这样像素值发生变化,自然会进行计算。

  其次,如果像素值没有发生变化,那无非就是担心换行之后,格子上方和下方的格子的数值变化,拿上方格子数值变化为例,如果两个格子(黄色)上方格子数值不一样,那紫色格子的数值发生变化时,必然会计算黄色格子的数值,所以此处不需计算。其他情况同理。

  而最下面一行的第一个格子,它的下面的格子不是数值发生变化,而是消失了,即可以理解为,它下面的格子数值发生了变化但是不会启动计算过程,所以最下面一行的第一个格子是特殊的。

 #include<iostream>
#include<map>
using namespace std;
/*
可以利用map<int,int>的first为下标,second为像素值
一个输入map,一个输出map
利用map的特性,输出map插入后自动以first排序
输出的时候遍历输出map,如果second不同,则进行输出 代码很乱包括了我的测试代码……
*/
void Print(map<int,int> OutMap,int n,int Max)
{
long tempFirst = ,tempSecond=;
/*
map<int,int>::iterator iter = OutMap.begin();
for(iter;iter != OutMap.end();iter++)
{
cout<<iter->first<<" "<<iter->second<<endl;
}
*/
map<int,int>::iterator iter1 = OutMap.begin();//向前迭代
tempFirst = iter1->first;tempSecond = iter1->second;
for(iter1;iter1 != OutMap.end();iter1++)
{
if(iter1->second != tempSecond)
{
cout<<tempSecond<<" "<<iter1->first-tempFirst<<endl; tempSecond = iter1->second;
tempFirst = iter1->first;
}
}
cout<<tempSecond<<" "<<Max-tempFirst<<endl; cout<<<<" "<<<<endl;
}
void Compute(map<int,int> In,int n,int Max)
{//计算输出数组
/**/
map<int,int> OutMap;
int Count=;//记录数组下
int temp=;
int arr[] = {,-n-,-n,-n+,-,,n-,n,n+,Max-n};
///对In进行遍历
map<int,int>::iterator iter = In.begin();
for(iter;iter != In.end();iter++)
{
for(int i=;i<;i++)
{
if(i == ) Count = arr[i];
else Count = iter->first + arr[i];//周围8个像素的下标,包括自己
if(Count < || Count >= Max)
{//下标越界
continue;
}
else if(Count%n == n- && iter->first%n == && n!=&& n!=)
{//在最左边一列,没有左边像素
continue;
}
else if(Count%n == && iter->first%n == n- && n!=&& n!=)
{//在最右边一列,没有右边像素
continue;
}
else{
map<int,int>::iterator CountIter = In.begin();//指针定位到中心
CountIter = In.upper_bound(Count);
CountIter--;
//cout<<"测试CountIter:"<<CountIter->first<<" "<<CountIter->second<<endl;
///计算当前像素的值
int Num = ;
int tempNum = ;
for(int j =;j<;j++)//考察周围的八个点
{
temp = Count + arr[j];
if(temp< || temp>=Max || temp%n==n-&&Count%n==&&n!= || temp%n==&&Count%n==n-&&n!=)
{
continue;
}else{
map<int,int>::iterator tempIter;
tempIter = In.upper_bound(temp);//第一个大于temp的位置
//cout<<"测试tempIter:"<<tempIter->first<<" "<<tempIter->second<<endl;
tempIter--;
//cout<<"测试tempIter2:"<<tempIter->first<<" "<<tempIter->second<<endl;
tempNum = CountIter->second - tempIter->second;
if(tempNum < ) tempNum = - * tempNum;
}
if(tempNum > Num) Num = tempNum;
}
///插入到OutMap
OutMap.insert(pair<int,int>(Count,Num));
}
}
}
Print(OutMap,n,Max);
OutMap.clear();
} int main()
{
int n;
map<int,int> InMap; cin>>n;
cout<<n<<endl;
while(n)
{ int num,len;
long Count = ;
///获取输入数组
cin>>num>>len;
while(len)
{
InMap.insert(pair<int,int>(Count,num));
Count += len;//虚拟数组下标增加
cin>>num>>len;
}
InMap.insert(pair<int,int>(,));
/*
map<int,int>::iterator iter;//向前迭代
for(iter = InMap.begin();iter != InMap.end();iter++)
{
cout<<iter->first<<","<<iter->second<<endl;
}
*/
///输入结束,进行输出数组的计算
Compute(InMap,n,Count);
InMap.clear();
cin>>n;
cout<<n<<endl;
} return ;
}

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

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

  10. Image Processing and Analysis_8_Edge Detection:A Computational Approach to Edge Detection——1986

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

随机推荐

  1. js特效背景--点线随着鼠标移动而改变

    https://blog.csdn.net/css33/article/details/89450852 https://www.cnblogs.com/qq597585136/p/7019755.h ...

  2. 生成大量插入语句,并将语句写入txt文件中

    import java.io.*; /** * Created by czz on 2019/9/23. */ public class TTest { /** * 生成大量插入语句,并将语句写入tx ...

  3. yum 报错3

    . Contact the upstream for the repository and get them to fix the problem. . Reconfigure the baseurl ...

  4. Mac下安装svn服务器

    本文转载自http://www.cnblogs.com/czq1989/p/4913692.html Mac默认已经安装了svn,我们只需要进行配置并开启就可以了 首先我们可以验证一下是否安装了svn ...

  5. Dubbo 03 Restful风格的API

    目录 Dubbo03 restful风格的API 根路径 协议 版本 用HTTP协议里的动词来实现资源的增删改查 用例 swagger(丝袜哥) OpenAPI 资源 编写API文档 整合Spring ...

  6. Mongodb操作3-可视化工具使用

    1.无密码登录 1.创建连接 输入ip后 先测试在链接 2.有密码登录 设置密码 1.选择主数据库 >>>use admin # 第一步 选择主数据 switched to db a ...

  7. Java语言基础(6)

    1 while循环 案例:Demo1 1+2+3+4+5+...+100 = ? 首先定义一个变量sum,用来保存累加之和,int sum=0 第1次:sum = sum + 1 第2次: sum = ...

  8. (转)oracle使用expdp、impdp和exp、imp导入导出表及表结构

    使用expdp.impdp和exp.imp时应该注重的事项: 1.exp和imp是客户端工具程序,它们既可以在客户端使用,也可以在服务端使用. 2.expdp和impdp是服务端的工具程序,他们只能在 ...

  9. [CF#592 E] [二分答案] Minimizing Difference

    链接:http://codeforces.com/contest/1244/problem/E 题意: 给定包含$n$个数的数组,你可以执行最多k次操作,使得数组的一个数加1或者减1. 问合理的操作, ...

  10. highcharts的基本使用(转载)

    1 概述 Highcharts是一个跨浏览器的JavaScript图表控件,支持柱状图.趋势图.面积图.饼图.环形图.组合图.堆积图.散点图. Highcharts图表的基本功能,只需要引入两个JS类 ...