📄 abstract_character.cpp
字号:
/****************************************************************************** * 光学字符识别程序 * 文件名:abstract_aharacter.cpp * 功能 :抽象字符类实现文件 * modified by PRTsinghua@hotmail.com******************************************************************************/#include <stdlib.h>#include <ostream>#include "common.h"#include "abstract_character.h"using std::cout;using std::endl;/****************************************************************************** * 未匹配区域******************************************************************************/float abstract_connection::unmatched_area(const vector<abstract_singular_point> &aspv){ if( is_matched ) return 0; float length=0; point<float> p=aspv[singular_point_1]; list< point<float> >::iterator i=polyline.begin(); while( i!=polyline.end() ) { length+=euklidian_distance(p.x,p.y, i->x,i->y); p=*i; ++i; } length+=euklidian_distance(p.x,p.y, aspv[singular_point_2].x,aspv[singular_point_2].y); return weight*length*length;}/****************************************************************************** * <<操作******************************************************************************/ostream& operator<< (ostream& o, point<float> &p){ o << '(' << p.x << ',' << p.y << ')'; return o;}/****************************************************************************** * <<操作******************************************************************************/ostream& operator<< (ostream& o, abstract_character &c){ int nr=0; o << "--- singular points ---" << endl; for(vector<abstract_singular_point>::iterator i=c.aspv.begin(); i!=c.aspv.end(); ++i) { o << nr++ << ": (" << i->x << ',' << i->y << ") is " << i->type << " with connections: "; for(list<int>::iterator j=i->acl.begin(); j!=i->acl.end(); ++j) { if( j!=i->acl.begin() ) o << ", "; o << *j; } o << endl; } nr=0; o << "--- connections ---" << endl; for(vector<abstract_connection>::iterator i=c.acv.begin(); i!=c.acv.end(); ++i) { o << nr++ << ": " << i->singular_point_1 << "->" << i->singular_point_2 << " is " << i->type << " with polygon points: "; for(list< point<float> >::iterator j=i->polyline.begin(); j!=i->polyline.end(); ++j) o << '(' << j->x << ',' << j->y << ") "; o << endl; } return o;}/****************************************************************************** * <<操作******************************************************************************/ostream& operator<< (ostream& o, const path& p){ o << p.singular_point_1 << "-["; for(list<int>::const_iterator i=p.connections.begin(); i!=p.connections.end(); ++i) { if( i!=p.connections.begin() ) o << ", "; cout << *i; } o << "]->" << p.singular_point_2; return o;}/****************************************************************************** * 变换操作 * 参数:angle 旋转角度 * scale 变化比例 * x x 坐标 * y y 坐标 * 返回:无******************************************************************************/transformation::transformation(float angle, float scale, float x, float y) : min_x(FLT_MAX), max_x(-FLT_MAX), min_y(FLT_MAX), max_y(-FLT_MAX), scale_factor(scale), x_0(x), y_0(y), a(cos(angle)), b(-sin(angle)), c(sin(angle)), d(cos(angle)){}/****************************************************************************** * 平移变换 * 参数:x x坐标 * y y坐标 * t_x x方向平移坐标 * t_y y方向平移坐标 * 返回:无******************************************************************************/void transformation::transform(float x, float y, float &t_x, float &t_y){ x=scale_factor*(x-x_0); y=scale_factor*(-y-y_0); t_x=a*x+b*y; t_y=c*x+d*y; if( t_x<min_x ) min_x=t_x; if( t_x>max_x ) max_x=t_x; if( t_y<min_y ) min_y=t_y; if( t_y>max_y ) max_y=t_y;}/****************************************************************************** * 开始跟踪路径******************************************************************************/path::const_iterator path::begin() const{ const_iterator it; it.base_char=base_char; it.cached_point=&(base_char->aspv[singular_point_1]); it.end_state=false; it.end_point=singular_point_1; it.con_iter=connections.begin(); it.con_last=--connections.end(); it.setup_polyline_iterators(); return it;}/****************************************************************************** * 重新开始跟踪路径******************************************************************************/path::const_reverse_iterator path::rbegin() const{ const_reverse_iterator it; it.base_char=base_char; it.cached_point=&(base_char->aspv[singular_point_2]); it.end_state=false; it.end_point=singular_point_2; it.con_iter=--connections.end(); it.con_last=connections.begin(); it.setup_polyline_iterators(); return it;}/****************************************************************************** * 获得未匹配的分歧点******************************************************************************/float path::get_unmatched_divergence(){ float divergence=0; float x=0,y=0; for(const_iterator i=begin(); i!=end(); ++i) { if( i!=begin() && !i.is_matched() ) { float segment_area=euklidian_distance(x,y, i->x,i->y); divergence+=i.get_weight()*segment_area*segment_area; } x=i->x; y=i->y; } return divergence;}/****************************************************************************** * 标记未匹配的部分******************************************************************************/void path::mark_unmatched(){ for(list<int>::iterator i=connections.begin(); i!=connections.end(); ++i) base_char->acv[*i].is_matched=true;}/****************************************************************************** * 标记******************************************************************************/void path::mark(){ for(list<int>::iterator i=connections.begin(); i!=connections.end(); ++i) { base_char->acv[*i].is_matched=true; base_char->acv[*i].weight+=1.0; }}/****************************************************************************** * 内部路径******************************************************************************/inner_path::inner_path(abstract_character &ac, int start_point, int end_point) : path(&ac){ singular_point_1=start_point; singular_point_2=end_point;}/****************************************************************************** * 附加连接******************************************************************************/bool inner_path::append_connection(int con){ if( contains_connection(con) ) return false; connections.push_back(con); return true;}/****************************************************************************** * 路径树构造函数******************************************************************************/tree_path::tree_path(abstract_character &ac, int start_point) : path(&ac){ singular_point_1=start_point; singular_point_2=start_point;}/****************************************************************************** * 附加连接******************************************************************************/bool tree_path::append_connection(int con){ assert( singular_point_1!=-1 ); if( contains_connection(con) ) return false; connections.push_back(con); singular_point_2=base_char->acv[con].walk(end_point()); return true;}/****************************************************************************** * 移除最后一个连接******************************************************************************/void tree_path::remove_last_connection(){ singular_point_2=base_char->acv[connections.back()].walk(end_point()); connections.pop_back();}/****************************************************************************** * hash表******************************************************************************/namespace __gnu_cxx {template<> struct hash< const singular_point* >{ size_t operator()( const singular_point* const& key ) const { return reinterpret_cast<size_t>(key); // hash value is the pointer itself }};/****************************************************************************** * hash表******************************************************************************/template<> struct hash< const connection* >{ size_t operator()( const connection* const& key ) const { return reinterpret_cast<size_t>(key); }};}/****************************************************************************** * 移除连接******************************************************************************/int abstract_character::resolve_con( const connection *con, hash_map<const singular_point*, int, hash<const singular_point*> > &spmap, hash_map<const connection*, int, hash<const connection*> > &conmap, transformation &T){ hash_map<const connection*, int, hash<const connection*> >::iterator coni = conmap.find(con); if( coni!=conmap.end() ) return coni->second; acv.push_back( abstract_connection() ); abstract_connection &acon=acv.back(); int aconnr=acv.size()-1; conmap[con]=aconnr; acon.type=con->type; acon.singular_point_1=resolve_sp(con->point1,spmap,conmap,T); acon.singular_point_2=resolve_sp(con->point2,spmap,conmap,T); bool first=true; for(list<skeleton_sequence>::const_iterator i=con->sseql.begin(); i!=con->sseql.end(); ++i) { float x,y; if( first ) { T.transform(i->first->aligned_x,i->first->aligned_y,x,y); acon.polyline.push_back( point<float>(x,y) ); first=false; } T.transform(i->last->aligned_x,i->last->aligned_y,x,y); acon.polyline.push_back( point<float>(x,y) ); } return aconnr;}/****************************************************************************** * 去除孤立点******************************************************************************/int abstract_character::resolve_sp( const singular_point *sp, hash_map<const singular_point*, int, hash<const singular_point*> > &spmap, hash_map<const connection*, int, hash<const connection*> > &conmap, transformation &T){ hash_map<const singular_point*, int, hash<const singular_point*> >::iterator spi = spmap.find(sp); if( spi!=spmap.end() ) return spi->second; aspv.push_back( abstract_singular_point() ); abstract_singular_point &asp=aspv.back(); int aspnr=aspv.size()-1; spmap[sp]=aspnr; T.transform(sp->x,sp->y,asp.x,asp.y); asp.type=sp->type; for(list< inner_sequence_start >::const_iterator j=sp->sequences.begin(); j!=sp->sequences.end(); ++j) asp.add_connection( resolve_con(j->connect,spmap,conmap,T) ); return aspnr;}/****************************************************************************** * 笔划 * 参数:thickness 粗细 * x1 点1的x坐标 * y1 点1的y坐标 * x2 点2的x坐标 * y2 点2的y坐标******************************************************************************/void abstract_character::stroke(transformation &T, float thickness, float x1, float y1, float x2, float y2){ float x=x2-x1,y=y2-y1; if( is_equal(x*x+y*y,0) ) // 线是一个点 { T.transform(x1,y1,x,y); return; } thickness/=2; float angle=atan2(y,x); float dx=cos(angle-M_PI_2)*thickness; float dy=sin(angle-M_PI_2)*thickness; T.transform(x1+dx,y1+dy,x,y); T.transform(x2+dx,y2+dy,x,y); dx=cos(angle+M_PI_2)*thickness; dy=sin(angle+M_PI_2)*thickness; T.transform(x1+dx,y1+dy,x,y); T.transform(x2+dx,y2+dy,x,y);}/******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -