题目描述:
对输入图像进行边缘提取,算法是分别计算当前像素和周围8个像素之间的差,最大值就是提取后的像素值。
输入图像和输出图像都按照游程编码存储。
主要思路:
不能计算每个像素的值,会导致TL。其实,只在以下几种情况下,输出像素与前一个像素的值不同(变化点)
1. 输入图像中某个点对比前一个点发生了变化,那么它周围的 8 个点可能是输出图像中的变化点
2. 输入图像中某一行的像素值变化了,那么当前行的左右两个端点可能是输出图像中的变化点
源代码:
#include <iostream>
using namespace std;
struct Point
{
int pos;
int val;
Point* pNext;
};
struct RLE
{
int val;
int len;
};
RLE iRLE[10000];
Point* pFirst;
int width;
int iRLElen;
int sum;
int GetVal(int pos)
{
int curpos = 0;
if((pos >= 0) && (pos < iRLE[0].len))
return iRLE[0].val;
for(int i = 1; i < iRLElen; i++)
{
curpos = curpos + iRLE[i-1].len;
if((pos >= curpos) && (pos < curpos + iRLE[i].len))
return iRLE[i].val;
}
return 0;
}
void GetBorderPoint(int pos)
{
Point* pb = pFirst;
Point* ppre = pFirst;
while(pb != NULL)
{
if(pb->pos == pos)
return;
if(pb->pos > pos)
break;
ppre = pb;
pb = pb->pNext;
}
int surround[8] = {0};
int max = 0;
int val = GetVal(pos);
if(pos >= width)
surround[0] = abs(GetVal(pos - width) - val);
if(pos < sum - width)
surround[1] = abs(GetVal(pos + width) - val);
if(pos % width > 0)
surround[2] = abs(GetVal(pos - 1) - val);
if(pos % width < width - 1)
surround[3] = abs(GetVal(pos + 1) - val);
if((pos >= width) && (pos % width > 0))
surround[4] = abs(GetVal(pos - width - 1) - val);
if((pos >= width) && (pos % width < width - 1))
surround[5] = abs(GetVal(pos - width + 1) - val);
if((pos < sum - width) && (pos % width > 0))
surround[6] = abs(GetVal(pos + width - 1) - val);
if((pos < sum - width) && (pos % width < width - 1))
surround[7] = abs(GetVal(pos + width + 1) - val);
for(int i = 0; i < 8; i++)
{
if(surround[i] > max)
max = surround[i];
}
if(pFirst == NULL)
{
pFirst = new Point;
pFirst->pos = pos;
pFirst->val = max;
pFirst->pNext = NULL;
}
else
{
Point* newpoint = new Point;
newpoint->pos = pos;
newpoint->val = max;
newpoint->pNext = pb;
ppre->pNext = newpoint;
}
}
void GetBorder(int pos)
{
GetBorderPoint(pos);
if(pos >= width)
GetBorderPoint(pos - width);
if(pos < sum - width)
GetBorderPoint(pos + width);
if(pos % width > 0)
GetBorderPoint(pos - 1);
if(pos % width < width - 1)
GetBorderPoint(pos + 1);
if((pos >= width) && (pos % width > 0))
GetBorderPoint(pos - width - 1);
if((pos >= width) && (pos % width < width - 1))
GetBorderPoint(pos - width + 1);
if((pos < sum - width) && (pos % width > 0))
GetBorderPoint(pos + width - 1);
if((pos < sum - width) && (pos % width < width - 1))
GetBorderPoint(pos + width + 1);
GetBorderPoint((pos / width) * width);
GetBorderPoint((pos / width + 1) * width - 1);
}
void PrintResult()
{
cout << width << endl;
Point* pb = pFirst;
Point* preb = pFirst;
int prepos = 0;
int preval = pFirst->val;
while(pb != NULL)
{
if(pb->val != preval)
{
cout << preval << " " << pb->pos - prepos << endl;
preval = pb->val;
prepos = pb->pos;
}
preb = pb;
pb = pb->pNext;
delete preb;
}
cout << preval << " " << sum - prepos << endl;
cout << "0 0" << endl;
}
int main()
{
while(true)
{
cin >> width;
if(!width) break;
iRLElen = 0;
sum = 0;
pFirst = NULL;
memset(iRLE, 0, sizeof(iRLE));
while(true)
{
cin >> iRLE[iRLElen].val >> iRLE[iRLElen].len;
sum = iRLE[iRLElen].len + sum;
if(iRLE[iRLElen].len == 0)
break;
iRLElen++;
}
int curpos = 0;
GetBorder(curpos);
GetBorder(curpos + iRLE[0].len - 1);
for(int i = 1; i < iRLElen; i++)
{
curpos = curpos + iRLE[i-1].len;
GetBorder(curpos);
GetBorder(curpos + iRLE[i].len - 1);
}
PrintResult();
}
cout << "0" << endl;
return 0;
}