📄 character.h
字号:
/****************************************************************************** * 光学字符识别程序 * 文件名:character.h * 功能 :字符类定义文件 * modified by PRTsinghua@hotmail.com******************************************************************************/#ifndef CHARACTER_H#define CHARACTER_H#include <list>#include <complex>#include "common_gfx.h"#include "common_math.h"#include "segimage.h"using std::ostream;using std::polar;typedef enum { left_curved=-1, straight=0, right_curved=1 } curvature_type;typedef enum { end_point, branching_point, turning_point } point_type;inline curvature_type operator-(curvature_type t){ return static_cast<curvature_type>( -static_cast<int>(t) );};struct inner_point : public point<float>{ float direction; // 方向 float thickness; // 粗细 float aligned_x; // 多边形终点: 交叉点x坐标 float aligned_y; // 多边形终点: 交叉点y坐标 float angle; // 夹角 inline void set_angle(const inner_point &prev, const inner_point &next); };typedef list<inner_point> inner_sequence;struct correlation_info : public correlation<inner_point>{ void align_connection_point(const correlation_info &prev_ci); inline void set_angle();};typedef correlation_info skeleton_sequence;struct singular_point;struct connection{ curvature_type type; // 曲线类型 singular_point *point1; // 起点 singular_point *point2; // 终点 float length; // 曲线长度 float mean_dist; // 点线平均距离 list< skeleton_sequence > sseql; // 多边形曲线近似 float distance_to_start( point<float> *p ); float distance_to_end( point<float> *p );};inline float connection::distance_to_start( point<float> *p ){ return euklidian_distance(p->x, p->y, sseql.front().first->aligned_x, sseql.front().first->aligned_y);}inline float connection::distance_to_end( point<float> *p ){ return euklidian_distance(p->x, p->y, sseql.back().last->aligned_x, sseql.back().last->aligned_y);}struct subconnection{ int curvature_signum; // +/-1 凸/凹; 0 直线 int num_sequences; // 序列数目 float length; // 总的曲线长度 list<skeleton_sequence>::iterator start; // 起点 list<skeleton_sequence>::iterator end; // 终点 subconnection() : curvature_signum(0), num_sequences(0), length(0) {} inline void add_sequence_at_front(list<skeleton_sequence>::iterator n); inline void add_sequence(list<skeleton_sequence>::iterator n); inline void remove_last_sequence();};struct inner_sequence_start { bool is_start; inner_sequence* sequence; connection* connect; void get_connection_info(const subconnection &sc); inner_sequence_start() : is_start(false) {} ~inner_sequence_start();};struct singular_point : public point<float>{ point_type type; int area; list< inner_sequence_start > sequences; void set_type(); void delete_connection(connection *con);};class character{ public: list<singular_point> spl; int min_x, min_y, max_x, max_y; // 字符包围边界 float line_thickness; // 截面平均粗细 character(const Segimage &segimage, list<Segimage::singularpoint> &spl_old); // 缺省的析构函数释放了所有的变量 private: static const float threshold; // 如果方向的平均变化超过阈值,则停止 static const float lower_factor; // 合并后更大的序列的百分比 static const float smooth_iterations_factor; // 方向平滑次数 static const int lower_boundary; // 骨架序列的上限点数 static const int sufficient_number; // 骨架序列的下限点数 static const float md_threshold; // 用来决定直线判断的经验相关系数阈值 static const float md_compound_threshold; // 复合直线的距离均值阈值 static const float angle_treshold; // 角度阈值 static const float acute_angle_threshold; // 锐角阈值 static const float straight_line_threshold_for_merge; // 直线合并阈值 static const float straight_line_lower_threshold_for_intersect; // 两条线夹角的下阈值 static const float straight_line_upper_threshold_for_intersect; // 两条线夹角的上阈值 static const float straight_line_threshold; // 直线合并阈值 static const float curve_to_line_ratio; // 曲线直线转换比 float long_line; // 字符中长线的长度 float short_line; // 字符中短线的长度 int char_size; // 水平/垂直 大小中的相对大者 int min_sequence; // 可能的直线最短距离 static void merge_segments(const skeleton_sequence &prev, const skeleton_sequence &curr, skeleton_sequence &result); static void add_direction(complex<float> &c, float angle); static bool is_bigger(list<skeleton_sequence>::iterator curr, list<skeleton_sequence>::iterator other, list< skeleton_sequence > &sseql); bool is_good_line(const connection &conn); float choose_direction(float dir, float last); bool average_angle(const float a[], int num_elements, float &result); void collect_curve_segments(list< skeleton_sequence > &sseql); void detect_curves(); void identify_curves(); void strip_extra_line(); void find_dots(); void beautify(); void delete_connection(connection *con);};//// 内联函数定义///****************************************************************************** * 设置角度 * 参数:prev 前一个点 * next 后一个点 * 返回:无******************************************************************************/inline void inner_point::set_angle(const inner_point &prev, const inner_point &next){ angle=angle_between(prev.aligned_x, prev.aligned_y, aligned_x, aligned_y, next.aligned_x, next.aligned_y);}/****************************************************************************** * 设置角度 * 参数:无 * 返回:无******************************************************************************/inline void correlation_info::set_angle(){ angle=atan2(last->y-first->y, last->x-first->x);}/****************************************************************************** * 序列前添加 * 参数:n 迭代器 * 返回:无******************************************************************************/inline void subconnection::add_sequence_at_front(list<skeleton_sequence>::iterator n){ if( num_sequences==0 ) end=n; num_sequences++; length+=euklidian_distance(n->first->aligned_x,n->first->aligned_y, n->last->aligned_x,n->last->aligned_y); start=n;}/****************************************************************************** * 增加序列一个 * 参数:n 迭代器 * 返回:无******************************************************************************/inline void subconnection::add_sequence(list<skeleton_sequence>::iterator n){ if( num_sequences==0 ) start=n; num_sequences++; length+=euklidian_distance(n->first->aligned_x,n->first->aligned_y, n->last->aligned_x,n->last->aligned_y); end=n;}/****************************************************************************** * 移去最后序列 * 参数:无 * 返回:无******************************************************************************/inline void subconnection::remove_last_sequence(){ assert( num_sequences>0 ); length-=euklidian_distance(end->first->aligned_x,end->first->aligned_y, end->last->aligned_x,end->last->aligned_y); num_sequences--; if( num_sequences>0 ) end--; if( num_sequences<=1 ) curvature_signum=0;}/****************************************************************************** * 添加方向 * 参数:c 复数 * angle 角度 * 返回:无******************************************************************************/inline void character::add_direction(complex<float> &c, float angle){ c+=polar(1.0F,angle);}/****************************************************************************** * 选择方向 * 参数:dir 方向 * last 最后一个 * 返回:方向******************************************************************************/inline float character::choose_direction(float dir, float last){ float d1=fabs(normalize_angle_pi(dir-last)); float d2=fabs(normalize_angle_pi(normalize_angle_pi(dir+M_PI)-last)); return d1<d2?dir:normalize_angle_pi(dir+M_PI);}/****************************************************************************** * 判断字符是否更大 * 参数:curr 当前迭代器 * other 另一个迭代器 * 返回:是,则返回true,否则返回false******************************************************************************/inline bool character::is_bigger(list<skeleton_sequence>::iterator curr, list<skeleton_sequence>::iterator other, list< skeleton_sequence > &sseql){ return other!=sseql.end() && other->num_points>=sufficient_number && (curr->num_points<=lower_boundary || (curr->num_points<other->num_points*lower_factor));}/****************************************************************************** * 评价线的好坏 * 参数:conn 连接 * 返回:是好线,返回true,否则返回false******************************************************************************/inline bool character::is_good_line(const connection &conn){ return conn.type==straight && (conn.length>short_line || (2*conn.length>line_thickness && conn.mean_dist<md_threshold));}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -