Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

GMSAPR

.pdf
Скачиваний:
11
Добавлен:
16.03.2016
Размер:
9.01 Mб
Скачать

151

Рис. 20. Половина изображения обработана фильтром "Рельеф"

6.9 Фильтр «Размытие»

Фильтр «Размытие» — это уже пространственное преобразование. Применение этого фильтра оказывает эффект сглаживания деталей изображения. Казалось бы — зачем портить картинку, однако далее мы убедимся в том, что иногда процесс «размытия» бывает полезен.

Фильтр реализуется классом CBlur:

class CBlur: public CMatrixFilter

{

public:

CBlur();

};

Все особенности этого фильтра заключаются в его конструкторе.

const int BlurMatrix[25]=

{ 1, 1, 1, 1, 1,

1, 1, 1, 1, 1,

1, 1, 1, 1, 1,

1, 1, 1, 1, 1,

152

1,

1,

1,

1,

1

};

CBlur::CBlur()

{

m_pMatrix=BlurMatrix;

m_rangX=5;

m_rangY=5;

};

Матрица BlurMatrix задает преобразование «размытие», а в конструкторе CBlur() просто запоминается ее адрес и размер.

Эффект применения фильтра «Размытие» показан на рис. 21.

Рис. 21. Половина изображения обработана фильтром "Размытие"

Для того, чтобы эффект был явно заметен на картинке, фильтр был применен несколько раз.

6.10 Фильтр «Контур»

Фильтр «Контур» используется для выделения высокочастотных элементов изображения. Он широко применяется при распознавании образов и в машинном зрении. Высокочастотный элемент изображения — это, например,

153

светлый пиксел на однородном темном фоне, или наоборот. Практически же все очень просто. Матрица преобразования определяет весовые коэффициенты пикселов в операции сложения.

#define CONTOUR_COEFF 3 // Коэффициент четкости границ,

// его вполне можно задавать в диалоге

const int ConturMatrix[9]=

{-1*CONTOUR_COEFF, -1*CONTOUR_COEFF, -1*CONTOUR_COEFF,

-1*CONTOUR_COEFF, 8*CONTOUR_COEFF, -1*CONTOUR_COEFF,

-1*CONTOUR_COEFF, -1*CONTOUR_COEFF, -1*CONTOUR_COEFF

};

Представим теперь, что яркость пикселов, попавших в область действия матрицы, примерно одинакова. Это значит, что после сложения получится сумма, близкая к нулю. Если же преобразуемый пиксел (ему соответствует центральный элемент матрицы) имеет яркость, превышающую окружающие пикселы, то результат сложения будет больше нуля. Заметьте, что сумма элементов матрицы равна нулю. Поэтому изображение превратится в черное с белыми контурами. Если же центральный элемент матрицы сделать, например, равным 9, то тогда цвета изображения в основном не изменятся, будут выделены лишь границы.

Фильтр реализуется классом CContour:

class CContour: public CMatrixFilter

{

public:

CContour();

};

В конструкторе этого класса запоминается нужная матрица и ее размер. В общем-то, такие фильтры, как «Размытие» и «Контур», можно было бы реализовать одним классом, просто инициализировать разными матрицами.

CContour::CContour()

154

{

m_pMatrix=ConturMatrix;

m_rangX=3;

m_rangY=3;

}

На рис. 22 показан результат применения фильтра «Контур» (может быть так видит Терминатор своим страшным красным глазом).

Рис. 22. Половина изображения обработана фильтром "Контур"

6.11 Фильтр «Четкость»

Фильтр «Четкость» иллюстрирует собой единство и борьбу противоположностей, и, если вдуматься, то можно обнаружить в нем глубокий философский смысл. Для повышения четкости изображения в фильтре используется матрица «Размытие». Задача повышения четкости изображения заключается в том, чтобы выделить высокочастотные детали изображения. Светлые детали сделать ярче, темные — темнее. Для этого изображение сначала размывается, а затем определяется разность между размытым

155

изображением и оригиналом. На величину этой разницы изменяется яркость оригинала. Таким образом, однородные участки изображения не подвергнутся изменениям, а те места картинки, где присутствуют высокочастотные детали, станут контрастнее.

Фильтр реализуется классом CSharp:

class CSharp: public CMatrixFilter

{

public:

CSharp();

BOOL TransformPix(LONG x, LONG y);

};

В классе CSharp переопределен метод TransformPix(), реализация метода приведена ниже:

CSharp::CSharp()

{

m_pMatrix=BlurMatrix; m_rangX=5; m_rangY=5;

};

#define SHARP_COEFF 3 // Коэффициент увеличения резкости, // его вполне можно задавать в диалоге

BOOL CSharp::TransformPix(LONG x, LONG y)

{// Размыли пиксел

if(!CMatrixFilter::TransformPix(x, y)) return FALSE;

BYTE *pDPix=NULL, *pSPix=NULL;

pSPix=m_pSourceBM->GetPixPtr(x,y); pDPix=m_pDestBM->GetPixPtr(x, y); int d=0;

for(int c=0; c<3; c++)

{

156

d=*(pSPix+c)-*(pDPix+c); // Нашли разницу

d*=SHARP_COEFF; // Усилили разницу

// Присвоили пикселу новое значение if(*(pDPix+c)+d <0)

*(pDPix+c)=0; else

if(*(pDPix+c)+d > 255) *(pDPix+c)=255;

else

*(pDPix+c)+=d;

}

return TRUE;

}

Результат применения фильтра показан на рис. 23.

Рис. 23. Половина изображения обработана фильтром "Четкость"

157

6.12Фильтр «Удаление шума»

Вграфических редакторах часто встречаются фильтры, предназначенные для очистки изображения от различного вида шумов. Задача этих фильтров в том, чтобы каким-то образом восстановить исходную «картину мира». Методы, заложенные внутри этих фильтров, могут существенно различаться, но, наверняка, все включают в себя два этапа. Сначала определяется «шумовой» пиксел (как правило, в выявлении шума и состоит основная сложность). Затем значение шумового пиксела заменяется на новое, как правило, рассчитанное из окружающих пикселов значение. Простейшим примером такого фильтра является фильтр «Размытие». Критерий определения шума в нем предельно категоричен — все пикселы считаются шумовыми, а способ замены тоже не отличается хитростью — используется среднее арифметическое значение. Однако в ряде случаев применение такого фильтра оказывает весьма положительный эффект.

Рассмотрим далее реализацию чуть более сложного фильтра, будем называть его энтропийным. Идея этого фильтра заключается в следующем: рассматривается группа пикселов, например 5 x 5 элементов; центральный пиксел этой матрицы является тестируемым. В ходе проверки рассчитывается отклонение яркости пиксела от среднего значения яркости и оценивается влияние этого отклонения на энтропию рассматриваемого фрагмента изображения. Если фильтр решает, что такого пиксела быть не должно, его «шумное» значение заменяется новым, посчитанным на основе окружающих пикселов.

Критерий определения шума в данном методе состоит в следующем:

1. Рассматривается n пикселов, попавших в рассматриваемую область. Находится сумма отклонений яркостей пикселов от среднего значения.

n1

S = i

i=0 , (1)

158

n1

где i = b bi ; bi — значение пиксела i; b = bi n — среднее значение

i=0

яркости.

2. Определяется относительный вклад отклонения k тестируемого пиксела в значение S:

pk = Sk , (2)

где k — номер тестируемого пиксела.

n1

3. Очевидно, что pi =1 . Если в рассматриваемом фрагменте

i =0

изображения наблюдается более-менее равномерное распределение яркостей

пикселов, то и значения pi будут не сильно отличатся от 1/n. Шумовой же пиксел, как правило, «бросается в глаза» именно благодаря тому, что его яркость значительно отличается от средней яркости окружающих его пикселов.

Величина k такого пиксела больше, чем у остальных пикселов, а значит, и его вклад в значение, рассчитанное по формуле (1), будет больше и, в результате, значение pk будет превышать 1/n. Это и является критерием шумового пиксела:

если pk > 1n , значит пиксел k является шумом. (3)

Можно привести и более «наукообразное» обоснование такого критерия.

Свойства значений pi и способ их вычисления подталкивают назвать эту величину вероятностью. В теории информации для оценки количества информации используется энтропийная мера, которая является функцией вероятности и принимает свое значение при равномерном распределении, т. е. в

нашем случае, когда pi = 1n , i = 0,…,n-1. Если же какое-то из значений pk

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

159

Практика использования данного критерия показывает, что целесообразно модифицировать условие (3) к следующему виду:

pk > c 1n , (4)

где c — коэффициент (назовем его пороговым), влияющий на чувствительность критерия.

При c = 1 условие (4) превращается в (3). Опыт показывает, что наилучшие результаты достигаются при значениях c = 1,5—2,0. Впрочем, вы сами сможете поэкспериментировать со значением этого коэффициента.

После того, как нарушитель спокойствия выявлен, остается решить, что с ним делать. Здесь возможны несколько вариантов:

1.Заменить шумовой пиксел средним значением b .

2.Заменить шумовой пиксел средним значением, посчитанным с учетом значений всех пикселов, за исключением самого нарушителя.

3.Заменить шумовой пиксел средним значением, посчитанным с учетом значений всех пикселов, не удовлетворяющих критерию отбора шума. Здесь предполагается, что в рассматриваемый фрагмент может попасть более одного пиксела, удовлетворяющих критерию «шум», и при расчете нового значения их не следует учитывать.

Могут быть и другие варианты расчета замены. В рассмотренной далее реализации мы используем подход номер 3.

Наш фильтр работает с группой пикселов, что весьма похоже на матричное преобразование, поэтому реализующий его класс (назовем его CDeNoise) сделаем наследником класса CMatrixFilter:

class CDeNoise: public CMatrixFilter

{

public:

double m_dK;

int m_nWhatToDo;

160

CDeNoise();

BOOL TransformPix(LONG x, LONG y);

};

Однако, действия, выполняемые фильтром, отличаются от реализованных

в методе CMatrixFilter::TransformPix(), поэтому его придется

переопределить:

CDeNoise::CDeNoise()

{

m_pMatrix=NULL; m_rangX=5; m_rangY=5;

m_dK=2.0; m_nWhatToDo=0;

};

BOOL CDeNoise::TransformPix(LONG x, LONG y)

{

BYTE *pDPix=NULL, *pSPix=NULL; if(m_pSourceBM==NULL || m_pDestBM==NULL)

return FALSE;

//Определяем зону перекрытия изображения и матрицы

//преобразования. Это требуется для обработки

//пикселов, находящихся на границах изображения

int x_start=0; int y_start=0;

int dx=m_rangX/2, dy=m_rangY/2; if(x-dx<0) x_start=dx-x; if(y-dy<0) y_start=dy-y;

int x_finish=m_rangX; if(x+dx>m_pSourceBM->GetBMWidth())

x_finish-=(x+dx-m_pSourceBM->GetBMWidth()); int y_finish=m_rangY;

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]