📄 common_gfx.cpp
字号:
} }}/****************************************************************************** * 画图标识******************************************************************************/void Histogram::toggle_draw_flag( unsigned int flag ){ if ( draw_flags & flag ) draw_flags &= ~flag; // 清除标识 else draw_flags |= flag; // 设置标识}/****************************************************************************** * 键盘事件******************************************************************************/void Histogram::keyPressEvent( QKeyEvent *e ){ switch (e->key()) { case Key_W: toggle_draw_flag( draw_max_white ); break; case Key_B: toggle_draw_flag( draw_max_black ); break; case Key_T: toggle_draw_flag( draw_threshold ); break; case Key_I: toggle_draw_flag( draw_middle ); break; case Key_M: toggle_draw_flag( draw_mean_value ); break; case Key_Print: save(); break; default: if ( parent ) { QKeyEvent accel_event(QEvent::Accel, e->key(), e->ascii(), 0); QApplication::sendEvent( parent, &accel_event ); QApplication::sendEvent( parent, e ); } } repaint();}/****************************************************************************** * 边缘跟踪 * 参数:start_x x起点坐标 * start_y y起点坐标 * 返回:无******************************************************************************/void Walker::walk_border( int start_x, int start_y ){ const int x_offset[] = { /* down */ 0, /* right */ 1, /* up */ 0, /* left */ -1 }; const int y_offset[] = { /* down */ 1, /* right */ 0, /* up */ -1, /* left */ 0 }; direction d = left, t; int x = start_x, y = start_y; int walker_x, walker_y; int count = 0; // 搜寻邻近的自由点 while ( !is_good_walker_start( walker_x = x + x_offset[d], walker_y = y + y_offset[d] ) && count++ < 4 ) ++d; if ( count >= 4 ) // 没有发现合适的起点 return; walker_process2( walker_x, walker_y ); int first_walker_x = walker_x, first_walker_y = walker_y; // 正确的方向 while( t = leftof(d), walker_x + x_offset[t] != x || walker_y + y_offset[t] != y ) ++d; int last_x = -1, last_y = -1; int same_pixel_count = 0; bool stopit = false; do { if ( !stopit && ( x != last_x || y != last_y ) ) { walker_process( x, y ); last_x = x; last_y = y; same_pixel_count = 0; } else same_pixel_count++; if ( is_border_pixel( x = walker_x + x_offset[d], y = walker_y + y_offset[d] ) ) --d; else { walker_process2( walker_x, walker_y ); walker_x = x; walker_y = y; t = leftof(d); if ( !is_border_pixel( x = walker_x + x_offset[t], y = walker_y+y_offset[t] ) ) // 角点 { walker_x = x; walker_y = y; ++d; // 逆时针旋转 t = leftof(d); x = walker_x + x_offset[t]; y = walker_y + y_offset[t]; } } if ( !( x != start_x || y != start_y || ( last_x == start_x && last_y == start_y && same_pixel_count < 3 ) ) ) stopit = true; } while ( !stopit || walker_x != first_walker_x || walker_y != first_walker_y );}/****************************************************************************** * 判断是否好的起点 * 参数:x x坐标 * y y坐标 * 返回:返回bool值******************************************************************************/bool CharImageWalker::is_good_walker_start( int x, int y ) const{ return img.is_background( x, y ) && ( !img.is_background( x-1, y ) || !img.is_background( x+1, y ) || !img.is_background( x, y-1 ) || !img.is_background( x, y+1 ) );}float straight_line::function( float xval ) const{ // y = gradient * x + y_axis_intercept float gradient = tan( angle ); float y_axis_intercept = y - gradient * x; return xval * gradient + y_axis_intercept;}/****************************************************************************** * 计算交叉点 * 参数:line2 * x_intersect 保存交叉点的x坐标 * y_intersect 保存交叉点的y坐标 * 返回:返回bool值******************************************************************************/bool straight_line::intersect(const straight_line &line2, float &x_intersect, float &y_intersect) const{ float angle1 = normalize_line_angle( angle + M_PI_2 ); float angle2 = normalize_line_angle( line2.angle + M_PI_2 ); float tan_phi1 = tan( angle1 ); float sin_phi2 = sin( angle2 ); float cos_phi2 = cos( angle2 ); float divisor = cos_phi2*tan_phi1 - sin_phi2; if( is_null( divisor ) ) return false; x_intersect = -( sin_phi2 * ( x + tan_phi1 * (y - line2.y) ) - tan_phi1 * cos_phi2 * line2.x )/divisor; y_intersect = ( cos_phi2 * ( x + tan_phi1 * y - line2.x ) - sin_phi2 * line2.y )/divisor; return true;}/****************************************************************************** * 归一化 * 参数:x x坐标 * y y坐标 * 返回:无******************************************************************************/straight_line straight_line::normal(float x, float y) const{ return straight_line(x,y,normalize_line_angle(angle + M_PI_2));}/****************************************************************************** * 计算垂线 * 参数:px x坐标 * py y坐标 * x_perpendicular 垂足的x坐标 * y_perpendicular 垂足的y坐标 * 返回:无******************************************************************************/void straight_line::construct_perpendicular(float px, float py, float &x_perpendicular, float &y_perpendicular) const{ assert( intersect( normal(px,py), x_perpendicular, y_perpendicular ) );}/****************************************************************************** * 判断点序列是否和线段相交******************************************************************************/bool line_segment::intersect( const line_segment &seg2, bool touch_is_intersect, point<float> *pi ){ point<float> A = p1; point<float> B = p2; point<float> C = seg2.p1; point<float> D = seg2.p2; float nominator1 = ( A.y - C.y ) * ( D.x - C.x ) - ( A.x - C.x ) * ( D.y - C.y ); float nominator2 = ( A.y - C.y ) * ( B.x - A.x ) - ( A.x - C.x ) * ( B.y - A.y ); float denominator = ( B.x - A.x ) * ( D.y - C.y ) - ( B.y - A.y ) * ( D.x - C.x ); if ( is_null( denominator ) ) { if ( is_null( nominator1 ) ) return true; // 共线的情况 else return false; // 平行的情况 } float r = nominator1 / denominator; float s = nominator2 / denominator; if ( pi ) // 如有必要,计算交叉点 { pi->x = A.x + ( r * (B.x - A.x) ); pi->y = A.y + ( r * (B.y - A.y) ); } if ( !touch_is_intersect ) // 如果起点和终点相同,则无交叉点 { // 考虑机器精度 if ( !specify( r, 0 ) ) specify( r, 1 ); if ( !specify( s, 0 ) ) specify( s, 1 ); return ( r > 0 && r < 1 && s > 0 && s < 1 ); } else return ( r >= 0 && r <= 1 && s >= 0 && s <= 1 );}/****************************************************************************** * 3×3滤波器******************************************************************************/int filter( int x, int y, CharImage src, float H[3][3] ){ int Se[3][3] = { { src.get_pixel( x-1, y-1 ), src.get_pixel( x, y-1 ), src.get_pixel( x+1, y-1 ) }, { src.get_pixel( x-1, y ), src.get_pixel( x, y ), src.get_pixel( x+1, y ) }, { src.get_pixel( x-1, y+1 ), src.get_pixel( x, y+1 ), src.get_pixel( x+1, y+1 ) } }; int k = 1, Sa = 0; for ( int u=0; u<3; u++ ) for ( int v=0; v<3; v++ ) Sa += qRound( Se[1+k-v][1+k-u] * H[v][u] ); return qRound( Sa/9.0 );}/****************************************************************************** * 3×3滤波器******************************************************************************/CharImage filter( CharImage src, float H[3][3] ){ CharImage filtered( src.width(), src.height(), 32 ); for ( int y = 0; y < src.height(); y++ ) for ( int x = 0; x < src.width(); x++ ) filtered.set_pixel( x, y, filter( x, y, src, H ) ); return filtered;}/****************************************************************************** * 3×3滤波器******************************************************************************/CharImage filter( CharImage src, float Hx[3][3], float Hy[3][3], int mode ){ // 模式含义 // 0 = magnitude of gradient (default) // 1 = angle of gradient (see below) // 2 = border (b/w) CharImage filtered( src.width(), src.height(), 32 ); for ( int y = 0; y < src.height(); y++ ) for ( int x = 0; x < src.width(); x++ ) { int Gx = filter( x, y, src, Hx ); int Gy = -filter( x, y, src, Hy ); if ( mode == 0 || mode == 2 ) filtered.set_pixel( x, y, static_cast<int>( sqrt( Gx*Gx + Gy*Gy ) + 0.5 ) ); else { if ( Gx == 0 && Gy == 0 ) filtered.set_pixel( x, y, 0 ); else { float angle = atan2( Gy, Gx ); filtered.set_pixel( x, y, static_cast<int>( normalize_angle_2pi(angle)/(2*M_PI) * 255 + 0.5 ) ); } } } if ( mode == 2 ) { filtered.set_bw_threshold( 16 ); filtered = filtered.convert_bw(); } return filtered;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -