Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Санкт-Петербургский Государственный Электротехнический
Университет «ЛЭТИ» им. Ульянова Ленина
Кафедра АСОИУ
Отчет о выполнении курсовой работы
по программированию
«Обработка растровых изображений»
Выполнил: Лукин Р.О.
Преподаватель: Пелевин М.
Факультет: КТИ
Группа №: 2363
СанктПетербург, 2012 г
Содержание
Введение 3
Входные и выходные данные 4
Описание алгоритма обработки 5
Реализация алгоритма 6
Заключение 8
Список использованной литературы 9
Приложение 1 10
Введение
В данной курсовой работе рассмотрены основные принципы обработки растрового изображения путем применения матрицы свертки.
В первой части работы ставится цель и находится алгоритмическое решение задачи, во второй части приводится реализация алгоритма. В качестве программного средства используется компилятор mingw gcc, который уже была использована мной при выполнении лабораторных работ по данному курсу.
Результат работы программы можно увидеть на Рис.1.
Рис.1 Слева изображение до преобразования, справа после
Входные и выходные данные
При вызове программы ей передаются два параметра:
1) Название 24 битного изображения в формате bmp(которое обязательно должно находиться в текущем каталоге), которое необходимо преобразовать;
2) Название изображения, которое получится путем применения матрицы свертки к преобразуемому изображению.
В результате выполнения программы в текущем каталоге появится файл с именем заданным вторым параметром.
Описание алгоритма обработки
Рис.2 div коэффициент нормирования.
В качестве исходных данных выступают матрицы пикселей RGB каналов.
Преобразования происходит следующим образом. Каждый элемент исходной матрицы умножается на центральное значение матрицы ядра. Кроме этого на соответствующие значения умножаются окружающие его элементы (при размере ядра 3x3 их будет 8), после чего результаты суммируются и принимаются как преобразованное значение. Далее преобразованное значение делится на коэффициент нормирования для того, чтобы средняя интенсивность оставалась неизменной. Пример такого преобразования показан на Рис.2.
Реализация алгоритма
При описании структур используются директива выравнивания данных:
#pragma pack(push)
#pragma pack(pop).
Заголовки BMP файла описываются в структурах header, iHeader.
#pragma pack(push)
#pragma pack(1)
struct header
{
unsigned char b1,b2;
unsigned long bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned long bfOffBits;
};
struct BGR
{
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
} ;
struct iHeader
{
unsigned long biSize;
long biWidth;
long biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned long biCompression;
unsigned long biSizeImage;
long biXPelsPerMeter;
long biYPelsPerMeter;
unsigned long biClrUsed;
unsigned long biClrImportant;
};
#pragma pack(pop)
Мы считываем заголовки в переменные head, iHead и перемещаемся на саму матрицу пикселей, пропустив палитру, в силу того что 24 битный формат беспалитровый.
fread(&head,sizeof(header),1,input);
fread(&iHead,sizeof(iHeader),1,input);
fseek(input,iHead.biBitCount+30, SEEK_SET);
После чего мы считываем пиксели в массив структур matrix:
for (int i=0;i<=iHead.biHeight;i++)
{
for(int j=0;j<iHead.biWidth;j++)
{
fread(&matrix[i][j],sizeof(BGR),1,input);
}
}
Задаем матрицу свертки с помощью которой мы преобразуем наше изображение:
float filter[filterWidth][filterHeight] =
{
1, 2, 1,
2, 4, 2,
1, 2, 1
};
Применим матрицу свертки к каждому пикселю и запишем результат:
for (int i = 0;i<=iHead.biHeight;i++)
{
for (int j = 0; j<iHead.biWidth;j++)
{
float red = 0,green = 0,blue = 0;
BGR pixel;
for (int x = 0;x<filterHeight;x++)
{
for (int y = 0;y<filterWidth;y++)
{
int W = (i - filterHeight / 2 + x + iHead.biHeight) % iHead.biHeight;
int H = (j - filterWidth / 2 + y + iHead.biWidth) % iHead.biWidth;
blue += matrix[W][H].rgbBlue*filter[x][y];
green += matrix[W][H].rgbGreen*filter[x][y];
red += matrix[W][H].rgbRed*filter[x][y];
}
}
pixel.rgbBlue = min(max(int(blue/divide+offset), 0),255);
pixel.rgbGreen = min(max(int(green/divide+offset), 0),255);
pixel.rgbRed = min(max(int(red/divide+offset), 0),255);
fwrite(&pixel,sizeof(BGR),1,output);
}
}
}
Полный листинг программы см. Приложение 1.
Заключение
В ходе курсовой работы было произведено детальное ознакомление со структурами растровых изображений.
Исходя из полученного результата, можно сказать что способ преобразования изображений путем применения матрицы свертки к матрицам RGB каналов изображения, достаточно эффективен.
Думаю что программу можно доработать, использовав более быстрые алгоритмы перемножения матриц, а так же включив библиотеки работы с изображениями.
СПИСОК ЛИТЕРАТУРЫ
Приложение 1 Полный листинг программы
#include <iostream>
#include <fstream>
#include <string.h>
#include <algorithm>
using namespace std;
#pragma pack(push)
#pragma pack(1)
struct header
{
unsigned char b1,b2;
unsigned long bfSize;
unsigned short bfReserved1;
unsigned short bfReserved2;
unsigned long bfOffBits;
};
struct BGR
{
unsigned char rgbBlue;
unsigned char rgbGreen;
unsigned char rgbRed;
} ;
struct iHeader
{
unsigned long biSize;
long biWidth;
long biHeight;
unsigned short biPlanes;
unsigned short biBitCount;
unsigned long biCompression;
unsigned long biSizeImage;
long biXPelsPerMeter;
long biYPelsPerMeter;
unsigned long biClrUsed;
unsigned long biClrImportant;
};
#pragma pack(pop)
int main(int argc, char *argv[])
{
FILE *input,*output;
input = fopen(argv[1],"rb");
output = fopen(argv[2],"wb");
header head;
iHeader iHead;
//file::read
fread(&head,sizeof(header),1,input);
fread(&iHead,sizeof(iHeader),1,input);
fseek(input,iHead.biBitCount+30, SEEK_SET);
BGR matrix[iHead.biHeight+1][iHead.biWidth];
for (int i=0;i<=iHead.biHeight;i++)
{
for(int j=0;j<iHead.biWidth;j++)
{
fread(&matrix[i][j],sizeof(BGR),1,input);
}
}
//filter
const int filterWidth = 3, filterHeight = 3;
int divide = 9, offset = 0;
//convolution matrix
float filter[filterWidth][filterHeight] =
{
1, 2, 1,
2, 4, 2,
1, 2, 1
};
//write headers and palette
fwrite(&head, sizeof(header), 1, output);
fwrite(&iHead, sizeof(iHeader), 1, output);
fwrite(0, sizeof(unsigned char), 30, output);
//manipulation with pixels and write it to file
for (int i = 0;i<=iHead.biHeight;i++)
{
for (int j = 0; j<iHead.biWidth;j++)
{
float red = 0,green = 0,blue = 0;
BGR pixel;
for (int x = 0;x<filterHeight;x++)
{
for (int y = 0;y<filterWidth;y++)
{
int W = (i - filterHeight / 2 + x + iHead.biHeight) % iHead.biHeight;
int H = (j - filterWidth / 2 + y + iHead.biWidth) % iHead.biWidth;
blue += matrix[W][H].rgbBlue*filter[x][y];
green += matrix[W][H].rgbGreen*filter[x][y];
red += matrix[W][H].rgbRed*filter[x][y];
}
}
pixel.rgbBlue = min(max(int(blue/divide+offset), 0),255);
pixel.rgbGreen = min(max(int(green/divide+offset), 0),255);
pixel.rgbRed = min(max(int(red/divide+offset), 0),255);
fwrite(&pixel,sizeof(BGR),1,output);
}
}
}