public:
list<TMapElDot> map; //карта точек на изображении
TMapDot(){};
~TMapDot(){map.clear();};
};
//сопроводительна информация
class TInfo{
public:
short kol; //количество точек
short dpi; //качество исходного отпечатка (dot per inch)
CString src; //путь к образу из которого была получена информация
CTime date; //дата отпечатка
CString description; //описание
bool operator==(const TInfo &inf){return src == inf.src;}; //сравнение расположения изображений на диске
TInfo(){kol = -1; dpi = -1; /*src = ""; description = "";*/};
void Printf(FILE *fout) //запись данных в файл
{
fwrite((void *)(&kol), sizeof(kol), 1, fout);
fwrite((void *)(&dpi), sizeof(dpi), 1, fout);
int strlen = src.GetLength();
fwrite((void *)(&strlen), sizeof(int), 1, fout);
fwrite((void *)(src.GetBuffer()), strlen, 1, fout);
};
void Scanf(FILE *fin) //чтение данных из файла
{
fread((void *)(&kol), sizeof(kol), 1, fin);
fread((void *)(&dpi), sizeof(dpi), 1, fin);
int strlen;
fread((void *)(&strlen), sizeof(int), 1, fin);
char * text = new char[strlen+1];
fread((void *)(text), strlen, 1, fin);
text[strlen] = '\0';
src = text;
delete(text);
};
};
//абсолютные параметры точки
class TAbsDot{
public:
CPoint coord; //координаты
double alpha; //направление в точке
bool type; //тип точки (1- окончание, 0- раздвоение)
bool show; //видимость точки (1- видима, 0- скрыта)
public:
TAbsDot(){coord.x = -1; coord.y = -1; alpha = 0; type = false; show = false;};
~TAbsDot(){};
bool operator==(const TAbsDot &f){return (coord.x == f.coord.x && coord.y == f.coord.y && alpha == f.alpha);};
bool operator <(const TAbsDot &f){return (alpha < f.alpha);};
bool operator >(const TAbsDot &f){return (alpha > f.alpha);};
bool operator!=(const TAbsDot &f){return false;};
bool operator<=(const TAbsDot &f){return false;};
bool operator>=(const TAbsDot &f){return false;};
CString toStr()
{
CString str;
str.Format("%d %d %f %d %d\n", coord.x, coord.y, alpha, type, show);
return str;
};
};
//класс для хранения точек в _абсолютных_ параметрах
//Описание отпечатка в абсолютных параметрах
class TAbsFing: public list<TAbsDot>
{
public:
TAbsFing(){this->clear();};
~TAbsFing(){this->clear();};
bool LoadFing(CString src); //Загрузка отпечатка из файла *.sav
bool SaveFing(CString fsav); //Сохранение отпечатка в файл *.sav
};
//относительные параметры точки
class TRelDot{
public:
short l,a1,a2; //координаты точки
//l - растояние между точками
//a1 - угол между собственным направлением точки А и направлением A -> B [0, 2*M_PI)
//a2 - угол между собственным направлением точки В и направлением A -> B [0, 2*M_PI)
TAbsDot absDot; //ее абсолютные параметры (необходимо для отображения на экране совпавших точек)
public:
bool operator<(const TRelDot &f){return this->l < f.l;}
bool sortByA1(TRelDot &f){return a1 < f.a1;} //эта функция нужна для сортировки, но сортировка так и не реализованна
bool operator==(const TRelDot &f){return (this->l == f.l && this->a1 == f.a1 && this->a2 == f.a2);}
CString toStr(){CString s; s.Format("%d %d %d\n", l, a1, a2); return s;}
};
//класс для хранения _относительных_ параметров точки
typedef list<TRelDot> listTRelDot;
//Шаблон для хранения пары значений {first, second}
template <class data_t1, class data_t2> struct TPair{
data_t1 first;
data_t2 second;
TPair(data_t1 _f, data_t2 _s){first = _f; second = _s;};
};
typedef TPair<TAbsDot, TAbsDot> TPairAbsDot;
typedef TPair<listTRelDot*, listTRelDot*> TPairSur;
//результат сравнения отпечатков
struct TCompareFing{
double val; //уровень схожести отпечатков
short cDot; //количество совпавших точек
short nfng; //номер отпечатка
CString name; //файл отпечатка
list<TPairAbsDot> dots; //first - совпавшие точки на отпечатке в базе
//second - совпавшие точки на открытом отпечатке
list<TPairSur> surdots;
//окружения на одинаковых отпечатках должны быть одинаковыми,
//на этом основано сравнение "роз"
};
//Описание отпечатка в _относительных_ параметрах
class TRelFing: public list<listTRelDot>{
private:
inline double GetS(const CPoint A, const CPoint B); //растояние между точками
double GetAlpha(const CPoint A, const CPoint B); //Направлени из точки А в В [-pi,pi)
public:
TRelFing(){};
~TRelFing(){};
TRelFing *Convert(TAbsFing &fng); //конвертировать абсолютные параметры к относительным
TCompareFing Compare(TRelFing &fng); //сравнить отпечатки
};
П.1.7 ТЕКСТ МОДУЛЯ fing.cpp
#include "stdafx.h"
#include "fing.h"
bool TAbsFing::SaveFing(CString fsav)
//Сохранение отпечатка в файл *.sav
{
if(!this->size()) return false;
TAbsFing::iterator iter;
FILE *fingfile = fopen(fsav, "wb");
if(fingfile == NULL)
{
MessageBox(NULL,"Невозможно создать файл: '"+fsav+"'", "Ошибка работы с файлом", MB_OK);
return false;
}
for(iter = this->begin(); iter != this->end(); iter++)
{
TAbsDot dot = *iter;
if(iter->show) fwrite((void *)&dot, 1, sizeof(dot), fingfile);
}
fclose(fingfile);
return true;
}
bool TAbsFing::LoadFing(CString src)
//Загрузка отпечатка из файла *.sav
{
TAbsDot dot;
FILE *fingfile = fopen(src, "rb");
if(fingfile == NULL)
{
MessageBox(NULL,"Невозможно открыть файл: '"+src+"'", "Ошибка работы с файлом", MB_OK);
return false;
}
this->clear();
while(!feof(fingfile))
{
fread((void *)&dot, 1, sizeof(dot), fingfile);
this->push_back(dot);
}
this->pop_back();
fclose(fingfile);
return true;
}
///////////////////////////////////////////////////////////////////////////////////////
///TRelFing//TRelFing/TRelFing/TRelFing/TRelFing/TRelFing/TRelFing/TRelFing/TRelFing///
///////////////////////////////////////////////////////////////////////////////////////
TRelFing *TRelFing::Convert(TAbsFing &fng)
//конвертировать абсолютные параметры к относительным
{
if(fng.empty()) return this;
this->clear();
TAbsFing::iterator iterA1, iterA2;
TRelDot tmpR;
listTRelDot listDots;
double tmpa, vecAB;
for(iterA1 = fng.begin(); iterA1 != fng.end(); iterA1++)
{
for(iterA2 = fng.begin(); iterA2 != fng.end(); iterA2++)
{
if(iterA2 == iterA1) continue;
tmpR.l = (short)(GetS(iterA1->coord, iterA2->coord)+0.5); //l - растояние между точками
vecAB = GetAlpha(iterA2->coord, iterA1->coord);
tmpa = iterA1->alpha - vecAB;
if(tmpa < 0) tmpa = 2*M_PI + tmpa;
tmpR.a1 = (short)(tmpa * 180.0/M_PI +0.5); //a1 - угол между собственным направлением точки А и направлением A -> B
tmpa = iterA2->alpha - vecAB;
if(tmpa < 0) tmpa = 2*M_PI + tmpa;
tmpR.a2 = (short)(tmpa * 180.0/M_PI +0.5); //a2 - угол между собственным направлением точки В и направлением A -> B
tmpR.absDot = *iterA1; //Во всех точках хранятся одни и те же данные!(необходимо для отображения совпавших точек)
listDots.push_back(tmpR);
}
listDots.sort();
this->push_back(listDots);
listDots.clear();
}
return this;
}
inline double TRelFing::GetS(const CPoint A, const CPoint B)
//растояние между точками
{
return sqrt( (double)((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y)) );
}
double TRelFing::GetAlpha(const CPoint A, const CPoint B)
//Направлени из точки А в В [-pi,pi)
{
if(A == B) return 0.0;
double alpha;
if (A.x - B.x == 0)
{
if (A.y > B.y) alpha = M_PI_2;
else alpha = -M_PI_2;
}else
{
double a = ((double)A.y-B.y)/((double)B.x-A.x);
alpha = atan(a);
if (A.x > B.x)
{
if (alpha < 0) alpha += M_PI;
else alpha -= M_PI;
if (A.y == B.y) alpha = -M_PI;
}
}
return alpha;
}
TCompareFing TRelFing::Compare(TRelFing &fng)
//сравнить отпечаток с отпечатком из файла
{
TCompareFing ret;
ret.nfng = (short)fng.size();
const short CONFIRM_VAL = 9;
const double DELTA_L = 10.0; //ограничитель
const double DELTA_A = 10.0; //ограничитель
short confirmDot = 0; //количество совпавших СТ (спец точек)
short confirmVal = 0; //количество совпавших сопряженных СТ с текущей СТ
short needVal = (short)(min(this->size(),fng.size())/3.0 +0.5);
if(needVal > CONFIRM_VAL) needVal = CONFIRM_VAL;
listTRelDot *surroundDots1, *surroundDots2;
listTRelDot::iterator baseIter;
for(TRelFing::iterator tekFing = this->begin();
tekFing != this->end();
tekFing++)
{
for(TRelFing::iterator baseFing = fng.begin();
baseFing != fng.end();
baseFing++)
{
confirmVal = 0;
surroundDots1 = new(listTRelDot);
surroundDots2 = new(listTRelDot);
for(listTRelDot::iterator tekIter = (*tekFing).begin();
tekIter != (*tekFing).end();
tekIter++)
{
baseIter = (*baseFing).begin();
short prev, next;
prev = next = abs(baseIter->l - tekIter->l);
while(
prev >= next &&
next >= DELTA_L &&
baseIter != (*baseFing).end())
{
prev = next;
baseIter++;
next = abs(baseIter->l - tekIter->l);
}
if(prev >= DELTA_L && prev < next) continue; //нет смысла сравнивать дальше т.к. всегда будет next >= DELTA_L
for(;
baseIter != (*baseFing).end();
baseIter++)
{
int len = abs(tekIter->l - baseIter->l);
if(len >= DELTA_L) break; //нет смысла сравнивать дальше т.к. всегда будет next >= DELTA_L
int delta_a = DELTA_A;
if(
((abs(tekIter->a1 - baseIter->a1)<delta_a)||(abs(tekIter->a1 - baseIter->a1) > 360-delta_a))&&
((abs(tekIter->a2 - baseIter->a2)<delta_a)||(abs(tekIter->a2 - baseIter->a2) > 360-delta_a)))
{
confirmVal++;
surroundDots1->push_back(*baseIter);
surroundDots2->push_back(*tekIter);
break;
}
}
if(confirmVal > needVal)
{
///////////////////////////
//удалим эту точку из последующего перебора, т.к. она уже совпала
ret.dots.push_back(TPairAbsDot(baseFing->back().absDot, tekFing->back().absDot));
ret.surdots.push_back(TPairSur(surroundDots1,surroundDots2));
baseFing->clear();
fng.erase(baseFing);
confirmDot++;
break;
}
}
if(confirmVal > needVal){break;}
else{
ret.dots.push_back(TPairAbsDot(baseFing->back().absDot, tekFing->back().absDot));
ret.surdots.push_back(TPairSur(surroundDots1,surroundDots2));
surroundDots1->clear();
surroundDots2->clear();
}
}
}
ret.cDot = confirmDot;
ret.val = 0;
return ret;
}
П.1.8 ТЕКСТ МОДУЛЯ TAnalysePicture.h
#pragma once
#include "TFingPicture.h"
//MESSAGEOUT отображать отладочную информацию с помощью popup окон
//#define MESSAGEOUT true
#define MESSAGEOUT false
#define OUT_FILE "fingAnalyserOut.txt" //файл отчет
#define BLANK "blank.bmp" //пустое изображение
///////////////////////////////////////////////////////////////////////////////////
//важные параметры для обхода изображения
#define LEN_S 3 //длина малого вектора (LEN_S точек)
#define LEN_L 4 //длина большого вектора (LEN_L малых векторов)
#define KOL_L 2 //необходимое количество больших векторов
#define KOL_S LEN_L*KOL_L //необходимое количество точек
#define TEST_ALPHA 130.0 //тест на разворот вектора. Указывается угол в градусах
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
// Класс АНАЛИЗА ИЗОБРАЖЕНИЯ
///////////////////////////////////////////////////////////////////////////////////
class TAnalysePicture
{
private:
TFingPicture *pic; //Собственно сама картинка
TFingPicture *tmpPic; //копия картинки
TFingPicture *pic2; //изображение для отображения в окне
int height, width; //высота и ширина изображения
CString srcImg; //путь к изображению
int err; //Код состояния картинки
TInfo info; //сопроводительная информация
private:
int ChangeLine(list<TMapElDot>::iterator _dot, list<TMapElDot> &_map); //Обработка картинки, ее изменение
TAbsFing ReadPic(list<TMapElDot>::iterator _dot); //Нахождение на изображении спец точек
list<TMapElDot> LookPic(); //Сканирование картинки и нахождение линий на ней
inline double GetAlpha(const CPoint A, const CPoint B); //Направлени из точки А в В [-pi,pi)
inline double GetS(CPoint A, CPoint B); //растояние между точками
CPoint FindAcceptDot(CPoint dot, double alpha, bool type); //Поиск продолжения из окончания/раздвоения
bool TestFindDot(int _x, int _y);//тест точки: Разность направлений вперед и назад должно быть меньше 110 градусов
double ChangeAlphaInterval(double _alpha); //Приведение итрервала к [-pi,pi)
int DotsFilter(TAbsFing &_dots);
/*Фильтрование полученных точек отсеиваются близкостоящие направленные в противоположные строки
а так же точки слева и справа от которых нет линий*/
bool LeftDot(TAbsFing::iterator &iter);
/*Если точка является окончанием, то слева и справа от нее должны быть линии