1.图形基类(CShape)
1.1 描述
图形基类,提供所有图形的标准属性和方法。其他图形类(直线、圆)等都是该类的子类,继承其所有的public属性和方法,对其中的虚方法(virtual)进行重定义和实现。
该类为虚类,其成员函数主要为虚函数,为其所有子类提供统一的接口,但是没有实现。其他模块对图形进行操作时,除非生成新的实例(Instance),都无须知道所操作的是哪个具体的图形,而统一使用Cshape类型,为程序的实现、扩充和维护提供很大方便。
1.2 实现
class CShape {
public:
/*属性定义*/
//前景色(由于时间等的限制,本系统暂时只定义该图形的属性,其
// 他如:填充色,线条型,填充型等可扩充)
TColor color;
/*编辑用属性*/
//编辑时标志该图形是否被选择
bool isSelected;
//编辑操作所选中的点
TPoint * editP
/*识别用属性*/
//识别的效果描述,值越小说明识别效果越好
// 最小二乘法的平均误差;
// 霍夫变换:1 -参数空间中该图形的值/最大值
double chance;
//图形上点的数量
int pointCount;
/*成员函数定义*/
/*显示和描述用方法*/
//显示图形:在指定的位图上显示图形
virtual void draw(Graphics::TBitmap * argDest);
//描述图形:作为TtreeView的节点(主窗体使用)
virtual void discript(int index, TTreeView * tree);
//描述图形:返回描述图形的字符串
virtual String discript();
/*识别用*/
//比较两个图形,如果是同一个图形,返回True,否则False。
// 直线上的两个线段;圆上面的两个圆弧
virtual bool similarWith(CShape * argShape);
//合并两个图形
// 经过判断为相同的图形进行合并,返回True;否则返回False。
virtual bool mergeWith(CShape * argShape);
//判断图形存在的可能性(利用具体图形的几何规则)
virtual bool checkPossible();
/*编辑用*/
//判断是否点击该图形,若选中则当前编辑的图形改为当前图形
virtual bool isClickOnShape(int x, int y);
//取得鼠标形状:鼠标移动到选中图形的可操作点上时,显示为编辑形状
virtual TCursor getCursor(int x, int y);
//更新图形:将编辑点移动到(x, y)点。更新成功返回True,否则False。
virtual bool update(int x, int y);
};
2.图形类(CLine、CCircle)
2.1 描述
图形类是几何图形的具体实现,实现对应几何图形的描述和相关操作。图形类有共同的父类CShape,对父类中定义的虚方法根据本几何图形的特征进行实现。
根据要求,本系统中实现了直线(CLine)和圆(CCircle)两个图形类。其他简单的几何图形如椭圆、矩形等也可以类似的方法实现,作为本系统的一个扩充。
本系统中,直线类采用直观的的形式来描述直线(既避免点斜式不能描述竖直直线,也避免极坐标方程转换的问题)。因为成比例的两组和表示同一条直线,所以规定,如果B参数不为0,则,否则A必定不为0,则。由于要识别图像中的线段,所以增加两个端点进行限制。
直线类有三个点可以编辑:1)两个端点,选中一个端点并移动,是以另一端点为轴进行旋转;2)线段的中点,选中中点并移动,是平移整个直线。
圆类采用的形式描述(其中为圆心,R为半径),直观方便。圆上有两个点支持编辑操作:1)圆心,选中圆心并移动,是平移整个圆;2)圆上的一个点,选中该点并移动,是改变圆的半径,圆心不变。
2.2 实现
l 直线类(CLine)
class CLine: public CShape {
public:
/*初始化*/
CLine(double argA, double argB, double argC);
/*直线的属性*/
//线段的两个端点
TPoint *startP, *endP;
//直线方程的参数:A,B,C
double A, B, C;
/*对父类虚方法的实现*/
//在目标位图上画出直线(本系统中的实现为画线段)
void draw(Graphics::TBitmap * argDest);
//在TTreeView中描述
void discript(int index, TTreeView * tree);
//返回描述用字符串
String discript();
// 判断该直线是否与指定图形相同
// 将指定图形强制转化为CLine类型,比较其参数A, B, C,
// 若小于指定阈值,则返回Ture,否则返回False。
bool similarWith(CShape * argShape);
//合并同一直线上的两个线段
// 若目标图形与该图形属同一直线,进行合并,返回True;
// 否则返回False。
void mergeWith(CShape * argShape);
//判断是否选择该直线进行编辑。
// 判断指定点(x, y)到该直线的距离,
// 如果小于指定阈值则返回True,否则False。
bool isClickOnShape(int x, int y);
//取得鼠标形状。
// 端点时返回45度,135度的双向箭头形状表示旋转;
// 中点时返回垂直的四个方向箭头的形状表示移动
TCursor getCursor(int x, int y);
//更新直线
bool update(int x, int y);
};
l 圆类(CCircle)
class CCircle: public CShape {
public:
/*初始化*/
CCircle(int argX, int argY, int argR);
/*圆的属性*/
//圆心
TPoint * centerP;
//半径
int R;
/*对父类虚方法的实现*/
//在目标位图上画出圆
void draw(Graphics::TBitmap * argDest);
//在TTreeView中描述
void discript(int index, TTreeView * tree);
//返回描述用字符串
String discript();
// 判断该圆是否与指定图形相同
// 将指定图形强制转化为CCircle类型,比较其参数圆心坐标和半径,
// 若小于指定阈值,则返回Ture,否则返回False。
bool similarWith(CShape * argShape);
//合并同一圆上的两个圆弧
// 若目标图形与该图形属同一圆,进行合并,返回True;
// 否则返回False。
void mergeWith(CShape * argShape);
//判断是否选择该圆进行编辑。
// 计算指定点(x, y)到圆心的距离,并与半径比较,
// 如果小于指定阈值则返回True,否则False。
bool isClickOnShape(int x, int y);
//取得鼠标形状。
// 圆上点时返回水平的双向箭头形状表示改变半径;
// 圆心时返回垂直的四个方向箭头的形状表示移动
TCursor getCursor(int x, int y);
//更新圆
bool update(int x, int y);
};
3.图形容器类(CShapes)
3.1 描述
图形容器类是图形类的集合类,由C++ Builder的TList继承得到。用来组织对图像的识别结果、组织当前编辑工作的图形对象集。提供添加图形、删除图形、图形编辑等接口。
3.2 实现
class CShapes : public TList {
public:
/*初始化*/
CShapes();
//从TreeView得到Shapes
CShapes(TTreeView * tree);
//在目标位图上画出所有的图形
void drawShapes(Graphics::TBitmap * argDest);
//描述图形
void discript(TTreeView * tree);
};
4.点类(CPoint)
4.1 描述
点类对于与图像上的前景点。由于识别时需要判断是否为交点,在一般的点的基础上增加是否为交点的属性。由C++ Builder的TPoint继承得到。
4.2 实现
class CPoint : public TPoint {
public:
/*初始化*/
CPoint() {isCrossPoint = false; };
CPoint(int argx, int argy, bool isCross);
CPoint(int argx, int argy, Graphics::TBitmap * argImg);
/*属性:是否为交点*/
bool isCrossPoint;
};
5.单义域类(CSegment)
5.1 描述
在“基于单义域的图形识别算法”中,单义域和多义域的唯一区别就是多义域不是单一的几何元素,其在存储结构上是一样的,在本系统中,都由CSegment类实现,姑且命名为单义域类。
单义域类为点的集合类,由C++ Builder的TList类继承得到。提供添加点、删除点、判断该单义域是否有识别价值、识别该单义域等接口和方法。
5.2 实现
class CSegment : public TList {
public:
/*初始化*/
CSegment(CPoint * p);
/*识别该单义域:实现算法中对单义域的识别部分*/
// 如果识别成功(得到圆或线段)返回True,否则返回False
bool recognize();
/*尝试添加新的点到该单义域*/
// 判断该点是否属于该单义域并确定是在头部还是在尾部,并将其插入到适当位置;如果该点为交点,则将相应的方向关闭增长;若加入成功返回True,否则返回False。
bool addNewPoint();
/*判断该单义域是否有识别价值*/
//如果该单义域含有的点数太少,则没有价值返回False,否则返回True。
bool checkValue();
/*属性:识别出的图形*/
CShape * shape;
};
6.基于单义域识别类(CSegments)
6.1 描述
基于单义域识别类是实现“基于单义域的直线和圆识别算法”的主要类。它实现了对目标图像的分割、对分割结果的显示、对识别得到的多义域进行分割、对单义域识别结果的总体考虑,最终得到识别结果集。
基于单义域识别类同时是单义域的集合类,由C++ Builder的TList类继承得到。用来组织对图像的单义域分割后的结果。。
6.2 实现
class CSegments : public TList {
public:
/*构造和析构函数*/
CSegments();
~CSegments();
/*扫描图像,得到多义域*/
//从上往下,从左往右扫描图像,对于每一个前景点
// 1。生成新的CPoint实例
// 2。对于本类中的所有单义域,将该点尝试加入
// 3。如果加入失败,以该点为头生成新的单义域并加入。
void segmentize(Graphics::TBitmap * argSrc);
/*在指定的位图上显示分割得到的多义域、单义域*/
void displaySegments(Graphics::TBitmap * argDes);
/*识别该集合中的元素*/
// 1。调用单义域的checkValue(),如果得到False,删除该单义域;
// 2。调用单义域的recognize(),如果返回False,对该单义域进行分割;
// 将新得到的2个单义域取代当前的单义域,并进行识别
// 3。所有的单义域识别完毕后,对各个单义域的识别结果进行合并
// 4。返回得到的图形容器类。
CShapes * recognize();
/*删除集合中的指定位置的元素*/
void removeItemOnly(int index);
void removeItemAndFreePoints(int index);
};
7.霍夫变换识别直线类(CHTLine)
7.1 描述
实现霍夫变换识别直线算法。
7.2 实现
class CHTLine {
public:
/*构造和析构函数*/
CHTLine ();
~ CHTLine ();
/*对源位图按照直线识别算法进行霍夫变换*/
// argRho, argTheta分别是对r和q的分割的份数。
void recognize(Graphics::TBitmap * argSource, int argRho, int argTheta);
/*在目标位图上显示参数坐标的信息*/
// 以参数坐标的最大值为灰度最大值,按比例灰度在位图上显示。
void displayPramater(Graphics::TBitmap * argDest);
/*按照argRate指定的概率取得识别出的直线列表*/
void getLines(TList * argList, double argRate);
};
8.霍夫变换识别圆类(CHTCircle)
8.1 描述
实现霍夫变换识别圆算法。
8.2 实现
class CHTCircle {
public:
/*构造和析构函数*/
CHTCircle ();
~ CHTCircle ();
/*对源位图按照圆的识别算法进行霍夫变换*/
void recognize(Graphics::TBitmap * argRes);
/*在目标位图上显示参数坐标的信息*/
// 以参数坐标的最大值为灰度最大值,按比例灰度在位图上显示参数坐标中指定半径的二维平面的数据。
void displayPramater(Graphics::TBitmap * argDest, int argR);
/*按照argRate指定的概率取得识别出的直线列表*/
void getCircles(TList * argList, double argRate);
};
第二节主程序实现
第三节系统功能介绍
1.识别部分
(1).基于霍夫变换下的识别
启动recognize.exe
File->open打开要识别的bmp文件
Hough Trans->ling recognize得到识别出的直线的霍夫变换图,图中的每个亮点代表一条直线;
识别的圆的概率圆,在下面的Edit控件中是你想要显示的圆的直径,输入后点display后就可以看到霍夫变换的结果
注:由于霍夫变换是一个三维的循环,消耗内存较多,速度较慢,所以图像的原图的大小直接影响到速度。
下面是几幅图象的实验结果: