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. ТЕКСТ МОДУЛЯ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.6. ТЕКСТ МОДУЛЯ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.7. ТЕКСТМОДУЛЯ 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.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