Министерство образования и науки Российской Федерации
Южно-Уральский государственный университет
Кафедра Автоматика и Управление
Курсовая работа
на тему
Реализация метода главных компонент с помощью библиотеки OpenCV
Выполнил: Пушников А.А.
Группа: ПС-669
Проверил Разнополов К.О.
Дата «____» _____________2006 г.
Челябинск
2006 г Оглавление
Метод главных компонент2
Реализация метода главных компонент в OpenCV_ 3
Текст программы_ 4
Метод главных компонент (Principal Component Analysis, PCA) применяется для сжатия информации без существенных потерь информативности. Он состоит в линейном ортогональном преобразовании входного вектора X размерности N в выходной вектор Y размерности M, N. При этом компоненты вектора Y являются некоррелированными и общая дисперсия после преобразования остаётся неизменной. Матрица X состоит из всех примеров изображений обучающего набора. Решив уравнение , получаем матрицу собственных векторов , где – ковариационная матрица для X, а – диагональная матрица собственных чисел. Выбрав из подматрицу , соответствующую M наибольшим собственным числам, получим, что преобразование , где – нормализованный вектор с нулевым математическим ожиданием, характеризует большую часть общей дисперсии и отражает наиболее существенные изменения X.
Выбор первых M главных компонент разбивает векторное пространство на главное (собственное) пространство , содержащее главные компоненты, и его ортогональное дополнение .
Применение для задачи распознавания изображений имеет следующий вид. Входные вектора представляют собой отцентрированные и приведённые к единому масштабу изображения. Собственные вектора, вычисленные для всего набора изображений, называются собственными объектами (eigenobject). С помощью вычисленных ранее матриц входное изображение разлагается на набор линейных коэффициентов, называемых главными компонентами. Сумма главных компонент, умноженных на соответствующие собственные вектора, является реконструкцией изображения.
Забиваем Сайты В ТОП КУВАЛДОЙ - Уникальные возможности от SeoHammer
Каждая ссылка анализируется по трем пакетам оценки: SEO, Трафик и SMM.
SeoHammer делает продвижение сайта прозрачным и простым занятием.
Ссылки, вечные ссылки, статьи, упоминания, пресс-релизы - используйте по максимуму потенциал SeoHammer для продвижения вашего сайта.
Что умеет делать SeoHammer
— Продвижение в один клик, интеллектуальный подбор запросов, покупка самых лучших ссылок с высокой степенью качества у лучших бирж ссылок.
— Регулярная проверка качества ссылок по более чем 100 показателям и ежедневный пересчет показателей качества проекта.
— Все известные форматы ссылок: арендные ссылки, вечные ссылки, публикации (упоминания, мнения, отзывы, статьи, пресс-релизы).
— SeoHammer покажет, где рост или падение, а также запросы, на которые нужно обратить внимание.
SeoHammer еще предоставляет технологию Буст, она ускоряет продвижение в десятки раз,
а первые результаты появляются уже в течение первых 7 дней.
Для каждого изображения лица вычисляются его главные компоненты. Обычно берётся от 5 до 200 главных компонент. Остальные компоненты кодируют мелкие различия между эталоном и шум. Процесс распознавания заключается в сравнении главных компонент неизвестного изображения с компонентами всех остальных изображений. Для этого обычно применяют какую-либо метрику (простейший случай – Евклидово расстояние). При этом предполагается, что изображения, соответствующие одному эталону, сгруппированы в кластеры в собственном пространстве. Из базы данных (или тренировочного набора) выбираются изображения-кандидаты, имеющие наименьшее расстояние от входного (неизвестного) изображения.
Дальнейшее совершенствование заключалось в использовании метрики Махаланобиса и Гауссовского распределения для оценки близости изображений. Для учёта различных ракурсов в этой же работе использовалось многомодальное распределение изображений в собственном пространстве.
Основное преимущество применения анализа главных компонент – это хранение и поиск изображений в больших базах данных, реконструкция изображений.
Сервис онлайн-записи на собственном Telegram-боте
Попробуйте сервис онлайн-записи VisitTime на основе вашего собственного Telegram-бота:
— Разгрузит мастера, специалиста или компанию;
— Позволит гибко управлять расписанием и загрузкой;
— Разошлет оповещения о новых услугах или акциях;
— Позволит принять оплату на карту/кошелек/счет;
— Позволит записываться на групповые и персональные посещения;
— Поможет получить от клиента отзывы о визите к вам;
— Включает в себя сервис чаевых.
Для новых пользователей первый месяц бесплатно.
Основной недостаток – высокие требования к условиям съёмки изображений. Изображения должны быть получены в близких условиях освещённости, одинаковом ракурсе. Должна быть проведена качественная предварительная обработка, приводящая изображения к стандартным условиям (масштаб, поворот, центрирование, выравнивание яркости, отсечение фона).
Библиотека OpenCV реализует описанный выше алгоритм следующими функциями:
Функция, вычисляет собственные объекты эталонов:
void cvCalcEigenObjects( int nObjects, void* input, void* output, int ioFlags, int ioBufSize, void* userData, CvTermCriteria* calcLimit, IplImage* avg, float* eigVals ),
где
nObjects – число эталонов
input - указатель на массив изображений-эталонов (изображения глубиной 8 бит)
output – (выход функции) указатель на массив собственных объектов (изображения глубиной 32 бит)
ioFlags – флаги ввода/вывода. Для работы с памятью.
ioBufSize - размер буфера. Для работы с памятью.
userData – указатель на структуру для работы с памятью.
calcLimit – критерий прекращения вычислений. Два варианта: по количеству итераций и по ко точности (?)
avg – (выход функции) усредненное изображение эталонов
eigVals (выход функции) указатель на собственные числа (может быть NULL)
Функция, вычисляет коэффициенты разложения:
voidcvEigenDecomposite( IplImage* obj, inteigenvec_count, void* eigInput, intioFlags, void* userData, IplImage* avg, float* coeffs ),
где
obj – исследуемое изображение
eigenvec_count – число собственных объектов
eigInput - указатель на массив собственных объектов (изображения глубиной 32 бит)
ioFlags – флаги ввода/вывода. Для работы с памятью.
userData – указатель на структуру для работы с памятью.
avg - (выход функции) усредненное изображение эталонов
coeffs - (выход функции) коэффициенты разложения (?)
Функция, вычисляет проекцию исследуемого изображения на пространство собственных объектов:
void cvEigenProjection( void* input_vecs, int eigenvec_count, int io_flags, void* userdata, float* coeffs, IplImage* avg, IplImage* proj ),
где
input_vec - указатель на массив собственных объектов (изображения глубиной 32 бит)
eigenvec_count – число собственных объектов
io_flags – флаги ввода/вывода. Для работы с памятью.
userdata – указатель на структуру для работы с памятью.
coeffs - коэффициенты разложения (?)
avg - усредненное изображение эталонов
proj - проекция исследуемого изображения на пространство собственных объектов
В полученной проекции имеет смысл убрать излишние компоненты (например, с помощью функции cvThreshold – отсечение по порогу). Далее полученный результат можно сравнивать с эталонами, для принятия решения. Способов сравнения много, это может быть, например, минимальное расстояние (Евклидово) или корреляция с эталонами.
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include "cxcore.h"
#include "cv.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
IplImage **Objs, *Pro, *Object;
int obj_number=3;
HINSTANCE highgui,cv,cvaux;
IplImage* (__stdcall *cvLoadImage)( const char* filename, int iscolor);
int (__stdcall *cvSaveImage)( const char* filename, const CvArr* image);
int (__stdcall *cvNamedWindow)( const char* name, int flags );
void (__stdcall *cvShowImage)( const char* name, const CvArr* image );
IplImage* (__stdcall *cvCreateImage_)( CvSize size, int depth, int channels );
double (__stdcall *cvDotProduct_)(const CvArr* src1, const CvArr* src2 );
void (__stdcall *cvMul_)(const CvArr* src1, const CvArr* src2, CvArr* dst, double scale=1 );
void (__stdcall *cvThreshold_)(const CvArr* src, CvArr* dst, double threshold,double max_value, int threshold_type);
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void show_im(TCanvas*c,IplImage *p)
{
for(int i=0;i<p->width;i++)
for(int j=0;j<p->height;j++)
{
int a=p->imageDataOrigin[p->widthStep*j+i];
c->Pixels[i][j]=a&0x0000ff|(a<<8)&0x00ff00|(a<<16)&0xff0000;
}
}
void pca(int obj_number, IplImage **Objs,CvTermCriteria limit, IplImage *Object,IplImage *Pro)
{
CvSize size;
int m1=obj_number;
IplImage **EigObjs, *Avg;
float *coeffs;
HINSTANCE hDLL = LoadLibrary("cvaux100.dll");
if (!hDLL) return;
void (__stdcall *cvCalcEigenObjects)( int nObjects, void* input, void* output, int ioFlags, int ioBufSize, void* userData, CvTermCriteria* calcLimit, IplImage* avg, float* eigVals );
cvCalcEigenObjects = (void(__stdcall *)( int nObjects, void* input, void* output, int ioFlags, int ioBufSize, void* userData, CvTermCriteria* calcLimit, IplImage* avg, float* eigVals ))GetProcAddress(hDLL, "cvCalcEigenObjects");
if (!cvCalcEigenObjects) return;
void (__stdcall *cvEigenDecomposite)( IplImage* obj, int nEigObjs, void* eigInput, int ioFlags, void* userData, IplImage* avg, float* coeffs );
cvEigenDecomposite = (void(__stdcall *)( IplImage* obj, int nEigObjs, void* eigInput, int ioFlags, void* userData, IplImage* avg, float* coeffs ))GetProcAddress(hDLL, "cvEigenDecomposite");
if (!cvEigenDecomposite) return;
void (__stdcall *cvEigenProjection)( void* eigInput, int nEigObjs, int ioFlags, void* userData, float* coeffs, IplImage* avg, IplImage* proj );
cvEigenProjection = (void(__stdcall *)( void* eigInput, int nEigObjs, int ioFlags, void* userData, float* coeffs, IplImage* avg, IplImage* proj ))GetProcAddress(hDLL, "cvEigenProjection");
if (!cvEigenProjection) return;
EigObjs=new IplImage*[m1];
coeffs=new float[m1];
size.width = Object->width; size.height = Object->height;
Avg = cvCreateImage_( size, IPL_DEPTH_32F, 1 );
for(int i=0; i<m1; i++ )
{
EigObjs[i] = cvCreateImage_( size, IPL_DEPTH_32F, 1 );
}
cvCalcEigenObjects( obj_number, (void*)Objs, (void*)EigObjs, 0, 0, NULL, &limit, Avg, NULL );
cvEigenDecomposite( Object, m1, (void*)EigObjs, 0, NULL, Avg, coeffs );
cvEigenProjection ( (void*)EigObjs, m1, 0, NULL, coeffs, Avg, Pro );
FreeLibrary(hDLL);
// cvReleaseImage( &Avg );
// for(int i=0; i<m1; i++ )
// {
// cvReleaseImage( &EigObjs[i] );
// }
// cvFree( &coeffs);
}
void __fastcall TForm1::FormCreate(TObject *Sender)
{
highgui = LoadLibrary("highgui100.dll");
if (!highgui) return;
cvLoadImage = (IplImage*(__stdcall *)( const char* filename, int iscolor))GetProcAddress(highgui, "cvLoadImage");
if (!cvLoadImage) return;
cvSaveImage = (int(__stdcall *)( const char* filename, const CvArr* image))GetProcAddress(highgui, "cvSaveImage");
if (!cvSaveImage) return;
cvNamedWindow = (int(__stdcall *)( const char* name, int flags ))GetProcAddress(highgui, "cvNamedWindow");
if (!cvNamedWindow) return;
cvShowImage = (void(__stdcall *)( const char* name, const CvArr* image ))GetProcAddress(highgui, "cvShowImage");
if (!cvShowImage) return;
cv = LoadLibrary("cxcore100.dll");
if (!cv) return;
cvCreateImage_ = (IplImage*(__stdcall *)( CvSize size, int depth, int channels ))GetProcAddress(cv, "cvCreateImage");
if (!cvCreateImage_) return;
cvDotProduct_ = (double(__stdcall *)( const CvArr* src1, const CvArr* src2))GetProcAddress(cv, "cvDotProduct");
if (!cvDotProduct_) return;
cvMul_ = (void(__stdcall *)( const CvArr* src1, const CvArr* src2, CvArr* dst, double scale=1))GetProcAddress(cv, "cvMul");
if (!cvMul_) return;
cvaux = LoadLibrary("cv100.dll");
if (!cvaux) return;
cvThreshold_ = (void(__stdcall *)(const CvArr* src, CvArr* dst, double threshold,double max_value, int threshold_type))GetProcAddress(cvaux, "cvThreshold");
if (!cvThreshold_) return;
Objs=new IplImage*[obj_number];
Objs[0] = cvLoadImage( ".\\et\\1.bmp", 0);
show_im(Image1->Canvas,Objs[0]);
Objs[1] = cvLoadImage( ".\\et\\2.bmp", 0);
show_im(Image2->Canvas,Objs[1]);
Objs[2] = cvLoadImage( ".\\et\\3.bmp", 0);
show_im(Image3->Canvas,Objs[2]);
String fname="6.bmp";
Object = cvLoadImage((".\\in\\"+fname).c_str(), 0);
show_im(Image4->Canvas,Object);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
float e[3];
CvTermCriteria limit;
CvSize size;
size.width = Object->width; size.height = Object->height;
Pro = cvCreateImage_( size, IPL_DEPTH_8U, 1 );
limit.type = CV_TERMCRIT_EPS;
limit.max_iter = 1;
limit.epsilon = 0.1;
show_im(Image4->Canvas,Object);
pca(obj_number,Objs,limit,Object,Pro);
show_im(Image5->Canvas,Pro);
cvThreshold_(Pro,Object,200,255,CV_THRESH_BINARY);
show_im(Image6->Canvas,Object);
cvMul_(Object,Objs[0],Pro);
show_im(Image7->Canvas,Pro);
cvMul_(Object,Objs[1],Pro);
show_im(Image8->Canvas,Pro);
cvMul_(Object,Objs[2],Pro);
show_im(Image9->Canvas,Pro);
e[0]=cvDotProduct_(Object,Objs[0])/cvDotProduct_(Objs[0],Objs[0]);
e[1]=cvDotProduct_(Object,Objs[1])/cvDotProduct_(Objs[1],Objs[1]);
e[2]=cvDotProduct_(Object,Objs[2])/cvDotProduct_(Objs[2],Objs[2]);
Label1->Caption=FloatToStr(int(e[0]*1000)/1000.);
Label2->Caption=FloatToStr(int(e[1]*1000)/1000.);
Label3->Caption=FloatToStr(int(e[2]*1000)/1000.);
if(e[0]>e[1])
if(e[0]>e[2])
ShowMessage("1");
if(e[1]>e[0])
if(e[1]>e[2])
ShowMessage("2");
if(e[2]>e[1])
if(e[2]>e[0])
ShowMessage("3");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Image1Click(TObject *Sender)
{
if(OpenPictureDialog1->Execute())
{
Objs[0] = cvLoadImage(OpenPictureDialog1->FileName.c_str(), 0);
show_im(Image1->Canvas,Objs[0]);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Image2Click(TObject *Sender)
{
if(OpenPictureDialog1->Execute())
{
Objs[1] = cvLoadImage(OpenPictureDialog1->FileName.c_str(), 0);
show_im(Image2->Canvas,Objs[1]);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Image3Click(TObject *Sender)
{
if(OpenPictureDialog1->Execute())
{
Objs[2] = cvLoadImage(OpenPictureDialog1->FileName.c_str(), 0);
show_im(Image3->Canvas,Objs[2]);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Image4Click(TObject *Sender)
{
if(OpenPictureDialog1->Execute())
{
Object = cvLoadImage(OpenPictureDialog1->FileName.c_str(), 0);
show_im(Image4->Canvas,Object);
}
}
//---------------------------------------------------------------------------
|