Автор работы: Пользователь скрыл имя, 24 Декабря 2012 в 22:09, контрольная работа
В данном задании рассматриваются одноместная и двухместная бинарная операция ИЛИ с изображением. Ее суть в том, чтобы увеличить яркость участков изображения, если она ниже константы.
В цветовой модели RGB для хранения значения интенсивности каждого цветового компонента выделяется один байт, т.е. интенсивность может принимать значения в диапазоне от 0(минимальная интенсивность) до 255 (28-1) (максимальная интенсивность). Цвет пикселя описывается структурой размером 3 (или 4) байта.
1. Задание №1.Написать программы, реализующие логические операции
с изображением:………………………………………………………………….3
1.1.Одноместная операция (в преобразование участвует изображение и некоторое константное значение) - операция ИЛИ с изображением.
1.2.Двухместная операция (в преобразование участвуют два изображения) - операция ИЛИ с изображением (выделение на изображении областей, которые имеют белый цвет).
2. Задание №2.Написать программы, реализующие арифметические операции с изображением:……………………………………………………….7
2.1.Одноместная (в преобразовании участвует изображение и некоторое константное значение) операция – (вычитание) с изображением.
2.2.Двухместная (в преобразовании участвуют два изображения) операция – (вычитание) с изображением (выделение на изображении областей, которые имеют белый цвет).
3. Задание №3.Написать программы, реализующие логические операции с изображением:……………………………………...……………………………11
3.1.Увеличение и уменьшение изображения с использованием метода определения неизвестных значений по ближайшему соседнему пикселю.
3.2.Увеличение и уменьшение изображения с использованием метода определения неизвестных значений с использованием кубической интерполяции.
4. Задание №4.Написать программу, реализующую масочную фильтрацию на основе заданных масок (двухмерных массивов):…………………………..18
4.1. Горизонтальный градиентный фильтр Превитта:
1 1 1
0 0 0
-1 -1 -1
4.2. Вертикальный градиентный фильтр Превитта:
-1 0 1
-1 0 1
-1 0 1
4.3. Горизонтальный градиентный фильтр Собеля:
1 2 1
0 0 0
-1 -2 -1
4.4. Вертикальный градиентный фильтр Собеля:
-1 0 1
-2 0 2
-1 0 1
5. Delphi 7………………………………………………………………………..25
Для первого случая:
void Substraction(HDC hdc)
{
DWORD c = 128;
DWORD dwColor = 0;
BYTE bRR = 0,bGG = 0,bBB = 0;
for(long y=15; y<15+HEIGHT; y++)
{
for(long x=380; x<380+WIDTH; x++)
{
dwColor = GetPixel(hdc,x,y);
bRR = (BYTE)(GetRValue(dwColor) - c);
bGG = (BYTE)(GetGValue(dwColor) - c);
bBB = (BYTE)(GetBValue(dwColor) - c);
SetPixel(hdc,x,y,RGB(bRR,bGG,
}
}
}
В функции определены переменные: с типа DWORD – значение константы, color типа DWORD – значение цвета получаемого пикселя, а также байты (BYTE) bRR, bGG, bBB, хранящие преобразованные значения каждого цветового компонента:
DWORD c = 128;
DWORD color = 0;
BYTE bRR = 0,bBB = 0,bGG = 0;
Далее расположен цикл for по переменной Y, имеющий вложенный цикл for по переменной Х. Константы HEIGHT, WIDTH определены в глобальной области видимости программы с помощью директивы препроцессора #define и определяют соответственно высоту и ширину изображения. Таким обрезом, получают значения всех пикселей исходного изображения.
Значение пикселя исходного изображения хранится в переменной dwColor.
dwColor = GetPixel(hdc,x,y);
Далее необходимо получить значение соответствующего компонента (с помощью макроса) и вычесть из него константу. Здесь необходимо отметить, что в данном случае возможно получение отрицательного значения. В то же время значение интенсивности цветового компонента не может быть отрицательным и его диапазон ограничен одним байтом. Чтобы этого не произошло, необходимо неявно преобразовать полученное значение к байтовому типу (BYTE). В этом случае значение будет равно разности, но без заема. Например 20 – 50 даст в итоге 226 (20 - 20 = 0, 0 – 1 = 255, 255 – 29 = 226.
bRR = (BYTE)(GetRValue(dwColor) - c);
bGG = (BYTE)(GetGValue(dwColor) - c);
bBB = (BYTE)(GetBValue(dwColor) - c);
SetPixel(hdc,x,y,RGB(bRR,bGG,
Далее рисуется пиксель, имеющий преобразованный цвет:
SetPixel(hdc,x,y,RGB(bRR,bGG,
Для второго случая:
void Substraction(HDC hdc)
{
DWORD dwSrcColor1=0, dwSrcColor2=0;
BYTE bRR=0,bGG=0,bBB=0;
for(long y=15; y<15+HEIGHT; y++)
{
for(long x=0; x<WIDTH; x++)
{
dwSrcColor1 = GetPixel(hdc,x+SRC1_X_OFFSET,
dwSrcColor2 = GetPixel(hdc,x+SRC2_X_OFFSET,
bBB = (BYTE)(GetBValue(dwSrcColor1) - GetBValue(dwSrcColor2));
bGG = (BYTE)(GetGValue(dwSrcColor1) - GetGValue(dwSrcColor2));
bRR = (BYTE)(GetRValue(dwSrcColor1) - GetRValue(dwSrcColor2));
SetPixel(hdc,x+RES_X_OFFSET,y,
}
}
}
Здесь также происходит объявление необходимых переменных. Так как теперь 2 исходных изображения, то необходимо хранить цвет пиксля каждого из них, поэтому объявлены две переменные типа DWORD – dwSrcColor1 и dwSrcColor2.
Затем в цикле получают значения цветов пикселей каждого из изображений, и выполняется операция вычитания между ними. Как и в первом случае, происходит неявное преобразоване к типу BYTE. Результаты преобразования каждого компонента «собирают» в DWORD макросом RGB и устанавливают новый цвет пикселя.
Выводы:
Рассмотренный алгоритм позволяет понижать яркость изображения с помощью разности цвета исходного изображения с константой или цветом соответсвующего пикселя другого изображения. Возможный недостаток – это цикличность (т.е., например, при вычитании значения 0 (интенсивность минимальная) со значением 1 получаем 255 (интенсивнось максимальная). Можно оставить значение цветового компонента минимальным, даже если разность меньше 0. Для этого необходимо заменить строки вида
bRR = (BYTE)(GetRValue(dwColor) - c);
строками:
int iTemp = (int)(GetRValue(dwColor) – c);
bRR = (iTemp < 0 ? 0 : (BYTE)iTemp);
В этом случае, если разность будет меньше нуля, значение все равно останется равным нулю.
Задание №3.
Теоретическая часть:
В данном задании рассматриваются алгоритмы изменения размеров изображения методами определения значения по ближайшему соседнему пикселю и с использованием метода кубической интерполяции.
Первый метод состоит в том,
чтобы заполнять недостающие
пиксели получаемого
На рисунке показаны фрагменты исходного и увеличенного в 2 раза изображения. Здесь каждому исходному пикселю будут соответствовать 4 новых пикселя того же цвета. При дробных значениях коэффициента масштабирования количество пикселей в получаемом изображении будет округляться (в меньшую сторону).
Это самый простой метод изменения размеров изображения. Его недостаток – отсутствие сглаживания в получаемом изображении, поэтому малейшее увеличение приведет к появлению «лестниц». Для масштабирования изображения с сохранением качества (в какой-то степени) используется интерполяция (линейная, кубическая, сплайновая и т.д.).
В данной работе рассматривается метод кубической интерполяции (а именно бикубической сплайновой интерполяции).
В последние годы интенсивно развивается новый раздел современной вычислительной математики - теория сплайнов. Сплайны позволяют эффективно решать задачи обработки экспериментальных зависимостей между параметрами, имеющих достаточно сложную структуру.
Наиболее широкое практическое применение, в силу их простоты, нашли кубические сплайны. Основные идеи теории кубических сплайнов сформировались в результате попыток математически описать гибкие рейки из упругого материала (механические сплайны), которыми издавна пользовались чертежники в тех случаях, когда возникала необходимость проведения через заданные точки достаточно гладкой кривой. Известно, что рейка из упругого материала, закрепленная в некоторых точках и находящаяся в положении равновесия, принимает форму, при которой ее энергия является минимальной. Это фундаментальное свойство позволяет эффективно использовать сплайны при решении практических задач обработки экспериментальной информации.
В общем случае для функции y = f(x) требуется найти приближение y = j (x) таким образом, чтобы f (xi) = j (xi) в точках x = xi, a в остальных точках отрезка [a, b] значения функций f(x) и j (x) были близкими между собой. При малом числе экспериментальных точек (например, 6-8) для решения задачи интерполяции можно использовать один из методов построения интерполяционных полиномов. Однако при большом числе узлов интерполяционные полиномы становятся практически непригодными. Это связано с тем, что степень интерполяционного полинома лишь на единицу меньше числа экспериментальных значений функций. Можно, конечно, отрезок, на котором определена функция, разбить на участки, содержащие малое число экспериментальных точек, и для каждого из них построить интерполяционные полиномы. Однако в этом случае аппроксимирующая функция будет иметь точки, где производная не является непрерывной, т. е. график функции будет содержать точки “излома”.
Кубические сплайны лишены этого недостатка. Исследования теории балок показали, что гибкая тонкая балка между двумя узлами достаточно хорошо описывается кубическим полиномом, и поскольку она не разрушается, то аппроксимирующая функция должна быть по меньшей мере непрерывно дифференцируемой. Это означает, что функции j (x), j'(x), j''(x) должны быть непрерывными на отрезке [a, b].
Кубическим интерполяционным сплайном, соответствующим данной функции f(x) и данным узлам xi, называется функция S(x), удовлетворяющая следующим условиям:
Алгоритм интерполяции основан на исходном коде библиотеки CxImage (файл ximatran.cpp, ximaint.cpp). Там для интерполяции используется квадрат 4 х 4 пикселя, с исходным пикселем в левом верхнем углу. Для каждого пикселя из этого квадрата вычисляется необходимый коэффициент. Далее значения цветовых компонентов умножаются на этот коэффициент и складываются с предыдущим значением.
Описание работы программ:
Обе программы представляют собой диалоговые окна с двумя кнопками – Файл… и Выход. При нажатии кнопки Файл… появляется диалоговое окно выбора файла для загрузки (должен быть формата .bmp). После этого рисуется исходное изображение, происходит его преобразование в соответствии с нужным алгоритмом и рисуется преобразованное изображение.
Краткое описание общего алгоритма
Работа алгоритма основана на функциональности стандартной библиотеке Windows пользовательского режима GDI. Она позволяет загружать изображения bmp-формата в память с помощью функции LoadImage. Полученный дескриптор битовой карты используется для дальнейших операциях с ней.
В данной работе сначала рисуется исходное изображение с помощью функции StretchBlt. Она позволяет растягивать изображение в разных пропорциях с интерполяцией и без. Новое изображение получается в результате преобразования пикселей нарисованного. Получение и установка значений интенсивностей цветовых компонентов пикселя выполняется соответственно функциями GetPixel и SetPixel.
Алгоритм интерполяции с определением значения по ближайшему соседнему пикселю.
void Operation(HDC hdc)
{
DWORD dwColor;
float fScale = 2.0f;
float dx = 0.0f,dy = 0.0f;
float destWidth = fScale*(float)WIDTH;
float destHeight = fScale*(float)HEIGHT;
for (int yy=0;yy<destHeight;yy++)
{
dy = (float)HEIGHT - (destHeight - (float)yy)/fScale +
(float)SRC_Y_OFFSET;
for (int xx=0;xx<destWidth;xx++)
{
dx = (float)WIDTH - (destWidth - (float)xx)/fScale +
(float)SRC_X_OFFSET;
dwColor = GetPixel(hdc,dx,dy);
SetPixel(hdc,RES_X_OFFSET+xx,
}
}
}
Константы WIDTH и HEIGHT определяют ширину и высоту исходного изображения, SRC_X_OFFSET и RES_X_OFFSET - смещение по оси Х соответственно исходного и нового изображения, а SRC_Y_OFFSET и RES_Y_OFFSET – смещение по оси Y.
Переменная dwColor необходима для хранения цвета пикселя. Переменная fScale задает масштаб нового изображения (в 2 раза больше предыдущего). В переменных destWidth и destHeight хранятся соответственно ширина и высота нового изображения. В переменных dx и dy хранятся вычисленные значения координат, которые необходимы для получения пикселя исходного изображения.
DWORD dwColor;
float fScale = 2.0f;
float dx = 0.0f,dy = 0.0f;
float destWidth = fScale*(float)WIDTH;
float destHeight = fScale*(float)HEIGHT;
Далее идет цикл, в который последовательно проходит по всем точкам нового изображения. Они, соответственно проецируются на старое за счет вычисления переменных dx и dy. После чего цвет точки с коодинатами dx и dy, полученный с помощью функции GetPixel, заносится в переменную dwColor и устанавливается функцией SetPixel в точке с координатами RES_X_OFFSET+xx и RES_Y_OFFSET+yy.
Алгоритм кубической интерполяции
void Operation(HDC hdc)
{
float fScale = 2.0f;
float dx = 0.0f,dy = 0.0f;
float destWidth = fScale*(float)WIDTH;
float destHeight = fScale*(float)HEIGHT;
for (int yy=0;yy<destHeight;yy++)
{
dy = (float)HEIGHT - (destHeight - (float)yy)/fScale +
(float)SRC_Y_OFFSET;
if(dy-1 <= SRC_Y_OFFSET)
dy = SRC_Y_OFFSET + 1;
if(dy+3 >= SRC_Y_OFFSET+HEIGHT)
dy = SRC_Y_OFFSET+HEIGHT-3;
for (int xx=0;xx<destWidth;xx++)
{
dx = (float)WIDTH - (destWidth - (float)xx)/fScale +
(float)SRC_X_OFFSET;
if(dx-1 <= SRC_X_OFFSET)
dx = SRC_X_OFFSET + 1;
if(dx+3 >= SRC_X_OFFSET+WIDTH)
dx = SRC_X_OFFSET+WIDTH-3;
SetPixel(hdc,RES_X_OFFSET+xx,
Interpolation(hdc,dx,dy,WIDTH,
}
}
}
В целом основная функция Operation не многим отличается от предыдущей, однако здесь основные преобразования выполняются в функции Interpolation, которая получает в качестве входных параметров дескриптор графического контекста устройства диалогового окна, координаты точки и ширину и высоту исходного изображения.
DWORD Interpolation(HDC hdc,float f_x,float f_y,int width, int height)
{
DWORD dwColor = 0;
float red=0,green=0,blue=0;
float a=0,b=0,r1=0,r2=0;
int i_x=0,i_y=0,xx=0,yy=0;
i_y = (int)floor(f_y);
a = f_y - (float)floor(f_y);
i_x = (int)floor(f_x);
b = f_x - (float)floor(f_x);
for(int m=-1; m<3; m++) //y cycle
{
r1 = KernelBSpline((float) m - a);
yy = i_y+m;
for(int n=-1; n<3; n++) //x cycle
{
r2 = r1 * KernelBSpline(b - (float)n);
xx = i_x+n;
dwColor = GetPixel(hdc,xx,yy);
red += GetRValue(dwColor) * r2;
green += GetGValue(dwColor) * r2;
blue += GetBValue(dwColor) * r2;
}
}
return RGB(red,green,blue);
}
Здесь сначала с помощью функции floor вычисляется ближайшее целое число, меньшее или равное аргументу. Эти значения заносятся в переменные i_y и i_x. Они будут использоваться для расчета координат точек квадрата, в котором выполняется интерполяция. Далее вычисляется разность между значением координаты, переданной в качестве параметра функции Interpolation, и ее ближайшим целым значением. Эта разность имеет формат числа с плавающей запятой (float). Она будет использоваться для расчета коэффициента интерполяции.
i_y = (int)floor(f_y);
a = f_y - (float)floor(f_y);
i_x = (int)floor(f_x);
b = f_x - (float)floor(f_x);
Далее в двух вложенных циклах вычисляются коэффициенты интерполяции и умножаются на значение интенсивности цветовых компонентов. Полученные значения суммируются с ранее вычисленными. Сами коэффициенты интерполяции вычисляются функцией KernelBSpline:
float KernelBSpline(const float x)
{
if (x < -2.0)
return(0.0f);
if (x < -1.0)
return((2.0f+x)*(2.0f+x)*(2.
if (x < 0.0)
return((4.0f+x*x*(-6.0f-3.0f*
if (x < 1.0)
return((4.0f+x*x*(-6.0f+3.0f*
if (x < 2.0)
return((2.0f-x)*(2.0f-x)*(2.
return(0.0f);
}
Коэффициент вычисляется в зависимости от значения переданного параметра:
r1 хранит значение коэффициента, вычисленное по оси Y, а r2 - окончательное, полученное путем умножения r1 на коэффициент по оси Х.
for(int m=-1; m<3; m++) //y cycle
{
r1 = KernelBSpline((float) m - a);
yy = i_y+m;
for(int n=-1; n<3; n++) //x cycle
{
r2 = r1 * KernelBSpline(b - (float)n);
xx = i_x+n;
dwColor = GetPixel(hdc,xx,yy);
red += GetRValue(dwColor) * r2;
green += GetGValue(dwColor) * r2;
blue += GetBValue(dwColor) * r2;
}
}
return RGB(red,green,blue);
Выводы:
Рассмотренный алгоритм определения неизвестных значений по ближайшему соседнему пикселю наиболее прост, однако приводит к возникновению эффекта «лестниц» при масштабировании изображения.
Кубическая интерполяция является наиболее качественным методом интерполяции, т.к. позволяет получать хорошие результаты даже при значительном увеличении размеров изображения. Однако, она выполняется медленнее, чем другие алгоритмы фильтрации (например, билинейная). Это связано со сложностью алгоритма и с большим количеством операций с над числами с плавающей запятой, так для этого используется FPU.