===================================================================================================================

Trabalho de Computação Gráfica

===================================================================================================================

Autora: Cláudia Maria Caixeta Bezerra

 

Dithering

//---------------------------------------------------------------------------------------------------------------------------------------------------------------

Este trabalho foi implementado na linguagem C utilizando o ambiente C++Builder.

//---------------------------------------------------------------------------------------------------------------------------------------------------------------

O dithering é um processo de filtragem cuja finalidade é minimizar os efeitos percentuais do contorno de quantização, neste caso de dois níveis (1 bit).

A estratégia básica dos filtros de dithering consiste em distribuir o erro local de quantização por áreas da imagem de modo que, globalmente, ele se

anule (Gomes e Velho, 1994).

Um algoritmo básico é o dithering pontual ou limiar (threshold). Esta técnica consiste na escolha de um valor limiar e avaliando cada pixel da

imagem original tornando-os branco ou preto. Como na Figura abaixo onde tem-se a imagem original e a imagem limiarizada.

 

Implementação

void __fastcall TForm1::Button1Click(TObject *Sender)

{

int i,j,aux=0;

int *histog=(int *)calloc(256,sizeof(int));

pBitmap1 = new Graphics::TBitmap();

pBitmap2 = new Graphics::TBitmap();

Image1->Width=pBitmap1->Width;

Image1->Height=pBitmap1->Height;

pBitmap2->Height=pBitmap1->Height;

pBitmap2->Width=pBitmap1->Width;

pBitmap1->Assign(Image1->Picture->Bitmap);

pBitmap2->Assign(pBitmap1);

for (int x=0;xWidth;x++) {

for (int y=0;yHeight;y++)

{ //construção do histograma

aux=(int)Image1->Canvas->Pixels[x][y];

//cálculo para transformar Tcolor em nível de cinza

aux=((aux&255)+(aux&65280)/256+(aux&16711680)/65536)/3;

histog[aux]++;

}

}

for(int x1=0;x1Width;x1++) {

for(int y1=0;y1Height;y1++){

if (((unsigned)pBitmap1->Canvas->Pixels[x1][y1] < RGB(128,128,128)))

pBitmap2->Canvas->Pixels[x1][y1]=clBlack;

else

pBitmap2->Canvas->Pixels[x1][y1]=clWhite;

}

}

Image2->Canvas->Draw(0,0,pBitmap2);

pBitmap1->FreeImage();

pBitmap2->FreeImage();

}

//-------------------------------------------------------------------

Figura 1. a)Imagem original b)Imagem após a aplicação do dithering pontual.

//==================================================================================================================

A pertubação aleatória somada à intensidade de cada pixel, descorrelaciona a intensidade do pixel da intensidade dos pixels vizinhos.

Isso faz com que o contorno de quantização não seja uma curva conexa, dificultando a percepção da fronteira que separa duas regiões de quantização distintas.

Esse algoritmo é conhecido pelo nome de dithering por modulação aleatória (Gomes e Velho, 1994). Na Figura 2, aplicou-se este algoritmo na imagem original (Figura 1).

Implementação

void __fastcall TForm1::Button2Click(TObject *Sender)

{

int i,j,aux2=0;

TColor tmp;

pBitmap1 = new Graphics::TBitmap();

pBitmap3 = new Graphics::TBitmap();

Image1->Width=pBitmap1->Width;

Image1->Height=pBitmap1->Height;

pBitmap3->Height=pBitmap1->Height;

pBitmap3->Width=pBitmap1->Width;

pBitmap1->Assign(Image1->Picture->Bitmap);

pBitmap3->Assign(pBitmap1);

for(int x1=0;x1Width;x1++) {

for(int y1=0;y1Height;y1++){

aux2=random(255);

tmp=pBitmap3->Canvas->Pixels[x1][y1]+RGB(aux2, aux2, aux2);

if(tmp < RGB(128,128,128))

pBitmap3->Canvas->Pixels[x1][y1]=clBlack;

else

pBitmap3->Canvas->Pixels[x1][y1]=clWhite;

}

}

Image3->Canvas->Draw(0,0,pBitmap3);

pBitmap1->FreeImage();

pBitmap3->FreeImage();

}

