⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 board.cpp

📁 鼠标手势识别系统
💻 CPP
📖 第 1 页 / 共 2 页
字号:
		SelectObject(hDC, m_hpen3);
		DrawVector(hDC, rc, m_angles);
	}
	
	RestoreDC(hDC, n_save_dc);
}

void Board::DrawBottomDesc(HDC hDC, RECT& rc)
{		
	if ((training_mode == m_mode || trained_mode == m_mode)
		&& m_update_bottom_desk)
	{
		BitBlt(hDC, 0, 0, rc.right - rc.left, rc.bottom - rc.top, m_hMemDC4, 0, 0, SRCCOPY);
	}
	else
	{
		int n_save_dc = SaveDC(hDC);
		SelectObject(hDC, m_hbrh2);
		SelectObject(hDC, m_hpen2);
		Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);

		if (recognized_success == m_mode)
		{
			//  draw a recognized pattern

			vector_real_t vec(NUMBER_OF_ANGLES);			
			for (unsigned n = 0; n < vec.size(); ++n)
				vec[n] = pattern_data[m_winners[0].m_id][n];

			SelectObject(hDC, m_hpen3);
			DrawVector(hDC, rc, vec);
		}

		RestoreDC(hDC, n_save_dc);
	}
}

void Board::DrawStatusInfo(HDC hDC, RECT& rc)
{
	int n_save_dc = SaveDC(hDC);

	SelectObject(hDC, m_hbrh2);
	SelectObject(hDC, m_hpen2);
	Rectangle(hDC, rc.left, rc.top, rc.right, rc.bottom);

	COLORREF clrTxt = RGB(0, 0, 0);

	TCHAR buf[512] = {0};

	if		(recognizing_mode == m_mode)
		sprintf(buf, "points %u", m_path.size());
	else if (training_mode == m_mode && m_errors.size())
		sprintf(buf, "error: %f", m_errors.back());	
	else if (trained_mode == m_mode && m_errors.size())
		sprintf(buf, "training cycles: %u, mean square error: %f", m_train_cycles, m_errors.back());	
	else if (recognized_success == m_mode)
	{
		clrTxt	= RGB(0, 0, 255);	
		sprintf(buf, "recognition is successful: %s (%f)", 
			pattern_names[m_winners[0].m_id], m_winners[0].m_probability);
	}
	else if (recognized_fail == m_mode)
	{
		clrTxt	= RGB(255, 0, 0);
		sprintf(buf, "unable to recognize anything, the best is %s (%f), points %u", 
			pattern_names[m_winners[0].m_id], m_winners[0].m_probability, m_path.size());
	}
	else 
		sprintf(buf, "untrained net");

	if (m_info.size())
	{
		_tcscat (buf, _T(" - "));
		_tcsncat(buf, m_info.c_str(), sizeof(buf)/sizeof(buf[0]) - _tcslen(buf));
	}
				
	SetBkMode(hDC, TRANSPARENT);	
	SetTextColor(hDC, clrTxt);
	SelectObject(hDC, GetStockObject(DEFAULT_GUI_FONT));
	SIZE sz;
	GetTextExtentPoint32(hDC, buf, lstrlen(buf), &sz);
	int x = rc.left + 3; 
	int y = rc.top + ((rc.bottom - rc.top) - sz.cy) / 2;
	ExtTextOut(hDC, x, y, ETO_CLIPPED, &rc, buf, lstrlen(buf), 0);	

	RestoreDC(hDC, n_save_dc);
}

void Board::DrawVector(HDC hDC, RECT& rc, vector_real_t& vec)
{
	typedef path_t::iterator iterator;

	path_t path;
	vector_to_path(rc, vec, path);

	iterator i = path.begin();
	MoveToEx(hDC, (*i).x, (*i).y, 0);
	++i;

	unsigned n = 0;
	for (; i != path.end(); ++i, ++n)
	{
		SelectObject(hDC, m_hpdesk[n / 4]);
		LineTo  (hDC, (*i).x, (*i).y);
		SetPixel(hDC, (*i).x, (*i).y, RGB(0, 0, 255));	
	}	
}

/////////////////////////////////////////////////

bool Board::TransfromPath()
{
	typedef path_t::iterator iterator;

	m_path2.assign(m_path.begin(), m_path.end());
		
	if (NUMBER_OF_ANCHOR_POINTS > m_path.size())
	{
		// todo : stretch path or warning message;		
		//	m_path.clear();
		m_path2.clear();
		m_mode = recognizing_mode;
		return false;
	}	
	else if (NUMBER_OF_ANCHOR_POINTS < m_path.size())
	{
		// smooth path		
		// finds smallest interval and replaces two points on median point

		while (m_path2.size() > NUMBER_OF_ANCHOR_POINTS)
		{
			double d;
			double d_min = std::numeric_limits<double>::max();
			
			iterator p_min  = m_path2.begin();
			++p_min;

			iterator p		= p_min;
			iterator i		= p_min;
			++i;

			iterator last	= m_path2.end();
			--last;

			for (; i != last; ++i)
			{
				d = sqrt(pow((*p).x - (*i).x, 2) + pow((*p).y - (*i).y, 2));
				if (d < d_min)
				{
					d_min = d;
					p_min = p;
				}
				p = i;
			}

			p = p_min;
			i = ++p_min;

			POINT pt = {((*p).x + (*i).x) / 2, ((*p).y + (*i).y) / 2};
			*i = pt;				// changes coord of a base point
			m_path2.erase(p);		// erases an odd point 
		}
	}		
	else
	{
		// nothing		
	}		
	
	_ASSERTE(m_path2.size() == NUMBER_OF_ANCHOR_POINTS);

	// computes angles, cosines and sines

	iterator i = m_path2.begin();
	iterator p = i++;
	unsigned n = 0;

	for (; i != m_path2.end(); ++i, ++n)
	{
		POINT pt2 = (*i);		
		POINT pt1 = (*p);		

		pt2.x -= pt1.x;
		pt2.y -= pt1.y;

		if (pt2.x || pt2.y)
		{
			m_cosines[n] = float(pt2.y / sqrt(pt2.x * pt2.x + pt2.y * pt2.y));
			m_sinuses[n] = (float)sqrt(1. - m_cosines[n] * m_cosines[n]);		
			if (pt2.x < 0) m_sinuses[n] = - m_sinuses[n];		
			m_angles[n] = float(acos(m_cosines[n]) * 180. / pi);
			if (pt2.x < 0) m_angles[n] = 360.f - m_angles[n];
		}
		else
		{
			m_cosines[n] = 1;
			m_sinuses[n] = 0;
			m_angles[n]  = 0;
		}
		
		p = i;

		_ASSERTE(m_cosines[n] <=  1.);
		_ASSERTE(m_cosines[n] >= -1.);
		_ASSERTE(m_sinuses[n] <=  1.);
		_ASSERTE(m_sinuses[n] >= -1.);
		_ASSERTE(m_angles [n] <= 360.);
		_ASSERTE(m_angles [n] >= 0.);		
	}	

	return true;
}

///////////////////////////////////////////////////////////

unsigned Board::StartTraining()
{
	m_mode = training_mode;
	m_update_top_desk = false;
	m_update_bottom_desk = false;
	m_path.clear();
	m_path2.clear();
	m_max_error = 0;	
	m_errors.clear();
	m_errors.reserve(m_rcMemDC.right - m_rcMemDC.left - DESK_WIDTH - 6);	
//	Refresh();
	return m_rcMemDC.right - m_rcMemDC.left - DESK_WIDTH - 6;
}

void Board::UpdateTrainingError(float current_error)
{
	m_max_error = std::_MAX(m_max_error, current_error);
	m_errors.push_back(current_error);
//	Refresh();
}

void Board::UpdateTrainingVector(vector_real_t& vec)
{
	_ASSERTE(vec.size() == m_angles.size());

	typedef vector_real_t::iterator iterator;
	for (iterator to = m_angles.begin(), from = vec.begin(); to != m_angles.end(); ++to, ++from)
	{
		*to = *from;
	}
	m_update_top_desk = true;
}

void Board::UpdateTrainingWeight(vector_real_t::iterator w_begin, vector_real_t::iterator w_end)
{
	_ASSERTE((w_end - w_begin) <= DESK_WIDTH * DESK_HEIGHT);

	typedef vector_real_t::iterator iterator;

	int n_save_dc = SaveDC(m_hMemDC4);

	RECT rc = {0, 0, DESK_WIDTH, DESK_HEIGHT};
	
	#define SPACE 2

	SelectObject(m_hMemDC4, m_hbrh2);
	SelectObject(m_hMemDC4, m_hpen2);
	Rectangle(m_hMemDC4, rc.left, rc.top, rc.right, rc.bottom);

	unsigned dim = (unsigned)sqrt(w_end - w_begin);

	unsigned left = (DESK_WIDTH - dim * SPACE) / 2;
	unsigned top  = (DESK_HEIGHT - dim * SPACE) / 2;
		
	iterator i = w_begin;
	for (unsigned x = left; x < left + dim * SPACE; x += SPACE)
		for (unsigned y = top; y < top + dim * SPACE; y += SPACE)
		{
			float f = *i;			
			COLORREF clr;
			if (fabs(f) > 1.) 
				clr = f < 0. ? RGB(255, 255, 0) : RGB(0, 0, 255) ;			
			else 
				clr = f < 0. ? RGB(f * 255., 0, 0) : RGB(0, f * 255., 0);

			SetPixel(m_hMemDC4, x, y, clr);

			SetPixel(m_hMemDC4, x + 0, y + 1, clr);
			SetPixel(m_hMemDC4, x + 1, y + 0, clr);
			SetPixel(m_hMemDC4, x + 1, y + 1, clr);

			++i;
		}

	_ASSERTE(i <= w_end);
	RestoreDC(m_hMemDC4, n_save_dc);
	m_update_bottom_desk = true;
}

void Board::StopTraining(unsigned last_cycle)
{
//	m_mode = recognizing_mode;
//	m_errors.clear();
	m_mode = trained_mode;
	m_train_cycles = last_cycle + 1; // 0..last_cycle
}

void Board::StartMouseRecord()
{	
//	CWindow(GetParent()).SendMessage(WM_COMMAND, MAKEWPARAM(ID_STOP, 0));
	m_path.clear();
	m_path2.clear();
	if (untrained_mode != m_mode)
		m_mode = recognizing_mode;
	Refresh();
}

void Board::AddMouseRecord(POINT pt)
{	
	m_path.push_back(pt);
	Refresh();
}

void Board::StopMouseRecord()
{	
	bool r = TransfromPath();	
	if (untrained_mode != m_mode && r)
	{		
		CWindow(GetParent()).SendMessage(WM_COMMAND, MAKEWPARAM(ID_RECOGNIZE, 0));
	}	
	Refresh();
}

///////////////////////////////////////

// static 
Board::vector_to_path(RECT& rc, vector_real_t& vec, path_t& path)
{
	typedef vector_real_t::iterator iterator;

	int y = 0, x = 0, cx = rc.right - rc.left, cy = rc.bottom - rc.top;				
	RECT borders = {0};
	iterator i;

	double dx = (double)cx / (vec.size() - 1);
	double dy = (double)cy / (vec.size() - 1);

	for (i = vec.begin(); i != vec.end(); ++i)
	{
		double angle = (double)*i;

		x += int(dx * sin(angle * (pi / 180.)));
		y += int(dy * cos(angle * (pi / 180.)));
		
		if (borders.left   > x) borders.left   = x;
		if (borders.right  < x) borders.right  = x;
		if (borders.top    > y) borders.top    = y;
		if (borders.bottom < y) borders.bottom = y;
	}

	x = - borders.left + (cx - (borders.right - borders.left)) / 2;
	y = - borders.top  + (cy - (borders.bottom - borders.top)) / 2; 

	POINT pt = {x, y};
	path.push_back(pt);

	unsigned n = 0;
	for (i = vec.begin(); i != vec.end(); ++i, ++n)
	{
		double angle = (double)*i;
		x += int(dx * sin(angle * (pi / 180.)));
		y += int(dy * cos(angle * (pi / 180.)));
		pt.x = x; pt.y = y;
		path.push_back(pt);
	}	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -