Реферат: Программа фильтрации шумов

Задание.

Создать программу, осуществляющую фильтрацию шумов врастровых изображениях методами усредняющего, порогового и медианного фильтров.

Программа написана на языкеObject Pascal и выполняется в среде Win32. Общий вид программы показан на рис.№ 1.

/>

Рис. № 2. Общий вид главного окна программы c загруженнымисходным изображением.

1. Усредняющий фильтp.

Алгоритм работы усредняющего фильтра заключается в заменезначения яркости в

текущем пикселе на среднюю яркость, вычисленную по его 8окрестностям, включая и сам элемент. Этот фильтр является самым простым. Кнедостаткам его можно отнести сглаживание ступенчатых и пилообразных функций.Кроме того пиксели, имеющее существенно отличное значение яркости и являющимисяшумовыми могут вносить значительный вклад в результат обработки.

Реализация фильтра представлена в виде процедуры:

 Procedure AverageFilter(Value:Integer);

 Данная процедура осуществляет алгоритм усредняющегофильтра применительно к объекту TBitmap. В него предварительно должна бытьзагружено изображение (Рис. № 2). Результат работы усредняющего фильтра можноувидеть на рис. № 3. Параметр Value – порог при котором производятсяманипуляции с пикселом.

Procedure TMainForm.AverageFilter;

var

 PrevisionLine:pByteArray;

 CurrentLine:pByteArray;

 NextLine:pByteArray;

 I,J:Integer;

 Summ:Integer;

begin

 if Image1.Picture.Bitmap.PixelFormat = pf8bit then

 begin

 for I := 0 to Image1.Picture.Bitmap.Height — 1 do

 begin

 CurrentLine := Image1.Picture.Bitmap.ScanLine[I];

 for J := 0 to Image1.Picture.Bitmap.Width — 1 do

 begin

 Summ := 0;

 if I > 0 then

 begin

 PrevisionLine := Image1.Picture.Bitmap.ScanLine[I — 1];

 if J > 0 then

 begin

 Summ := Summ + PrevisionLine^[J — 1];

 end;

 Summ := Summ + PrevisionLine^[J];

 if J + 1 < Image1.Picture.Bitmap.Width then

 begin

 Summ := Summ + PrevisionLine^[J + 1];

 end;

 end;

 if J > 0 then

 begin

 Summ := Summ + CurrentLine^[J — 1];

 end;

 Summ := Summ + CurrentLine^[J];

 if J + 1 < Image1.Picture.Bitmap.Width then

 begin

 Summ := Summ + CurrentLine^[J + 1];

 end;

 if I + 1 < Image1.Picture.Bitmap.Height then

 begin

 NextLine := Image1.Picture.Bitmap.ScanLine[I + 1];

 if J > 0 then

 begin

 Summ := Summ + NextLine^[J — 1];

 end;

 Summ := Summ + NextLine^[J];

 if J + 1 < Image1.Picture.Bitmap.Width then

 begin

 Summ := Summ + NextLine^[J + 1];

 end;

 end;

 if (Summ div 9) <= Value then

 CurrentLine^[J] := Summ div 9;

 end;

 end;

 Image1.Visible := False;

 Image1.Visible := True;

 N4.Enabled := True;

 end

 else

 MessageBox(Handle,'Такой формат файла пока неподерживается...',

 'Слабоват я пока...',MB_OK or MB_ICONSTOP orMB_APPLMODAL);

end;

/>

Рис. № 3. Результат работы усредняющего фильтра.

2. Пороговый фильтр.

Пороговый фильтр является модификацией усредняющего, иотличие заключается

том, что замена значения яркости на среднее производитсятолько в том случае, если разность между значением яркости и полученным среднимпревышает установленный порог. Выбор порога осуществляется в специальномдиалоговом окне (Рис. 4). Для произведения фильтрации используется процедураAverageFilter, показанная в пункте 1.

/>

Рис. № 4.Выбор коэффициента усреднения порогового фильтра.

/>

Рис. № 5. Результат работы порогового фильтра.

3. Медианный фильтр.

Одномерный медианный фильтр представляет собой скользящееокно охватывающее нечетное число элементов изображения. Центральный элементзаменяется медианой элементов изображения в окне. Медианой дискретнойпоследовательности М элементов при нечетном 1 называют элемент, для которогосуществует (М-1)/2 элементе меньших или равных ему по величине и (М-1)/2элементов больших или равных ему по величине.