//---------------------------------------------------------------------------

Figura 2. Dithering por modulação aleatória.

//==================================================================================================================

Em contraposição a estratégia de modulação aleatória, tem-se os algoritmos que produzem pertubações determinísticas.

ORDENADO PERIÓDICO (ESTRATÉGIA BÁSICA)

Implementação

void __fastcall TForm1::Button3Click(TObject *Sender)
{
int i,j, aux=0;
TColor tmp;

pBitmap1 = new Graphics::TBitmap();
pBitmap4 = new Graphics::TBitmap();

Image1->Width=pBitmap1->Width;
Image1->Height=pBitmap1->Height;

pBitmap4->Height=pBitmap1->Height;
pBitmap4->Width=pBitmap1->Width;

pBitmap1->Assign(Image1->Picture->Bitmap);
pBitmap4->Assign(pBitmap1);


for(int x1=0;x1Width;x1++) {
for(int y1=0;y1Height;y1++){
i=x1%4;
j=y1%4;
if(pBitmap1->Canvas->Pixels[x1][y1]>pBitmap1->Canvas->Pixels[i][j])
pBitmap4->Canvas->Pixels[x1][y1]=clWhite;
else
pBitmap4->Canvas->Pixels[x1][y1]=clBlack;

}
}

Image4->Canvas->Draw(0,0,pBitmap4);

pBitmap1->FreeImage();
pBitmap4->FreeImage();


}
//---------------------------------------------------------------------------

A Figura 3 mostra a imagem resultante da implementação.

Figura 3. Algoritmo ordenado periódico.

//==================================================================================================================

O dithering ordenado por dispersão faz uma distribuição dos limiares de quantização na matriz produzindo um efeito de transição suave entre as bandas obtidas em

relação ao dithering por aglomeração. A Figura 4 mostra os resultados da aplicação dos dois algoritmos ordenados periódicos na imagem original (Figura 1).

Implementação

void __fastcall TForm1::Button4Click(TObject *Sender)

{

TColor Aux[2][2];

pBitmap1 = new Graphics::TBitmap();

pBitmap5 = new Graphics::TBitmap();

Image1->Width=pBitmap1->Width;

Image1->Height=pBitmap1->Height;

pBitmap5->Height=pBitmap1->Height;

pBitmap5->Width=pBitmap1->Width;

pBitmap1->Assign(Image1->Picture->Bitmap);

pBitmap5->Assign(pBitmap1);

Aux[0][0]=RGB(63,63,63);

Aux[0][1]=RGB(128,128,128);

Aux[1][0]=RGB(255,255,255);

Aux[1][1]=RGB(191,191,191);

for(int y1=0;y1Height;y1++) {

for(int x1=0;x1Width;x1++){

if((pBitmap1->Canvas->Pixels[x1][y1])< (Aux[x1%2][y1%2]))

pBitmap5->Canvas->Pixels[x1][y1]=clBlack;

else

pBitmap5->Canvas->Pixels[x1][y1]=clWhite;

}

}

Image5->Canvas->Draw(0,0,pBitmap5);

pBitmap1->FreeImage();

pBitmap5->FreeImage();

}

//---------------------------------------------------------------------------

void __fastcall TForm1::Button5Click(TObject *Sender)
{
TColor Vec[2][2];

pBitmap1 = new Graphics::TBitmap();
pBitmap6 = new Graphics::TBitmap();

Image1->Width=pBitmap1->Width;
Image1->Height=pBitmap1->Height;

pBitmap6->Height=pBitmap1->Height;
pBitmap6->Width=pBitmap1->Width;

pBitmap1->Assign(Image1->Picture->Bitmap);
pBitmap6->Assign(pBitmap1);


Vec[0][0]=RGB(63,63,63);
Vec[0][1]=RGB(191,191,191);
Vec[1][0]=RGB(255,255,255);
Vec[1][1]=RGB(128,128,128);

for(int y1=0;y1Height;y1++) {
for(int x1=0;x1Width;x1++){
if((pBitmap1->Canvas->Pixels[x1][y1])< (Vec[x1%2][y1%2]))
pBitmap6->Canvas->Pixels[x1][y1]=clBlack;
else
pBitmap6->Canvas->Pixels[x1][y1]=clWhite;
}
}

Image6->Canvas->Draw(0,0,pBitmap6);

pBitmap1->FreeImage();
pBitmap6->FreeImage();

}
//---------------------------------------------------------------------------

 

