Реферат: Фильтрация шумов в растровых изображениях методами усредняющего, порогового и медианного фильтров
Белорусский Государственный Университет
Информатики и РадиоэлектроникиКонтрольная работапо
МАГИ
Выполнил студент
группы 500501
Балахонов Е.В.
Задание.Создать программу, осуществляющую фильтрациюшумов в растровых изображениях методами усредняющего, порогового и медианногофильтров.
Програма написана на языке Object Pascal и выполняется в среде Win32. Общий вид программы показан на рис. № 1.
/>
Рис. № 1. Общий вид главного окна программы.
/>
Рис. № 2. Общий вид главного окна программы c
загруженным исходным изображением.
1. Усредняющий фильтp.Алгоритмработы усредняющего фильтра заключается в замене значения яркости в
текущем пикселе на среднююяркость, вычисленную по его 8 окрестностям, включая и сам элемент. Этот фильтрявляется самым простым. К недостаткам его можно отнести сглаживание ступенчатыхи пилообразных функций. Кроме того пиксели, имеющее существенно отличноезначение яркости и являющимися шумовыми могут вносить значительный вклад врезультат обработки.
Реализация фильтрапредставлена в виде процедуры:
ProcedureAverageFilter(Value:Integer);
Даннаяпроцедура осуществляет алгоритм усредняющего фильтра применительно к объекту TBitmap. В него предварительно должна быть загруженоизображение (Рис. № 2). Результат работы усредняющего филтра можно увидеть нарис. № 3. Параметр Value – порог при которомпроизводятся манипуляции с пикселом.
Procedure TMainForm.AverageFilter;
var
PrevisionLine:pByteArray;
CurrentLine:pByteArray;
NextLine:pByteArray;
I,J:Integer;
Summ:Integer;
begin
ifImage1.Picture.Bitmap.PixelFormat = pf8bit then
begin
for I := 0 toImage1.Picture.Bitmap.Height — 1 do
begin
CurrentLine :=Image1.Picture.Bitmap.ScanLine[I];
for J := 0 toImage1.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_OKor MB_ICONSTOP or MB_APPLMODAL);
end;
/>
Рис. № 3. Результат работы усредняющего фильтра.
2. Пороговый фильтр.Пороговыйфильтр является модификацией усредняющего, и отличие заключается
том, что замена значения яркостина среднее производится толь-ко в том случае, если разность между значениемяркости и полученным сред-ним превышает установленный порог. Выбор порогаосуществляется в специальном диалоговом окне (Рис. 4). Для произведенияфильтрации используется процедура AverageFilter,показанная в пункте 1.
/>
Рис. № 4.Выбор коэффициента усреднения пороговогофильтра.
/>
Рис. № 5. Результат работы порогового фильтра.
3. Медианный фильтр.Одномерныймедианный фильтр пред-ставляет собой скользящее окно охватывающее нечетноечисло элементов изо-бражения. Центральный элемент заменяется медианой элементовизображения в окне. Медианой дискретной последовательности М элементов принечетном 1 называют элемент, для которого существует (М-1)/2 элементе меньшихили равных ему по величине и (М-1)/2 элементов больших или равных ему пове-личине.
Медианныйфильтр в одних случаях обеспечивает подавление шума, а в других — вызываетнежелательное подавление сигнала. Медианный фильтр не влияет на пилообразные иступенчатые функции, что обычно является полез-ным свойством, однако онподавляет импульсные сигналы, длительность которых составляет менее половиныширины окна. Фильтр также вызывает уплощение вершины треугольной функции.
Возможныразличные стратегии применения медианного фильтра для подавления шумов. Одна изних рекомендует начинать с медианного фильтра, окно которого охватывает триэлемента изображения. Если ослабление сигнала незначительно, то окнорасширяется до пяти элементов. Так поступают до тех пор, пока медианнаяфильтрация начнет приносить больше вреда, чем пользы. Другая возможностьсостоит в каскадной медианной фильтрации сигнала с использованием фиксированнойили изменяемой ширины окна. В общем случае те области, которые остаются безизменения после однократной обработки, не меняются и после повторной обработки.Области, в которых длительность им-пульсных сигналов составляет менее половиныширины окна, будут подвер-гаться изменениям после каждого цикла обработки.Концепцию медианного фильтра можно легко обобщить на два измерения, применяяокно прямоугольной или близкой к круговой формы.
Для реализациимедианного фильтра используется следующий код:
procedureTMainForm.N16Click(Sender: TObject);
var
PixelArray:array ofByte;
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;
ifValueForm.Execute(Value) then
begin
SetLength(PixelArray,Value*Value);
ifImage1.Picture.Bitmap.PixelFormat = pf8bit then
begin
for Vert := 0 toImage1.Picture.Bitmap.Height — 1 do
begin
CurrentLine :=Image1.Picture.Bitmap.ScanLine[Vert];
for Hor := 0 toImage1.Picture.Bitmap.Width — 1 do
begin
// Заносим все пиксели окошка в массив
Counter := 0;
for VertB := (Vert- (Value div 2)) to (Vert + (Value div 2)) 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;
// Сортируем массив
forVertB := 0 to Value*Value — 1 do
begin
for HorB := VertBto Value*Value — 1 do
begin
ifPixelArray[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_OKor MB_ICONSTOP or MB_APPLMODAL);
end;
end;
Результатработы фильтра можно увидеть на рис. № 6.
/>
Рис. № 6. Начало работы медианного фильтра – запрос наразмер окна фильтра.
/>
Рис. № 7.Результат работы медианного фильтра с окном 3на 3.
4. Заполнение объекта другим цветом.Для упрощения алгоритма слудующаяпроцедура заполняет графические объекты только белым цветом, однако путемпростого добавления диалогового окна с вопросом о цвете заполнения можнодобиться заполнения объектов любым цветом.
procedureTMainForm.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
ifImage1.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;
// Заполняем влево ее пока не дойдем до границы объекта
ifX — 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;
// Заполняем вправо еепока не дойдем до границы объекта
ifX + 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 — 1 then
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;
// Заполняем влево ее пока не дойдем до границы объекта
ifX — 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;
// Заполняем вправо еепока не дойдем до границы объекта
ifX + 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 — 1 then
Break;
end;
Inc(YOffset);
until ChangeCount =0;
Image1.Visible :=False;
Image1.Visible :=True;
end;
end;
Результаты работы программы можноувидеть на рис. № 8 и № 9.
/>
Рис. № 8. Исходное изображение для заполнения.
/>
Рис. № 9. Результат заполнения.
5. Инверсия.Ну и напоследок сделаем инверсиюнашего изображения (Рис. 10, 11):
procedureTMainForm.N7Click(Sender: TObject);
var
Line:pByteArray;
I,J:Integer;
Bits:Byte;
begin
Bits := 1;
for I :=0 toImage1.Picture.Bitmap.Height — 1 do
begin
Line :=Image1.Picture.Bitmap.ScanLine[I];
caseImage1.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 toImage1.Picture.Bitmap.Width * Bits — 1 do
Line^[J] := 255 — Line^[J];
end;
Image1.Visible :=False;
Image1.Visible :=True;
N4.Enabled := True;
end;
/>
Рис. № 10. Исходное изображение для инверсии.
/>
Рис. № 11. Результат инверсии изображения.