Portfolio[UWM] Techniki Multimedialne / PIRO

Canny


Zadanie
zaimplementować algorytmy Canny’ego

Obrazem wynikowym będzie bitmapa, zawierająca informacje o krawędziach bitmapy.

ma parametry funkcji: 
  • _BitMap źródło obrazka, 
BitMap Canny(BitMap _BitMap)
{
	// ETAP I
	strEl oMGauss = {
		3,
		3,
		{
			{1/16.0, 2/16.0, 1/16.0},
			{2/16.0, 4/16.0, 2/16.0},
			{1/16.0, 2/16.0, 1/16.0}
		}
	};
	BitMap oStage_I = filter(_BitMap, oMGauss);
	

	// ETAP II Utworzenie Gradient MOD i informacji o kątach
	strEl vGradient = {
		3,
		3,
		{
			{1, 2, 1},
			{0, 0, 0},
			{-1, -2, -1}
		}
	};
	BitMap oStage_II_GRADIENT_A = filter(oStage_I, vGradient);
	strEl oTransposition;
	oTransposition.Width = vGradient.Width;
	oTransposition.Height = vGradient.Height;
	for(int y = 0; y < oTransposition.Height; y++)
		for(int x = 0; x < oTransposition.Width; x++)
			oTransposition.Value[y][x] = vGradient.Value[x][vGradient.Height-y-1];
	BitMap oStage_II_GRADIENT_B = filter(oStage_I, oTransposition);

	BitMap oStage_II_A_MUL = multiply(oStage_II_GRADIENT_A, oStage_II_GRADIENT_A);
	BitMap oStage_II_B_MUL = multiply(oStage_II_GRADIENT_B, oStage_II_GRADIENT_B);
	BitMap oStage_II_MOD = sqrty(add(oStage_II_A_MUL, oStage_II_B_MUL));

	BitMap oStage_II = oStage_I;
	oStage_II.Pixels = Clone(oStage_I);
	for(int y = 0; y < oStage_II.Height; y++)
		for(int x = 0; x < oStage_II.Width; x++)
		{
			Pix oPix_A = Get_PIX(x, y, oStage_II_GRADIENT_A);
			Pix oPix_B = Get_PIX(x, y, oStage_II_GRADIENT_B);

			Pix oPix;
			if(oPix_B.Light == 0)
				oPix.Light = Ang(M_PI/2.0);
			else
				oPix.Light = Ang(atan(oPix_A.Light/(float)oPix_B.Light));

			float oL = ((oPix_A.Red+oPix_A.Green+oPix_A.Blue)/3);
			float oM = ((oPix_B.Red+oPix_B.Green+oPix_B.Blue)/3);
			if(oM == 0)
				oPix.Red = Ang(M_PI/2.0);
			else
				oPix.Red = Ang(atan(oL/(float)oM));

			oPix.Green = oPix.Red;
			oPix.Blue = oPix.Red;
			Set_PIX(x, y, oPix, oStage_II);
		}

	// ETAP III Wykorzystanie informacji o kątach... 
	BitMap oStage_III = oStage_II_MOD;
	oStage_III.Pixels = Clone(oStage_II_MOD);
	for(int y = 0; y < oStage_II.Height; y++)
		for(int x = 0; x < oStage_II.Width; x++)
		{
			Pix Zero;
			Zero.Light = 0;
			Zero.Red = 0;
			Zero.Green = 0;
			Zero.Blue = 0;

			Pix oPix = Get_PIX(x, y, oStage_II_MOD);
			Pix oAng = Get_PIX(x, y, oStage_II);
			if(oStage_II.Bits == 24)
			{
				Pix oPix_P = Get_PIX(x+1, y, oStage_II_MOD);
				Pix oPix_L = Get_PIX(x-1, y, oStage_II_MOD);

				Pix oPix_G = Get_PIX(x, y+1, oStage_II_MOD);
				Pix oPix_D = Get_PIX(x, y-1, oStage_II_MOD);

				Pix oPix_LG = Get_PIX(x+1, y+1, oStage_II_MOD);
				Pix oPix_PD = Get_PIX(x-1, y-1, oStage_II_MOD);

				Pix oPix_PG = Get_PIX(x+1, y-1, oStage_II_MOD);
				Pix oPix_LD = Get_PIX(x-1, y+1, oStage_II_MOD);

				if(oAng.Red == 255 && (oPix_G.Red > oPix.Red || oPix_D.Red > oPix.Red))
						Set_PIX(x, y, Zero, oStage_III);
				else if(oAng.Red == 100 && (oPix_PG.Red > oPix.Red || oPix_LD.Red > oPix.Red))
						Set_PIX(x, y, Zero, oStage_III);
				else if(oAng.Red == 200 && (oPix_PG.Red > oPix.Red || oPix_LD.Red > oPix.Red))
						Set_PIX(x, y, Zero, oStage_III);
				else if(oAng.Red == 150 && (oPix_L.Red > oPix.Red || oPix_P.Red > oPix.Red))
						Set_PIX(x, y, Zero, oStage_III);
				else if(oAng.Red == 50 && (oPix_LG.Red > oPix.Red || oPix_PD.Red > oPix.Red))
						Set_PIX(x, y, Zero, oStage_III);
			}
		}

	// Tutaj powinnień być IV etap...
	return oStage_III;
}

// Funkcja odpowiedzialna za zmianę kąta z danego zakresu na daną wartość.
// Można zmienić te wartości na własne, jednakże trzeba uwzględnić te zmiany w III etapie Canny
float Ang( float _Ang )
{
	_Ang += M_PI/2.0;
	if((_Ang >= 0 && _Ang < M_PI*0.125) || (_Ang > M_PI*0.75 && _Ang <= M_PI))
		return 50;
	else if(_Ang >= M_PI*0.125 && _Ang <= 3*M_PI/8.0)
		return 100;
	else if(_Ang > 3*M_PI/8.0 && _Ang <= 5*M_PI/8.0)
		return 150;
	else if(_Ang >= 5*M_PI/8.0 && _Ang <= M_PI*0.75)
		return 200;
	return 255;
}

 
Funkcje które były zrealizowane wcześniejszych artykułach :
  • filter
  • multiply
  • sqrty
  • add

  • Administracja