Figura 4. a)Dispersed b)Clustered

//==================================================================================================================

E por último vai ser mostrado, neste segundo trabalho, o dithering por difusão de erro--Floyd-Steinberg que é um dithering aperiódico. Ele calcula o

erro efetivo cometido na quantização de cada elemento e o distribui pelos seus vizinhos, tentando com isto minimizar o erro global. Pode ser visto na Figura a seguir

a aplicação deste algoritmo na imagem original (Figura 1).

Implementação

void __fastcall TForm1::Button6Click(TObject *Sender)

{

int aux=0;

TColor *erro=(TColor *)calloc(256,sizeof(TColor));

// erro = new Graphics::TBitmap();

pBitmap1 = new Graphics::TBitmap();

pBitmap7 = new Graphics::TBitmap();

Image1->Width=pBitmap1->Width;

Image1->Height=pBitmap1->Height;

pBitmap7->Height=pBitmap1->Height;

pBitmap7->Width=pBitmap1->Width;

pBitmap1->Assign(Image1->Picture->Bitmap);

pBitmap7->Assign(pBitmap1);

for(int x1=0;x1Width;x1++) {

for(int y1=0;y1Height;y1++){

if(pBitmap1->Canvas->Pixels[x1][y1]<128) {

*erro=pBitmap1->Canvas->Pixels[x1][y1]-RGB(0,0,0);

// erro->Canvas->Pixels[x1][y1]=pBitmap1->Canvas->Pixels[x1][y1]-RGB(0,0,0);

pBitmap1->Canvas->Pixels[x1][y1]=clBlack;

}

else {

*erro=pBitmap1->Canvas->Pixels[x1][y1]-RGB(255,255,255);

pBitmap1->Canvas->Pixels[x1][y1]=clWhite;

}

if (y1 < Height)

pBitmap7->Canvas->Pixels[x1][y1+1]=pBitmap7->Canvas->Pixels[x1][y1+1]+(7*(*erro)/16);

if(pBitmap7->Canvas->Pixels[x1][y1+1]!=clBlack)

pBitmap7->Canvas->Pixels[x1][y1+1]=clWhite;

}

if ((x1 < Width) && (y1 < Height)){

pBitmap7->Canvas->Pixels[x1+1][y1+1]=pBitmap7->Canvas->Pixels[x1+1][y1+1]+((*erro)/16);

if(pBitmap7->Canvas->Pixels[x1][y1+1]!=clBlack)

pBitmap7->Canvas->Pixels[x1][y1+1]=clWhite;

}

if (x1 < Width){

pBitmap7->Canvas->Pixels[x1+1][y1]=pBitmap7->Canvas->Pixels[x1+1][y1]+(5*(*erro)/16);

if(pBitmap7->Canvas->Pixels[x1][y1+1]!=clBlack)

pBitmap7->Canvas->Pixels[x1][y1+1]=clWhite;

}

if ((x1 < Width) && (y1 > 1)){

pBitmap7->Canvas->Pixels[x1+1][y1-1]=pBitmap7->Canvas->Pixels[x1+1][y1-1]+(3*(*erro)/16);

if(pBitmap7->Canvas->Pixels[x1][y1+1]!=clBlack)

pBitmap7->Canvas->Pixels[x1][y1+1]=clWhite;

}

}

}

Image7->Canvas->Draw(0,0,pBitmap7);

pBitmap1->FreeImage();

pBitmap7->FreeImage();

delete erro;

}

//---------------------------------------------------------------------------

Figura 5. Dithering Floyd-Steinberg.

//==================================================================================================================

Na Figura 6 pode-se ver a aplicação, na imagem original, de todos os algoritmos abordados neste trabalho.

 

Figura 6. Imagens mostrando todas as aplicação dos algoritmos aqui expostos.

//==================================================================================================================

Código    Código(Unit)

Aplicativo    Dithering.exe(zippado)

Arquivo    Dithering(zip)

//-------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

Pg Inicial    Visão Geral