Медианный фильтр в одних случаях обеспечивает подавлениешума, а в других — вызывает нежелательное подавление сигнала. Медианный фильтрне влияет на пилообразные и ступенчатые функции, что обычно является полезнымсвойством, однако он подавляет импульсные сигналы, длительность которыхсоставляет менее половины ширины окна. Фильтр также вызывает уплощение вершинытреугольной функции.

Возможны различные стратегии применения медианного фильтрадля подавления шумов. Одна из них рекомендует начинать с медианного фильтра,окно которого охватывает три элемента изображения. Если ослабление сигналанезначительно, то окно расширяется до пяти элементов. Так поступают до тех пор,пока медианная фильтрация начнет приносить больше вреда, чем пользы. Другаявозможность состоит в каскадной медианной фильтрации сигнала с использованиемфиксированной или изменяемой ширины окна. В общем случае те области, которыеостаются без изменения после однократной обработки, не меняются и послеповторной обработки. Области, в которых длительность импульсных сигналовсоставляет менее половины ширины окна, будут подвергаться изменениям послекаждого цикла обработки. Концепцию медианного фильтра можно легко обобщить надва измерения, применяя окно прямоугольной или близкой к круговой формы.

Для реализации медианного фильтра используется следующийкод:

procedure TMainForm.N16Click(Sender: TObject);

var

 PixelArray:array of Byte;

 Value:Byte;

 CurrentLine:pByteArray;

 BoxCurrentLine:pByteArray;

 Vert,Hor:Integer;

 VertB,HorB:Integer;

 Counter:Integer;

 Temp:Byte;

begin

 ValueForm.Caption := 'Размер окна фильтра n X n';

 ValueForm.TrackBar1.Min := 3;

 ValueForm.TrackBar1.Max := 9;

 ValueForm.TrackBar1.Frequency := 2;

 ValueForm.Edit1.ReadOnly := True;

 if ValueForm.Execute(Value) then

 begin

 SetLength(PixelArray,Value*Value);

 if Image1.Picture.Bitmap.PixelFormat = pf8bit then

 begin

 for Vert := 0 to Image1.Picture.Bitmap.Height — 1 do

 begin

 CurrentLine := Image1.Picture.Bitmap.ScanLine[Vert];

 for Hor := 0 to Image1.Picture.Bitmap.Width — 1 do

 begin

 // Заносим все пиксели окошка в массив

 Counter := 0;

 for VertB := (Vert — (Value div 2)) to (Vert + (Value div2)) do

 begin

 if (VertB >= 0) and (VertB <Image1.Picture.Bitmap.Height) then

 BoxCurrentLine := Image1.Picture.Bitmap.ScanLine[VertB];

 for HorB := (Hor — (Value div 2)) to (Hor + (Value div 2))do

 begin

 if (HorB >= 0) and (VertB >= 0) and

 (HorB < Image1.Picture.Bitmap.Width) and

 (VertB < Image1.Picture.Bitmap.Height) then

 PixelArray[Counter] := BoxCurrentLine^[HorB]

 else

 PixelArray[Counter] := 0;

 Inc(Counter);

 end;

 end;

 // Сортируем массив

 for VertB := 0 to Value*Value — 1 do

 begin

 for HorB := VertB to Value*Value — 1 do

 begin

 if PixelArray[VertB] > PixelArray[HorB] then

 begin

 Temp := PixelArray[VertB];

 PixelArray[VertB] := PixelArray[HorB];

 PixelArray[HorB] := Temp;

 end;

 end;

 end;

 // Берем то что посередине и присваиваем текущему пикселю

 CurrentLine^[Hor] := PixelArray[((Value*Value) div 2) +1];

 end;

 end;

 Image1.Visible := False;

 Image1.Visible := True;

 N4.Enabled := True;

 end

 else

 MessageBox(Handle,'Такой формат файла пока неподдерживается...',

 'Слабоват я пока...',MB_OK or MB_ICONSTOP orMB_APPLMODAL);

 end;

end;

Результат работы фильтра можно увидеть на рис. № 6.

/>

Рис. № 6. Начало работы медианного фильтра – запрос наразмер окна фильтра.

4. Заполнение объекта другим цветом.

Для упрощения алгоритма слудующая процедура заполняетграфические объекты только белым цветом, однако путем простого добавлениядиалогового окна с вопросом о цвете заполнения можно добиться заполненияобъектов любым цветом.

procedure TMainForm.Image1MouseDown(Sender: TObject;Button: TMouseButton;

 Shift: TShiftState; X, Y: Integer);

var

 TargetPixel:Byte;

 ChangeCount:Integer;

 CurrentLine:pByteArray;

 PrevLine:pByteArray;

 NextLine:pByteArray;

 YOffset, XOffset:Integer;

