Portfolio[UWM] Techniki Multimedialne / PIRO

Filtr Medianowy

Zadanie
Zaimplementować filtr medianowy gdzie w i h oznaczają rozmiar sąsiedztwa brany pod uwagę, gdzie obie te wartości muszą być nieparzyste.

Do obrazu wynikowego jest kopiowania medianowa wartość przyjmowana przez punkty sąsiadujące z punktem "wybranym" przez środek maski. Filtrowi medianowemu towarzyszy efekt usuwania zakłóceń (szumów) w obrazie.

ma parametry funkcji:
  • _BitMap źródło obrazka,
  • _W szerokość macierzy,
  • _H wysokość macierzy,

BitMap filtermedian(BitMap _BitMap, int _W, int _H)
{
	// utworzenie wyczyszczonej nowej bitmapy ( wartość 0 dla danej składowej )
	BitMap oNew = _BitMap;
	oNew.Pixels = Clear(_BitMap);

	// dekleracja tablic pomocniczych do wyszukiwania medianej
	int* oMedian[4];
	oMedian[0] = (int*)malloc(sizeof(int) * _H * _W); // Składowe Light
	oMedian[1] = (int*)malloc(sizeof(int) * _H * _W); // Składowe Red
	oMedian[2] = (int*)malloc(sizeof(int) * _H * _W); // Składowe Green
	oMedian[3] = (int*)malloc(sizeof(int) * _H * _W); // Składowe Blue

	// proces przetwarzania 
	for(int y = 0; y < _BitMap.Height; y++)
		for(int x = 0; x < _BitMap.Width; x++)
		{
			// utworzenie możliwego maksymalnego piksela
			for(int my = 0; my < _H; my++)
				for(int mx = 0; mx < _W; mx++)
				{
					int oX = x - _W/2 + mx;
					int oY = y - _H/2 + my;
					if(oX >= _BitMap.Width || oX < 0 || oY >= _BitMap.Height || oY < 0)
						continue;

					Pix oPix = Get_PIX(oX, oY, _BitMap);
					int oIndex = my*_H + mx;
					oMedian[0][oIndex] = oPix.Light;
					oMedian[1][oIndex] = oPix.Red;
					oMedian[2][oIndex] = oPix.Green;
					oMedian[3][oIndex] = oPix.Blue;
				}
			
			// sortowanie bąbelkowe
			for(int c = 0; c < 4; c++)
				for(int i = 0; i < _W*_H; i++)
					for(int index = 0; index < _W*_H - 1; index++)
						if(oMedian[c][index] < oMedian[c][index+1])
						{
							int oV = oMedian[c][index];
							oMedian[c][index] = oMedian[c][index+1];
							// wcześniej tutaj miałem błąd, poniżej opiszę pewną sytuację...
							oMedian[c][index+1] = oV; 
} Pix oPix; // zakąłdając, że macierz powstałą na parametrach _W i _H, jest wielkosci nieparzystej // wtedy nie musimy sprawdzać gdzie jest środek mediany... oPix.Light = oMedian[0][(int)((_W*_H)/2+1)]; oPix.Red = oMedian[1][(int)((_W*_H)/2+1)]; oPix.Green = oMedian[2][(int)((_W*_H)/2+1)]; oPix.Blue = oMedian[3][(int)((_W*_H)/2+1)]; // zapisanie piksela do nowej bitmapy Set_PIX(x, y, oPix, oNew); } return oNew; }

Dzięki znajomemu odkryłem błąd w sortowaniu, tzn było tak :

			// sortowanie bąbelkowe
			for(int c = 0; c < 4; c++)
				for(int i = 0; i < _W*_H; i++)
					for(int index = 0; index < _W*_H - 1; index++)
						if(oMedian[c][index] < oMedian[c][index+1])
						{
							int oV = oMedian[c][index];
							oMedian[c][index] = oMedian[c][index+1];
							oMedian[c][index+1] = oMedian[c][index];
						}

Jak znasz działanie algorytmu Sortowania Bąbelkowe (Quicksort). Widzisz, że powyższy fragment kodu jest źle zrealizowany. 
Jednakże, dlaczego przedstawiam ten fragment kodu w tym artykule ?
Ponieważ ten fragment kodu daje lepsze rezultaty, choć już raczej Filtrem Medianowym nie można.

Efektowniejszy w :
  • przy mniejszych macierzach usuwa więcej zakłóceń/szumu,
  • przy takich samych macierzach jest mniejsze rozmazanie obrazu,
Sposobem najlepszym na pokazanie rezultatów jest pokazanie obrazków : 
Zaznaczyć muszę, że obie metody były robione z _W i _H równe 3. 

  • Administracja