実験4:シード充填アルゴリズム
4.1実験目的
シード充填アルゴリズム(再帰的アルゴリズム)、改良されたシード充填アルゴリズム、スキャンラインシード充填アルゴリズムを習得する
4.2実験内容
C++で関数
テンプレートライブラリを作成するためのスタックの使用
4.3アルゴリズムのアイデア
すべてのシード充填アルゴリズムのコアは、実際には再帰的アルゴリズムであり、指定されたシードポイントから開始し、すべての方向を検索し、境界に到達するまでピクセルごとに処理します。さまざまなシード充填アルゴリズムは、色と境界のみを処理します。その上。
境界充填アルゴリズムと注入充填アルゴリズムの本質は実際には同じであり、再帰と検索の両方です。唯一の違いは、境界の確認、つまり再帰の終了条件が異なることです。インジェクション塗りつぶしアルゴリズムには境界の概念がなく、接続された領域の指定された色のみが置き換えられます。境界塗りつぶしアルゴリズムは、境界の存在を強調するだけです。境界内のポイントが任意の色である限り、次のように置き換えられます。指定された色。境界塗りつぶしアルゴリズムも広く使用されています。描画ソフトウェアの「ペイントバケット」機能は、境界塗りつぶしアルゴリズムの例です。
スキャンラインシード充填アルゴリズムの基本的なプロセスは次のとおりです。シードポイント(x、y)が指定されたら、最初に、シードポイントが左右方向にあるスキャンライン上の指定された領域のセクションを充填します。それぞれ、同時にこのセクションの範囲[xLeft、xRight]を書き留めてから、このセクションに接続されている上下のスキャンライン上の特定の領域内のセクションを決定し、それらを順番に保存します。充填が完了するまで、このプロセスを繰り返します。
4.4フローチャート
(1)シード充填アルゴリズム(再帰的アルゴリズム)
(2)境界シード充填アルゴリズム(改良)
(3)スキャンラインシード充填アルゴリズム
4.5実験手順
(1)シードフィリングアルゴリズム(再帰アルゴリズム)
は、getpixelメソッドを使用してポイントの色を取得し、元の色と同じかどうかを判断します。同じでない場合は、色を新しい色に変更し、 4つの接続されたエリアを再帰的に繰り返すことで秩序を達成します。エリアの外に出ることなく、エリア内の任意の要素に到達します。
(2)境界シード塗りつぶしアルゴリズム(改良)
ポイントの色をgetpixel法で取得し、元の色と同じか、境界色と同じかを判断します。秩序を達成する地域を超えずに地域内の任意の要素に到達します。
(3)スキャンラインシード充填アルゴリズム
1)シードポイントを格納するために空のスタックを初期化し、シードポイント(x、y)をスタックにプッシュします
。2)スタックが空かどうかを判断します。スタックが空の場合は終了します。アルゴリズム、それ以外の場合は取り出します。スタックの最上位要素が現在のスキャンラインのシードポイント(x、y)として使用され、yは現在のスキャンラインです
。3)シードポイント(x、y)から開始します。 、境界まで現在のスキャンラインに沿って左右の方向を入力します。セグメントの左端と右端の座標をそれぞれxLeftとxRightとしてマークし
ます。4)xLeftから現在のスキャンラインに隣接する2つのスキャンラインy-1とy + 1の間隔[xLeft、xRight]のピクセルを確認します。 xRightの方向で検索を開始します。境界がなく、塗りつぶされていないピクセルがある場合は、これらの隣接するピクセルの右端を見つけて、シードポイントとしてスタックにプッシュし、手順(2)に戻ります。
4.6実験コード
(1)CLiHuchenView()。hにコードを追加します。
public:
void Draw();//添加画图成员
CDC* mpDC;//定义指针
void Scanseedfill(int x,int y,COLORREF oldColor,COLORREF newColor);//定义扫描线种子填充算法
void FloodFill(int x, int y, COLORREF oldcolor, COLORREF newcolor);//定义递归种子填充算法
void BoundaryFill(int x, int y, COLORREF oldcolor, COLORREF newcolor);//定义改进的种子填充算法
(2)LiHuchenView.cppを追加します。
//引入种子库
#include "stack"
using namespace std;
extern stack<CPoint> s;
(3)LiHuchenView.cppにOnDraw()を追加します。
Draw();//添加画图函数
(4)機能の追加
/*
-----------------------------------区域填充算法---------------------------------------
*/
/
//画图
/
void CLiHuchenView::Draw()
{
CDC *pDC=GetDC();//定义指针
mpDC=pDC;
POINT ptpolygon1[6]={
{
600,50},{
600,250},{
700,250},{
700,230},{
620,230},{
620,50}};//多边形坐标
mpDC->Polygon(ptpolygon1,6);//绘制多边形
// Scanseedfill(610,100,RGB(255,255,255),RGB(255,0,0));//扫描线种子填充算法
// FloodFill(610,100,RGB(255,255,255),RGB(0,255,0));//递归种子填充算法
BoundaryFill(610,100,RGB(0,0,0),RGB(0,0,255));//边界种子填充算法
}
/
//记录种子点
/
struct Seed
{
int x;int y;
};
/
//扫描线种子填充算法
/
void CLiHuchenView::Scanseedfill(int x, int y, COLORREF oldColor, COLORREF newColor)
{
stack<Seed> sp;//种子库
int xl,xr;
bool spanNeedfill;
Seed pt;
pt.x=x;pt.y=y;
sp.push(pt);
while(!sp.empty())
{
pt=sp.top();sp.pop();
y=pt.y;x=pt.x;
while(mpDC->GetPixel(x,y)==oldColor)//向右填充
{
mpDC->SetPixel(x,y,newColor);
x++;
}
xr=x-1;x=pt.x-1;
while(mpDC->GetPixel(x,y)==oldColor)//向左填充
{
mpDC->SetPixel(x,y,newColor);
x--;
}
xl=x+1;
//处理上面一条扫描线
x=xl;y=y+1;
while(x<=xr)
{
spanNeedfill=false;
while(mpDC->GetPixel(x,y)==oldColor)
{
spanNeedfill=true;
x++;
}
if(spanNeedfill)
{
pt.x=x-1;pt.y=y;
sp.push(pt);
spanNeedfill=false;
}
while((mpDC->GetPixel(x,y)!=oldColor)&&x<=xr) x++;
}
//处理下面一条扫描线
x=xl;y=y-2;
while(x<=xr)
{
spanNeedfill=false;
while(mpDC->GetPixel(x,y)==oldColor)
{
spanNeedfill=true;
x++;
}
if(spanNeedfill)
{
pt.x=x-1;pt.y=y;
sp.push(pt);
spanNeedfill=false;
}
while((mpDC->GetPixel(x,y)!=oldColor)&&x<=xr) x++;
}
}
}
/
//递归种子填充算法
/
void CLiHuchenView::FloodFill(int x, int y, COLORREF oldcolor, COLORREF newcolor)
{
//判断当前颜色
if (mpDC->GetPixel(x, y) == oldcolor)
{
mpDC->SetPixel(x, y,newcolor); //修改颜色
//寻找周围的临近点,递归
FloodFill(x, y + 1, oldcolor, newcolor);
FloodFill(x, y - 1, oldcolor, newcolor);
FloodFill(x - 1, y, oldcolor, newcolor);
FloodFill(x + 1, y, oldcolor, newcolor);
}
}
/
//改进的种子填充算法(边界填充)
/
void CLiHuchenView::BoundaryFill(int x, int y, COLORREF boundarycolor, COLORREF newcolor)
{
//判断是否为边界颜色或者新的颜色
//默认边界颜色为黑色
if(mpDC->GetPixel(x, y) != boundarycolor &&mpDC->GetPixel(x, y) !=newcolor)
{
mpDC->SetPixel(x, y, newcolor); //修改颜色
//寻找周围的临近点,递归
BoundaryFill(x, y + 1, boundarycolor, newcolor);
BoundaryFill(x, y - 1, boundarycolor, newcolor);
BoundaryFill(x - 1, y, boundarycolor, newcolor);
BoundaryFill(x + 1, y, boundarycolor, newcolor);
}
}
4.7実験結果の表示
(1)スキャンラインシード充填アルゴリズム
(2)再帰シード充填アルゴリズム
(3)境界シード充填アルゴリズム(改良)