PKU ACM 1009 Edge Detection 边缘提取算法

该博客介绍了如何使用边缘提取算法处理输入图像,通过计算当前像素与周围8个像素的差值来确定输出图像。算法核心在于只在输入图像的像素变化点及其相邻点处更新输出图像。内容包括算法思路和源代码,图像数据以游程编码存储。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:Edge Detection 边缘提取算法

 

题目描述:

对输入图像进行边缘提取,算法是分别计算当前像素和周围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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值