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
关于map==》C++ STL 中 map 容器
这时候,需要考虑一下特殊的格子,对于在二维数组边界的格子,他的周围不足8个格子,计算的时候当然要注意。
我们可以用简单的取余运算就把在最左边一列、最右边一列给筛选出来。这里我们把连续段的长度进行求和为Max,即数组索引从0开始,且最大索引值不会超过Max,所以可以把最上面一行和最下面一行计算中的越界格子排掉。这里需要考虑到每行只有一列和两列的情况!!
还有更值得我们注意的!!这里也让本小白WA了几次,百思不得其解了好久……
那就是最后一行的第一个格子,由于它没有下一行,所以它的像素值会发生变化
有朋友问为什么最后一行的第一个格子需要考虑而别的行的第一个格子不需要考虑呢?
首先,如果像这样像素值发生变化,自然会进行计算。
其次,如果像素值没有发生变化,那无非就是担心换行之后,格子上方和下方的格子的数值变化,拿上方格子数值变化为例,如果两个格子(黄色)上方格子数值不一样,那紫色格子的数值发生变化时,必然会计算黄色格子的数值,所以此处不需计算。其他情况同理。
而最下面一行的第一个格子,它的下面的格子不是数值发生变化,而是消失了,即可以理解为,它下面的格子数值发生了变化但是不会启动计算过程,所以最下面一行的第一个格子是特殊的。
#include
#include
代码很乱包括了我的测试代码……
*/
void Print(map
{
long tempFirst = ,tempSecond=;
/*
map
for(iter;iter != OutMap.end();iter++)
{
cout<
tempFirst = iter1->first;tempSecond = iter1->second;
for(iter1;iter1 != OutMap.end();iter1++)
{
if(iter1->second != tempSecond)
{
cout<
tempSecond = iter1->second;
tempFirst = iter1->first;
}
}
cout<<tempSecond<<" "<<Max-tempFirst<<endl;
cout<<<<" "<<<<endl;
}
void Compute(map
{//计算输出数组
/**/
map
int Count=;//记录数组下
int temp=;
int arr[] = {,-n-,-n,-n+,-,,n-,n,n+,Max-n};
///对In进行遍历
map
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
CountIter = In.upper_bound(Count);
CountIter--;
//cout<<"测试CountIter:"<
{
continue;
}else{
map
tempIter = In.upper_bound(temp);//第一个大于temp的位置
//cout<<"测试tempIter:"<
if(tempNum < ) tempNum = - * tempNum;
}
if(tempNum > Num) Num = tempNum;
}
///插入到OutMap
OutMap.insert(pair
}
}
}
Print(OutMap,n,Max);
OutMap.clear();
}
int main()
{
int n;
map
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
for(iter = InMap.begin();iter != InMap.end();iter++)
{
cout<
cout<<n<<endl;
}
return ;
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章