Система идентификации личности по отпечаткам пальцев. Подсистема анализа изображения
Подсистема анализа изображения отпечатка пальца в составе системы идентификации личности по отпечаткам пальцев на основе папиллярного узора для дальнейшего распознавания личности. Характеристика функциональных возможностей системы и код програмы.
Рубрика | Программирование, компьютеры и кибернетика |
Вид | дипломная работа |
Язык | русский |
Дата добавления | 01.07.2008 |
Размер файла | 3,1 M |
Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже
Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.
Помещение, в котором производится разработка данного проекта, необходимо оборудовать средствами оповещения о пожаре, а также средствами для тушения пожара.
В данном разделе дипломной работы был проведен анализ вредных и опасных производственных факторов, действующих на рабочем месте инженера-программиста. Среди них были выделены: постоянное напряжение глаз, влияние электростатических и электромагнитных полей, длительное неизменное положение тела, шум. Был проведен анализ и указан комплекс мер по пожаробезопасности и электробезопасности. Проведен расчет эргономических требований к рабочему месту инженера-программиста. Созданные условия должны обеспечивать комфортную ра-бо-ту. На основании изученной литературы по данной проблеме, были указаны опти-маль-ные размеры рабочего стола и кресла, параметры рабочей поверхности, а также сформулированы предложения по улучшению параметров рабочего места. Соблюдение условий, определяющих оптимальную организацию рабочего места инженера-программиста, позволит сохранить хорошую работоспособность в течение всего рабочего дня, повысит как в количественном, так и в качественном отношениях производительность труда программиста, что в свою очередь будет способствовать быстрейшей разработке и отладке программного продукта.
ЗАКЛЮЧЕНИЕ
В результате проделанной работы был разработан метод автоматизации поиска схожих отпечатков и реализована программа, для данного метода. Программа позволяет за приемлемое время автоматически определять личность по отпечатку пальца посредством выделения локальных особенностей. По сравнению с ручным определением получен значительный выигрыш в скорости и удобстве использования.
Разработанная подсистема является неотъемлемой частью системы идентификации личности. Обработка позволяет улучшить качество отпечатка. Получаемые характеристики достаточно полно описывают изображение, это представление удобно для хранения и позволяет провести распознавание с высокой степенью точности.
Созданную подсистему следует рассматривать как исследовательскую подсистему, предназначенную для преобразования растрового представления изображения к структурному представлению, которое пригодно для компактного хранения и дальнейшей разработки в направлении большей автоматизации и других сфер деятельности.
Разработанная система реализует новый вид функциональности - подготовку изображений к автоматизированному структурному анализу.
ЛИТЕРАТУРА
1) Биометрические технологии - альтернатива персональным идентификационным номерам и паролям // k2kapital.com Аналитические обзоры 8 мая 2000. http://www.k2kapital.com/archives/research/rs20000508.html Проверено: 16.05.06.
2) Завгородний В.И. Комплексная защита информации в компьютерных системах // Учебное пособие. - М.: Мир, 2001. - 264 с.
3) Виталий Задорожный. Области применения и принципы построения биометрических систем // PC Magazine/Russian Edition 21 апреля 2004. http://www.pcmag.ru/?ID=447314&4Print=1. Проверено 16.05.06.
4) Долгий И.Д. Ковалев С.М., Кулькин С.А. К вопросу об идентификации личности в системе «Диспетчерской централизации» // Ростовский государственный университет путей сообщения, 2003. http://pitis.tsure.ru/files24/03.pdf. Проверено 16.05.06.
5) ООО «Биолинк Технолоджис». Продукты: BioLink BioTime 2006; BioLink Authenteon Software Appliance (ASA) // BioLink, 2001. biolink.ru Проверено 16.05.06.
6) Документация «Microsoft IntelliMouse Explorer with Fingerprint Reader» // Microsoft, 2004.
7) Первый телефон с функцией распознавания отпечатков пальцев. // ИА Клерк.Ру, 04.08.2004. http://www.klerk.ru/soft/n/?11433. Проверено 16.05.06.
8) Бойер, П. Флостер Д. Использование Adobe Photoshop 7. Специальное издание. - М.: Вильямс, 2004.
9) Руководство пользователя для FineReader 8.0 // 1996-2006 ABBYY Software. http://www.abbyy.com/DLCenter/downloadcentermanager.aspx?file=/fr80/guides/Guide_Russian.pdf. Проверено 16.05.06.
10) Сканеры отпечатков пальцев. // BIOMETRICS.RU 2002-2006, http://cyberdefend.narod.ru/biometric_devices.htm Проверено 16.05.06.
11) Задорожный В.В. Идентификация по отпечаткам пальцев. // PC Magazine/Russian Edition №1, 2004, - C. 25 - 35.
12) Геннадий Рябов. Современные технологии идентификации личности по отпечатку пальца с использованием емкостных датчиков. // radioradar.net, 2004. http://www.radioradar.net/staty/identif_otpech.php. Проверено 16.05.06.
13) Гончаров Д., Салихов Т. DirectX 7.0 для программистов // - С.-Пб.: Питер, 2001. - 528 с.
14) Прэтт У. Цифровая обработка изображений. Т. 1. - М.: Мир, 1982. - 312 с.
15) Дуда Р., Харт П. Распознавание образов и анализ сцен. - М.: Мир, 1976. - 511 с.
16) Аммерал Л. Принципы программирования в машинной графике. - М.: Сол Систем, 1992.
17) Анисимов Б.В., Курганов В.Д., Злобин В.К. Распознавание и цифровая обработка изображений. - М.: Высшая школа, 1983. - 256 с.
18) Бутаков А., Островский В. И., Фадеев И.Л. Обработка изображений на ЭВМ. - М.: Радио и связь, 1987.
19) Гренандер У. Лекции по теории образов. - М.: Мир, 1979. - Т. 1-3.
20) Павлидис Т. Алгоритмы машинной графики и обработки изображений. - М.: Радио и связь, 1986.
21) Ту Дж., Гонсалес Р. Принципы распознавания образов. - М.: Мир, 1976.
22) Файн В.С. Опознавание изображений. - М.: Наука, 1970.
23) Розенфельд А. Распознавание и обработка изображений с помощью ЭВМ. - М.: Мир, 1972.
24) Строустрап Б. Язык программирования С++. - М.: Мир, 1994. - 278 с.
25) Кнут Д. Искусство программирования для ЭВМ. - М.: Мир, 1976. - Т. 1-3.
26) Шилдт Г. Самоучитель С++. - С-Пб.: БВХ-Петербург, 2002. 3 издание.
27) Тихомиров Ю. OpenGL Программирование трехмерной графики. - С-Пб.: БВХ-Петербург, 2002г. 2 издание.
28) Шибаева И.В., Мурынов А.И., Пивоваров И.В. Математические и программные средства распознавания графических изображений для передачи по цифровым каналам связи // Информационные технологии в науке, образовании, телекоммуникациях и бизнесе: Материалы 31 Междунар. конф. - Украина, Крым, Ялта-Гурзуф: Ж. «Успехи современного естествознания» №5, 2004, Прилож. №1. - 114 c.
29) Соболева В.П. Методические указания по оформлению курсовых работ, курсовых и дипломных проектов. - Ижевск: Издательство ИМИ, 2003.
30) Эйнджел Э. Интерактивная компьютерная графика. - М.: Вильямс, 2001. - 592 с.
31) ГОСТ 12.1.006-84. ССБТ. Электромагнитные поля радиочастот. Допустимые уровни на рабочих местах и требования к проведению контроля. - М.: Издательство стандартов, 1985.
32) СанПиН 2.2.2.542-96. Гигиенические требования к видео-дисплейным терминалам, персонально-вычислительным машинам и организация работ. - М.: Госкомсанэпиднадзор России, 1996.
33) Налоговый кодекс РФ. - М.: ГроссМедиа Ферлаг, 2004. - 432 с.
34) ГОСТ 12.1.009-76. ССБТ. Электробезопасность. Термины и определения.
- М.: Издательство стандартов, 1985.
35) ГОСТ 19.505-79 ЕСПД. Руководство оператора. Требования к содержанию и оформлению. - М.: Издательство стандартов, 1979.
36) ГОСТ 19.504-79 ЕСПД. Руководство программиста. Требования к содержанию и оформлению. - М.: Издательство стандартов, 1979.
37) ГОСТ 19.701-90 ЕСПД. Схемы алгоритмов и программ. Правила выполнения. - М.: Издательство стандартов, 1991.
38) Технико-экономическое обоснование дипломных проектов при разработке приборов и методов контроля качества. Методические указания для студентов. - Ижевск: Издательство ИжГТУ, 2001.
39) Почерняев С.В., Килин И.В. Методические указания по дипломному проектированию. - Ижевск: Издательство ИжГТУ, 1994.
ПРИЛОЖЕНИЕ 1
ТЕКСТ ПРОГРАММЫ
П.1.1. ТЕКСТ МОДУЛЯ Resource.h
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by FingerAnalyser.rc
//
#define IDM_ABOUTBOX 0x0010
#define IDD_ABOUTBOX 100
#define IDS_ABOUTBOX 101
#define IDD_FINGERANALYSER_DIALOG 102
#define IDR_MAINFRAME 128
#define IDR_TOOLBAR 130
#define IDI_FING_ICON 135
#define IDR_MENU1 138
#define IDC_OPEN_FILE 1000
#define IDC_ANALYSE 1001
#define IDC_COMPARE 1002
#define IDC_EXIT 1003
#define IDC_SAVE_TO_DB 1004
#define IDC_SPEC_DOT 1005
#define IDC_LOAD_PROGRESS 1006
#define IDC_WORK_FILE 1007
#define IDC_LOAD_COMPARE_PROGRESS 1008
#define IDC_TEMESCAN 1009
#define IDC_BUTTON_PREV 1012
#define IDC_BUTTON_NEXT 1013
#define IDC_SHOW_BASE 1014
#define IDC_EDIT1 1015
#define ID_BASE 32771
#define ID_PROPERTY 32772
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 139
#define _APS_NEXT_COMMAND_VALUE 32774
#define _APS_NEXT_CONTROL_VALUE 1016
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
П.1.2. ТЕКСТ МОДУЛЯ FingAnalyser.h
// FingerAnalyser.h : main header file for the PROJECT_NAME application
//
#pragma once
#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif
#include "resource.h" // main symbols
// CFingerAnalyserApp:
// See FingerAnalyser.cpp for the implementation of this class
//
class CFingerAnalyserApp : public CWinApp
{
public:
CFingerAnalyserApp();
// Overrides
public:
virtual BOOL InitInstance();
// Implementation
DECLARE_MESSAGE_MAP()
};
extern CFingerAnalyserApp theApp;
П.1.3. ТЕКСТ МОДУЛЯ FingAnalyser.cpp
// FingerAnalyser.cpp : Defines the class behaviors for the application.
//
#include "stdafx.h"
#include "FingerAnalyser.h"
#include "FingerAnalyserDlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CFingerAnalyserApp
BEGIN_MESSAGE_MAP(CFingerAnalyserApp, CWinApp)
ON_COMMAND(ID_HELP, CWinApp::OnHelp)
END_MESSAGE_MAP()
// CFingerAnalyserApp construction
CFingerAnalyserApp::CFingerAnalyserApp()
{
// TODO: add construction code here,
// Place all significant initialization in InitInstance
}
// The one and only CFingerAnalyserApp object
CFingerAnalyserApp theApp;
// CFingerAnalyserApp initialization
BOOL CFingerAnalyserApp::InitInstance()
{
CWinApp::InitInstance();
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need
// Change the registry key under which our settings are stored
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
CFingerAnalyserDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}
П.1.4. ТЕКСТ МОДУЛЯ FingAnalyserDlg.h
// FingerAnalyserDlg.h : header file
//
#pragma once
#include "TFingPicture.h"
#include "afxcmn.h"
typedef list<TInfo> listTInfo;
// CFingerAnalyserDlg dialog
class CFingerAnalyserDlg : public CDialog
{
// Construction
public:
CFingerAnalyserDlg(CWnd* pParent = NULL); // standard constructor
~CFingerAnalyserDlg(); // деструктор
// Dialog Data
enum { IDD = IDD_FINGERANALYSER_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
CDC memDC;
CBitmap bm;
BITMAP bmp;
UINT timer;
TFingPicture *fp;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
afx_msg void OnBnClickedOpenFile();
afx_msg void OnBnClickedExit();
afx_msg void OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized);
afx_msg void OnBnClickedAnalyse();
afx_msg void OnBnClickedCompare();
afx_msg void OnTimer(UINT nIDEvent);
afx_msg void OnEnChangeSpecDot();
int m_kolDots;
afx_msg void OnBnClickedSaveToDb();
CProgressCtrl loadProgress;
public:
listTInfo *LoadDB(CString dbFile);
list<TCompareFing> *CompareWithBase();
CString m_workFile;
CProgressCtrl compare_progress;
long m_scantime;
afx_msg void OnBnClickedButtonPrev();
list<TCompareFing> *compareResult;
list<TCompareFing>::iterator showIter;
afx_msg void OnBnClickedButtonNext();
void ShowBase(bool key, bool next = true);
void PrintReport(CString file, CString report);
CString GetSAV(CString srcName); //получение пути к sav файлу
BOOL m_show_base;
afx_msg void OnBnClickedShowBase();
afx_msg void OnMouseMove(UINT nFlags, CPoint point);
CPoint mouse_pos;
int m_mouse_x;
int m_mouse_y;
afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
};
П.1.5 ТЕКСТ МОДУЛЯ FingAnalyserDlg.cpp
// FingerAnalyserDlg.cpp : implementation file
//
#include "stdafx.h"
#include "FingerAnalyser.h"
#include "FingerAnalyserDlg.h"
#include "TAnalysePicture.h"
#include ".\fingeranalyserdlg.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
CString sav_path, db_file;
TAnalysePicture *picture;
TAbsFing fingA;
TRelFing fingR;
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
enum { IDD = IDD_ABOUTBOX };
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()
// CFingerAnalyserDlg dialog
CFingerAnalyserDlg::CFingerAnalyserDlg(CWnd* pParent /*=NULL*/)
: CDialog(CFingerAnalyserDlg::IDD, pParent)
, m_kolDots(0)
, m_workFile(_T(""))
, m_scantime(0)
, m_show_base(FALSE)
, m_mouse_x(0)
, m_mouse_y(0)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
CFingerAnalyserDlg::~CFingerAnalyserDlg()
{
delete(fp);
delete(picture);
if(compareResult)
{
for(list<TCompareFing>::iterator i = compareResult->begin();
i != compareResult->end();
i++)
{
list<TPairSur>::iterator j;
for(j=i->surdots.begin(); j!=i->surdots.end(); j++)
{
j->first->clear(); delete(j->first);
j->second->clear(); delete(j->second);
}
}
compareResult->clear();
delete(compareResult);
compareResult = NULL;
}
}
void CFingerAnalyserDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Text(pDX, IDC_SPEC_DOT, m_kolDots);
DDX_Control(pDX, IDC_LOAD_PROGRESS, loadProgress);
DDX_Text(pDX, IDC_WORK_FILE, m_workFile);
DDX_Control(pDX, IDC_LOAD_COMPARE_PROGRESS, compare_progress);
DDX_Text(pDX, IDC_TEMESCAN, m_scantime);
DDX_Check(pDX, IDC_SHOW_BASE, m_show_base);
}
BEGIN_MESSAGE_MAP(CFingerAnalyserDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_OPEN_FILE, OnBnClickedOpenFile)
ON_BN_CLICKED(IDC_EXIT, OnBnClickedExit)
ON_WM_CLOSE()
ON_WM_ACTIVATE()
ON_BN_CLICKED(IDC_ANALYSE, OnBnClickedAnalyse)
ON_BN_CLICKED(IDC_COMPARE, OnBnClickedCompare)
ON_WM_TIMER()
ON_BN_CLICKED(IDC_SAVE_TO_DB, OnBnClickedSaveToDb)
ON_BN_CLICKED(IDC_BUTTON_PREV, OnBnClickedButtonPrev)
ON_BN_CLICKED(IDC_BUTTON_NEXT, OnBnClickedButtonNext)
ON_BN_CLICKED(IDC_SHOW_BASE, OnBnClickedShowBase)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()
// CFingerAnalyserDlg message handlers
BOOL CFingerAnalyserDlg::OnInitDialog()
{
CDialog::OnInitDialog();
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
fp = new TFingPicture(this->GetDC());
char fullpath[200];
_fullpath(fullpath, NULL, 200);
sav_path = fullpath;
sav_path += "\\sav\\";
db_file = sav_path + "fingbase.bse";
compareResult = NULL;
return TRUE; // return TRUE unless you set the focus to a control
}
void CFingerAnalyserDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CFingerAnalyserDlg::OnPaint()
{
CPaintDC dc(this); // device context for painting
if(m_show_base)
{//режим просмотра базы
ShowBase(true, false);
}
else
{//режим просмотра открытого образа
if (picture != NULL)
{
picture->GetPic1()->Show(110, 45);
picture->GetPic2()->Show(545, 45);
}
m_kolDots = (int)fingA.size();
UpdateData(false);
}
CDialog::OnPaint();
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CFingerAnalyserDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CFingerAnalyserDlg::OnBnClickedOpenFile()
{
char szFilters[]= "Образы (*.bmp)|*.bmp|All Files (*.*)|*.*||";
CFileDialog dlg(TRUE, "bmp", "*.bmp", OFN_FILEMUSTEXIST| OFN_HIDEREADONLY, szFilters, this);
if(dlg.DoModal() != IDOK) return; //никаких файлов не открыли
if(dlg.GetFileExt().CompareNoCase("bmp")) return; //открытый файл не имеет расширеня .bmp
// fp->Load(dlg.GetFileName());
CString fileName = dlg.GetFileName();
delete(picture);
picture = new TAnalysePicture(fileName, this->GetDC());
m_workFile = fileName;
if(compareResult)
{
for(list<TCompareFing>::iterator i = compareResult->begin();
i != compareResult->end();
i++)
{
list<TPairSur>::iterator j;
for(j=i->surdots.begin(); j!=i->surdots.end(); j++)
{
j->first->clear(); delete(j->first);
j->second->clear(); delete(j->second);
} }
compareResult->clear();
}
m_show_base = false;
Invalidate();
}
void CFingerAnalyserDlg::OnBnClickedExit()
{
CDialog::SendMessage(WM_CLOSE);
}
void CFingerAnalyserDlg::OnActivate(UINT nState, CWnd* pWndOther, BOOL bMinimized)
{
CDialog::OnActivate(nState, pWndOther, bMinimized);
// pWndOther->SetProperty(
}
void CFingerAnalyserDlg::OnBnClickedAnalyse()
{
if(picture == NULL) return;
LPSYSTEMTIME mTime;
mTime = new SYSTEMTIME;
GetSystemTime(mTime);
long int workTime;
workTime = mTime->wSecond*1000+mTime->wMilliseconds;
fingA = picture->AnalysePicture();
fingA.SaveFing(GetSAV(picture->getPathSrc()));
GetSystemTime(mTime);
workTime = mTime->wSecond*1000+mTime->wMilliseconds - workTime;
workTime = (workTime<0)?60000+workTime:workTime;
delete(mTime);
m_scantime = workTime;
Invalidate();
}
void CFingerAnalyserDlg::OnBnClickedCompare()
{
if(fingA.size() == 0)
{
MessageBox("Отпечаток не обработан", "Ошибка");
return;
}
fingR.Convert(fingA);
if(compareResult)
{
for(list<TCompareFing>::iterator i = compareResult->begin();
i != compareResult->end();
i++)
{
list<TPairSur>::iterator j;
for(j=i->surdots.begin(); j!=i->surdots.end(); j++)
{
j->first->clear(); delete(j->first);
j->second->clear(); delete(j->second);
}
}
compareResult->clear();
delete(compareResult);
compareResult = NULL;
showIter = NULL;
}
compareResult = CompareWithBase();
if(compareResult->size() == 0) return;
CString sOut="";
for(list<TCompareFing>::iterator i = compareResult->begin();
i != compareResult->end();
i++)
{
CString s="";
int mlevel = min(i->nfng,m_kolDots);
int percent;
if(mlevel > 10) mlevel = 10;
if(i->cDot > mlevel) percent = 100;
else percent = (int)(100.0*i->cDot/(double)mlevel + 0.5);
if(percent == 0) continue;
s.Format("%d %d %% %s\n", i->cDot, percent, i->name);
sOut += s;
}
if(sOut.GetLength()==0) sOut = "Ни одного отпечатка не найдено!\n";
CString kol; kol.Format("\n Всего в базе: %d", compareResult->size());
sOut += kol;
PrintReport(picture->getPathSrc(), sOut);
MessageBox(sOut, picture->getPathSrc());
}
void CFingerAnalyserDlg::OnTimer(UINT nIDEvent)
{
Invalidate();
CDialog::OnTimer(nIDEvent);
}
void CFingerAnalyserDlg::OnBnClickedSaveToDb()
{
char szFilters[]=
"Образы (*.bmp)|*.bmp|All Files (*.*)|*.*||";
CFileDialog dlg(TRUE, "bmp", "*.bmp", OFN_FILEMUSTEXIST| OFN_HIDEREADONLY| OFN_ALLOWMULTISELECT, szFilters, this);
if(dlg.DoModal() == IDOK)
{
listTInfo *fingDB = LoadDB(db_file);
FILE *fbse = fopen(db_file, "wb");
if(fbse == NULL)
{
MessageBox("Невозможно создать базу данных с отпечатками", "Ошибка создания БД", MB_OK);
return;
}
POSITION pos, posStart;
TInfo newFingInDB;
pos = posStart = dlg.GetStartPosition();
int kolFile = 0;
while(pos) {dlg.GetNextPathName(pos); kolFile++;}
pos = posStart;
loadProgress.SetRange(0, kolFile);
int progressPos = 1;
while(pos)
{
CString fileName = dlg.GetNextPathName(pos).MakeLower();
if(fileName.Find(".bmp") == -1) continue;
TAnalysePicture *loadingPic;
loadingPic = new TAnalysePicture(fileName, this->GetDC());
m_workFile = fileName;
fingA = loadingPic->AnalysePicture();
if(fingA.size() < MIN_SIZE) {MessageBox("Отпечаток не пригоден для сохраниения в базу!", fileName); continue;}
if(fingA.size() > MAX_SIZE) {MessageBox("Отпечаток не пригоден для сохраниения в базу!", fileName); continue;}
fingA.SaveFing(GetSAV(fileName));
newFingInDB.src = fileName;
fingDB->remove(newFingInDB);
fingDB->push_back(newFingInDB);
loadProgress.SetPos(progressPos);
progressPos++;
Invalidate();
delete(loadingPic);
}
loadProgress.SetPos(0);
int count = 0;
fwrite((void*)&count, sizeof(count), 1, fbse);
for(list<TInfo>::iterator iter = fingDB->begin(); iter != fingDB->end(); iter++)
{
iter->Printf(fbse);
count++;
}
fseek(fbse, 0, SEEK_SET);
fwrite((void*)&count, sizeof(count), 1, fbse);
fingDB->clear();
delete(fingDB);
fclose(fbse);
}
}
listTInfo *CFingerAnalyserDlg::LoadDB(CString dbFile)
//загрузить точки из БД
{
listTInfo *bse = new listTInfo();
TInfo finf; //данные по отпечатку
FILE *fbse = fopen(dbFile, "rb");
if(fbse == NULL)
{
// MessageBox("Невозможно загрузить базу данных с отпечатками", "Ошибка загрузки БД", MB_OK);
return bse;
}
int count = 0;
fread((void*)&count, sizeof(count), 1, fbse);
for(;count > 0; count--)
{
finf.Scanf(fbse);
bse->push_back(finf);
}
fclose(fbse);
return bse;
}
list<TCompareFing> *CFingerAnalyserDlg::CompareWithBase()
//сравнить точку с точками в БД
{
listTInfo *bse;
list<TCompareFing> *cFng;
cFng = new list<TCompareFing>;
bse = LoadDB(db_file);
if(bse->empty())
{
MessageBox("База данных отпечатков пуста", "Сообщение", MB_OK);
return cFng;
}
TAbsFing aFng;
TRelFing baseFng;
compare_progress.SetRange(0, (short)bse->size());
for(list<TInfo>::iterator ibse = bse->begin();
ibse != bse->end(); ibse++)
{
if(!aFng.LoadFing(GetSAV(ibse->src))) continue;
baseFng.Convert(aFng);
TCompareFing compareRes = fingR.Compare(baseFng);
compareRes.name = ibse->src;
cFng->push_back(compareRes);
compare_progress.SetPos((int)cFng->size());
}
bse->clear();
compare_progress.SetPos(0);
delete(bse);
return cFng;
}
void CFingerAnalyserDlg::OnBnClickedButtonPrev(){ ShowBase(false);}
void CFingerAnalyserDlg::OnBnClickedButtonNext(){ ShowBase(true);}
void CFingerAnalyserDlg::ShowBase(bool key, bool next)
//key - направление перемотки по базе (влево, вправо)
//next - нужно ли переходить к следующему отпечатку
{
if(!compareResult) return;
if(compareResult->size() == 0)
{
MessageBox("База данных отпечатков пуста", "Сообщение", MB_OK);
return;
}
if(showIter == NULL) showIter = compareResult->begin();
else
{
if(next)
if(key)
{
showIter++;
if(showIter == compareResult->end())
showIter = compareResult->begin();
}
else
{
if(showIter == compareResult->begin())
showIter = compareResult->end();
showIter--;
}
}
TFingPicture *pic;
pic = new TFingPicture(this->GetDC());
if(!pic->Load(BLANK)) return;
CPaintDC dc(this); // device context for painting
list<TPairSur>::iterator is = showIter->surdots.begin();
list<TPairAbsDot>::iterator id = showIter->dots.begin();
for(; id != showIter->dots.end(); id++, is++)
{
COLORREF col;
if(is->first->empty()) col = 0xBBBBBB;
else col = (id->first.type)?0xff0000:0x000000;
pic->Line(id->first.coord, id->first.coord, 5, col);
pic->Line(id->first.coord,
CPoint(id->first.coord.x+(int)(10.0*cos(id->first.alpha)),id->first.coord.y-(int)(10.0*sin(id->first.alpha))),
2, col);
if(is->first->empty()) continue; //окружения для этой точки нет
//проверка, что "мышь" находится над точкой
if( abs(mouse_pos.x-id->first.coord.x)<6 && abs(mouse_pos.y-id->first.coord.y)<6 )
{
TFingPicture pic2(this->GetDC());
if(!pic2.Load(BLANK)) return;
pic2.Copy(*picture->GetPic2());
for(listTRelDot::iterator ii = is->first->begin(); ii != is->first->end(); ii++)
{
COLORREF cl = 0x554444;
CPoint cd;
cd.x = (long)(id->first.coord.x - ii->l * cos(ii->a1*M_PI/180.0 - id->first.alpha));
cd.y = (long)(id->first.coord.y - ii->l * sin(ii->a1*M_PI/180.0 - id->first.alpha));
pic->Line(id->first.coord, cd, 1, cl);
}
for(listTRelDot::iterator ii = is->second->begin(); ii != is->second->end(); ii++)
{
COLORREF cl = 0x554444;
CPoint cd;
cd.x = (long)(id->second.coord.x - ii->l * cos(ii->a1*M_PI/180.0 - id->second.alpha));
cd.y = (long)(id->second.coord.y - ii->l * sin(ii->a1*M_PI/180.0 - id->second.alpha));
pic2.Line(id->second.coord, cd, 1, cl);
}
pic2.Show(545, 45);
}
}
if (pic != NULL)
{
pic->Show(110, 45);
m_workFile = showIter->name;
}
UpdateData(false);
delete(pic);
}
void CFingerAnalyserDlg::PrintReport(CString file, CString report)
{
FILE *outf = fopen("report.txt", "a");
CString msg = "\n------ "+file+" ------\n"+report;
fprintf(outf, msg);
fclose(outf);
}
CString CFingerAnalyserDlg::GetSAV(CString srcName)
{
CString fsav = srcName.Left(srcName.GetLength() - 3) + "sav";
while(fsav.Find("\\") != -1){ fsav = fsav.Right(fsav.GetLength() - fsav.Find("\\")-1); }
return sav_path + fsav;
}
void CFingerAnalyserDlg::OnBnClickedShowBase()
{
m_show_base =! m_show_base;
UpdateData(false);
if(m_show_base)
{
ShowBase(true, false);
}
else
{
OnPaint();
}
}
void CFingerAnalyserDlg::OnLButtonDown(UINT nFlags, CPoint point)
{
if(!m_show_base) return;
mouse_pos = point;
mouse_pos.x -= 110;
mouse_pos.y -= 45;
ShowBase(true, false);
CDialog::OnLButtonDown(nFlags, point);
}
П.1.6 ТЕКСТ МОДУЛЯ fing.h
#pragma once
#include "stdafx.h"
using namespace std;
//Элемент "карты точек"
//"Карта точек" - список точек для обработки
class TMapElDot{
public:
CPoint coord; //координаты точки
bool pr1, pr2; //признаки точки
public:
TMapElDot(CPoint dot){pr1 = true; pr2 = true; coord = dot;};
TMapElDot(){pr1 = true; pr2 = true;};
~TMapElDot(){};
};
//"Карта точек" - список точек для обработки
class TMapDot{
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);
/*Если точка является окончанием, то слева и справа от нее должны быть линии
если это не так, то точку нужно исключить из дальнейшего анализа*/
public:
TAnalysePicture(const CString src, CDC *screen);
~TAnalysePicture(void);
int getErr();
CString getErrMsg();
CString getPathSrc(){return srcImg;};
TAbsFing AnalysePicture(); //Обработка загруженного изображения и получение образа
bool Show(int x, int y, int xt=-1, int yt=-1);
TFingPicture *GetPic1();
TFingPicture *GetPic2();
};
П.1.9 ТЕКСТ МОДУЛЯ TAnalysePicture.cpp
#include "StdAfx.h"
#include "TAnalysePicture.h"
TAnalysePicture::TAnalysePicture(const CString src, CDC *screen)
{
pic = new TFingPicture(screen);
err = -1;
if(!pic->Load(src)) err = 0;
pic->Rectangle(CPoint(0, 0), pic->GetSize(), 10);
srcImg = src;
tmpPic = new TFingPicture(screen);
tmpPic->Load(src);
pic2 = new TFingPicture(screen);
pic2->Load(BLANK);
}
TAnalysePicture::~TAnalysePicture(void)
{
delete(tmpPic);
delete(pic2);
delete(pic);
}
//Код ошибки
int TAnalysePicture::getErr()
{
return err;
}
//Сообщение ошибки
CString TAnalysePicture::getErrMsg()
{
CString msg = "";
switch (err)
{
case -1: {msg = "Ошибок при загрузке изображения нет"; break;}
case 0: {msg = "Изображение не загружено"; break;}
case 1: {msg = "Возникла ошибка при загрузке изображения"; break;}
default: {msg = "Нераспознанная ошибка";}
}
return msg;
}
// Обработка загруженного изображения и получение образа
TAbsFing TAnalysePicture::AnalysePicture()
{
TAbsFing ret, ret2;
if(err != -1)
{
if(MESSAGEOUT) MessageBox(NULL, getErrMsg(), "Ошибка", MB_OK);
return ret;
}
int prevCol;
int changeN = 0; //Счетчик произведенных изменений на изображении
list<TMapElDot> map; //Карта точек принадлежащих линиям
list<TMapElDot>::iterator imap; //Итератор для map
map = LookPic(); //сканирование картинки и нахождение линий на ней
do{
changeN = 0;
prevCol = (int)map.size();
imap = map.begin();
do{ //Изображение можно модифицировать
if(imap->pr1) //Линия нуждается в обработке
changeN += ChangeLine(imap, map); //Обработка (преобразование) изображения
imap++; //Переход для обработки следующей линии
}while(imap != map.end()); //Изображение можно модифицировать
}while(prevCol<0.1*map.size()); //Изображение можно модифицировать
map = LookPic(); //сканирование картинки и нахождение линий на ней
imap = map.begin();
do{ //Изображение можно модифицировать
ret.merge(ReadPic(imap));
imap++; //Переход для обработки следующей линии
}while(imap != map.end()); //Изображение можно модифицировать
////////////////////////////////////////////////////////////////////
/////////////////////Фильтрование полученных точек//////////////////
///отсеиваются близкостоящие направленные в противоположные строки//
//////////а так же точки слева и справа от которых нет линий////////
int leftDots = 0; //число отсеянных точек
leftDots = DotsFilter(ret); //Фильтрование полученных точек
////////////////////////////////////////////////////////////////////
ret2.clear();
for(TAbsFing::iterator iter = ret.begin(); iter != ret.end(); iter++)
{
if(!iter->show) continue;
//рисование найденных точек (цвет окончания и раздвоения различный)
COLORREF col = (iter->type)?0xFF0000:0x000000;
pic2->Line(iter->coord, iter->coord, 5, col);
pic2->Line(iter->coord,
CPoint(iter->coord.x+(int)(10.0*cos(iter->alpha)),iter->coord.y-(int)(10.0*sin(iter->alpha))),
2, col);
ret2.push_back(*iter);
}
ret.clear();
return ret2;
}
TAbsFing TAnalysePicture::ReadPic(list<TMapElDot>::iterator _dot)
//Нахождение на изображении спец точек
{
TAbsFing retFing; //Образ отпечатка в абсолютных координатах
int kol = 0; //количество пройденных точек
int vec = 0; //направление поиска очередной точки
int tekS = 0; //Текущее количество коротких векторов
CPoint A, //Начало вектора
B; //Конец вектора
TAbsFing vecDotS; //массив точек для коротких векторов
TAbsFing vecDotL; //массив точек для длинных векторов
TAbsFing historyDotL; //история точек для длинных векторов
TAbsDot _tmpDotFing, bestDot;
TAbsFing::iterator iter;
double alpha; //направление вектора (в радианах)
int stopKol = 2000; //предел шагов
int ret = 0; //счетчик шагов после прохождения начальной точки
bool homeOver = false; //признак окончания обработки
A = _dot->coord; B = _dot->coord;
CPoint olddot, dot = _dot->coord; //Текущая точка на линии
do{
//основной цикл обработки,
//варианты завершения цикла
//продолжается до тех пор пока вся линия не будет пройдена (нормальный вариант)
//зацикливание (не нормальный вариант, их несколько)
//
olddot = dot;
dot = pic->NextDotCW(dot, vec); //Поиск следующей точки _по часовой_ стрелке
if(dot.x == olddot.x && dot.y == olddot.y)
{//положение точки не изменилось => выход//
CString s;
s.Format("x = %d, y = %d, kol= %d", dot.x, dot.y, kol);
if(MESSAGEOUT)MessageBox(0, "положение точки не изменилось => выход\n" + s, "", MB_OK);
return retFing;
}
kol++; //подсчет пройденных точек
if(kol % LEN_S == 0)
{//появился новый короткий вектор
tekS++;
A = B;
B = dot;
pic2->Line(A,B, 1, 0x999999);
_tmpDotFing.coord = A;
alpha = GetAlpha(A, B); //расчет локального направления между KOL_S пикселями (направление короткого вектора)//
double dAlpha = 0.0; //Разница углов
if(vecDotS.size() > 0) //в списке можно взять предыдущее значение
dAlpha = alpha - vecDotS.begin()->alpha;
/**/ if (abs(dAlpha) >= M_PI) //разница между новым углом и предыдущим не нормальная!
{//необходимо скорректировать текущую alpha
/**/ if (dAlpha < 0.0)
{
while (abs(dAlpha) > M_PI)
{
alpha += 2.0 * M_PI;
dAlpha += 2.0 * M_PI;
}
}else
{
while (dAlpha >= M_PI)
{
alpha -= 2.0 * M_PI;
dAlpha -= 2.0 * M_PI;
}
}
}
_tmpDotFing.alpha = alpha; //запоминание направления из точки А//
vecDotS.push_front(_tmpDotFing);
///////////////////////////////////////////////////////////////////////
///////проверяем два соседних длинных вектора при условии что//////////
///////пройдено достаточно точек, чтоб сравнивать длнинные вектора/////
if(vecDotS.size() < KOL_S) continue;
//Вычисление среднего направления LEN_L коротких векторов//
//запись данных по длинному вектору////////////////////////
double sumAlpha = 0.0;
iter = vecDotS.begin();
vecDotL.clear(); //пересчитаем длинные вектора
for(int i = 0; i < KOL_S; i++)
{
sumAlpha += iter->alpha;
if ((i+1) % LEN_L == 0)
{
_tmpDotFing = *iter;
_tmpDotFing.alpha = sumAlpha / LEN_L;
vecDotL.push_back(_tmpDotFing);
sumAlpha = 0.0;
}
iter++;
}
if (abs(vecDotL.begin()->alpha) > 3*2*M_PI)
{//слишком много оборотов//
CString s;
s.Format("alpha = %.2f", vecDotL.begin()->alpha*180);
if(MESSAGEOUT)MessageBox(0, "слишком много оборотов\n"+s, "", MB_OK);
return retFing;
}
//проверяем два соседних длинных вектора//
dAlpha = vecDotL.begin()->alpha - (++vecDotL.begin())->alpha;
if (abs(dAlpha) > (TEST_ALPHA / 180.0 * M_PI)) //сильный изгиб//
{
if (historyDotL.empty())
{ //сохранение состояния//
bestDot.alpha = 0.0;
}
if (dAlpha > 0) //раздвоение
alpha = (vecDotL.begin()->alpha - M_PI + (++vecDotL.begin())->alpha) / 2.0;
else //окончание
alpha = (vecDotL.begin()->alpha + M_PI + (++vecDotL.begin())->alpha) / 2.0;
_tmpDotFing = vecDotL.front();
_tmpDotFing.alpha = alpha; //направление в СТ (специфичная точка)//
_tmpDotFing.type = dAlpha<0; //тип СТ//
historyDotL.push_front(_tmpDotFing);
if(bestDot.alpha <= abs(dAlpha))
{
bestDot.coord = _tmpDotFing.coord;
bestDot.alpha = abs(dAlpha);
}
}
else //сильный изгиб//
{
if (!historyDotL.empty()) //был _пройден_ сильный изгиб
{
alpha = 0;
for(iter = historyDotL.begin(); iter != historyDotL.end(); iter++)
alpha += iter->alpha;
alpha /= historyDotL.size(); //среднее значение в пройденной СТ
iter = historyDotL.begin();
for(unsigned int i = 0; i<(historyDotL.size()/2); i++) iter++;
// CPoint wdot = iter->coord; //наиболее вероятная точка для СТ
CPoint wdot = bestDot.coord; //наиболее вероятная точка для СТ
//Если раскомментировать эти строки, то исключатся точки имеющие продолжение
// CPoint dotForAccept = FindAcceptDot(wdot, alpha, iter->type);
// if (dotForAccept.x == -1)
{ //точка не имеет продолжения, запомним ее//
_tmpDotFing.alpha = ChangeAlphaInterval(alpha);
_tmpDotFing.coord = wdot;
_tmpDotFing.show = true;
_tmpDotFing.type = historyDotL.begin()->type;
retFing.push_back(_tmpDotFing);
}
historyDotL.clear();
stopKol += (kol*1.5 > stopKol)?1000:0;
}
}
}
if (dot.x == _dot->coord.x && dot.y == _dot->coord.y)
{//вероятно обход линии завершен
if (kol <= 2)
{//Линия подозрительно короткая
CString s;
s.Format("%d", kol);
if(MESSAGEOUT)MessageBox(0, "kol<=2 kol = " + s, "", MB_OK);
return retFing;
}else
{
homeOver = true; //пройти необходимо дальше начала
stopKol = kol + KOL_L*LEN_L*LEN_S;
}
}
if (homeOver) ret++;
}while(ret < (LEN_L*LEN_S*KOL_L) && ret < stopKol && kol <= stopKol);
_dot->pr1 = false;
_dot->pr2 = false;
return retFing;
}
list<TMapElDot> TAnalysePicture::LookPic()
//Попиксельное "пробегание" по картинке и
//запоминание черных точек, после нахождения черной точки
//заливка всей линии в цвет фона (удаление линии с картинки)
{
list<TMapElDot> map;
TMapElDot dot;
tmpPic->Copy(*pic);
for(int j = 0; j < pic->GetSize().y; j++)
for(int i = 0; i < pic->GetSize().x; i++)
{
if(!tmpPic->GetPixel(i,j)) //найден черный пиксель
{
dot.coord.x = i; dot.coord.y = j;
dot.pr1 = dot.pr2 = true;
Подобные документы
Анализ биометрических систем идентификации личности по отпечаткам пальцев, форме кисти руки, оболочке глаза. Лицо как биометрический идентификатор. Анализ рынка систем распознавания личности. Оценка эффективности систем идентификации по геометрии лица.
курсовая работа [1,8 M], добавлен 30.05.2013Разработка алгоритма формирования относительных параметров для минюций. Подбор параметров системы допусков и критериев схожести при сравнении отпечатков. Метод пригоден для распознавания битовых изображений: символьной информации, шрифтов и подписей.
дипломная работа [4,0 M], добавлен 23.06.2008Использование паролей как способ защиты от несанкционированного доступа к программам и данным, хранящимися на компьютере. Биометрические системы идентификации по отпечаткам пальцев, геометрии ладони руки, характеристикам речи, радужной оболочке глаза.
презентация [679,6 K], добавлен 06.05.2015Анализ существующих методов реализации программного средства идентификации личности по голосу. Факторы, влияющие на уникальность речи. Разработка программного средства идентификации личности по голосу. Требования к программной документации приложения.
дипломная работа [12,7 M], добавлен 17.06.2016Классификация и основные характеристики биометрических средств идентификации личности. Особенности реализации статических и динамических методов биометрического контроля. Средства авторизации и аутентификации в электронных системах охраны и безопасности.
курсовая работа [1,7 M], добавлен 19.01.2011Разработка эскизного и технического проекта программы идентификации личности по отпечатку. Назначение и область применения, описание алгоритма, входных и выходных данных. Выбор состава технических и программных средств. Тестирование и внедрение продукта.
курсовая работа [61,9 K], добавлен 12.05.2015Проблема улучшения качества отпечатков пальца с целью повышения эффективности работы алгоритмов биометрической аутентификации. Обзор алгоритмов обработки изображений отпечатков пальцев. Анализ алгоритма, основанного на использовании преобразования Габора.
дипломная работа [4,5 M], добавлен 16.07.2014Телефакс как устройство факсимильной передачи изображения по телефонной сети. Назначение планшетного сканера. Использование листопротяжных сканеров. Принцип работы барабанного сканера. Применение сканера штрих-кода. Оптический сканер отпечатка пальцев.
реферат [11,6 K], добавлен 19.01.2010Основные цели и задачи построения систем распознавания. Построение математической модели системы распознавания образов на примере алгоритма идентификации объектов военной техники в автоматизированных телекоммуникационных комплексах систем управления.
дипломная работа [332,2 K], добавлен 30.11.2012Основы биометрической идентификации. Возможность использования нейросетей для построения системы распознавания речи. Разработка программного обеспечения для защиты от несанкционированного доступа на основе спектрального анализа голоса пользователя.
дипломная работа [2,8 M], добавлен 10.11.2013