begin

 if Image1.Picture.Bitmap.PixelFormat = pf8bit then

 begin

 // Запоминаем значение пиксела на котором щелкнули мышкой

 TargetPixel :=pByteArray(Image1.Picture.Bitmap.ScanLine[Y])^[X];

 YOffset := 0;

 // Пока число замен не станет равным 0 двигаемся вверх

 repeat

 ChangeCount := 0;

 if Y — YOffset < 0 then

 Break;

 // Берем линию

 CurrentLine := Image1.Picture.Bitmap.ScanLine[Y — YOffset];

 PrevLine := Image1.Picture.Bitmap.ScanLine[Y — YOffset — 1];

 if PrevLine[X] <> TargetPixel then

 Break;

 XOffset := 0;

 // Заполняем влево ее пока не дойдем до границы объекта

 if X — 1 >= 0 then

 while CurrentLine^[X — XOffset — 1] = TargetPixel do

 begin

 CurrentLine^[X — XOffset] := 255;

 Inc(XOffset);

 Inc(ChangeCount);

 if X — XOffset — 1 < 0 then

 Break;

 end;

 XOffset := 0;

 // Заполняем вправо ее пока не дойдем до границы объекта

 if X + 1 < Image1.Picture.Bitmap.Width — 1 then

 while CurrentLine^[X + XOffset + 1] = TargetPixel do

 begin

 CurrentLine^[X + XOffset] := 255;

 Inc(XOffset);

 Inc(ChangeCount);

 if X + XOffset + 1 > Image1.Picture.Bitmap.Width — 1then

 Break;

 end;

 Inc(YOffset);

 until ChangeCount = 0;

 YOffset := 1;

 // Пока число замен не станет равным 0 двигаемся вниз

 repeat

 ChangeCount := 0;

 if Y + YOffset > Image1.Picture.Bitmap.Width — 1 then

 Break;

 // Берем линию

 CurrentLine := Image1.Picture.Bitmap.ScanLine[Y +YOffset];

 NextLine := Image1.Picture.Bitmap.ScanLine[Y + YOffset +1];

 if NextLine[X] <> TargetPixel then

 Break;

 XOffset := 0;

 // Заполняем влево ее пока не дойдем до границы объекта

 if X — 1 >= 0 then

 while CurrentLine^[X — XOffset — 1] = TargetPixel do

 begin

 CurrentLine^[X — XOffset] := 255;

 Inc(XOffset);

 Inc(ChangeCount);

 if X — XOffset — 1 < 0 then

 Break;

 end;

 XOffset := 0;

 // Заполняем вправо ее пока не дойдем до границы объекта

 if X + 1 < Image1.Picture.Bitmap.Width — 1 then

 while CurrentLine^[X + XOffset + 1] = TargetPixel do

 begin

 CurrentLine^[X + XOffset] := 255;

 Inc(XOffset);

 Inc(ChangeCount);

 if X + XOffset + 1 > Image1.Picture.Bitmap.Width — 1then

 Break;

 end;

 Inc(YOffset);

 until ChangeCount = 0;

 Image1.Visible := False;

 Image1.Visible := True;

 end;

end;

Результаты работы программы можно увидеть на рис. № 8 и №9.

/>

Рис. № 8. Исходное изображение для заполнения.

/>

Рис. № 9. Результат заполнения.

5. Инверсия.

Ну и напоследок сделаем инверсию нашего изображения (Рис.10, 11):

procedure TMainForm.N7Click(Sender: TObject);

var

 Line:pByteArray;

 I,J:Integer;

 Bits:Byte;

begin

 Bits := 1;

 for I :=0 to Image1.Picture.Bitmap.Height — 1 do

 begin

 Line := Image1.Picture.Bitmap.ScanLine[I];

 case Image1.Picture.Bitmap.PixelFormat of

 pf4bit:Bits := 1;

 pf8bit:Bits := 1;

 pf15bit:Bits := 2;

 pf16bit:Bits := 2;

 pf24bit:Bits := 3;

 pf32bit:Bits := 4;

 end;

 for J :=0 to Image1.Picture.Bitmap.Width * Bits — 1 do

 Line^[J] := 255 — Line^[J];

 end;

 Image1.Visible := False;

 Image1.Visible := True;

 N4.Enabled := True;

end;

/>

Рис. № 10. Исходное изображение для инверсии.

/>

Рис. № 11. Результат инверсии изображения.

еще рефераты
Еще работы по информатике, программированию