字符分割
来源:互联网 发布:ubuntu安装网易云音乐 编辑:程序博客网 时间:2024/05/02 00:26
ANN在训练和识别时都只能将一个单独的数字作为样本,因此对于扫描图像中的多个连续数字需要进行分割。具体算法如下:
1,确定图像中字符的大致高度范围:先自下而上对图像进行逐行扫描,直到遇到第一个黑素像素,记下行号,然后自上而下对图像进行逐行扫描,直到遇到第一个黑素像素,记下行号。这两个行号就标志出了字符大致的高度范围。
2,确定每个字符的左起始和右终止位置:在第一步得到的高度范围内进行自左向右逐列扫描,遇到第一个黑色像素时,认为是字符分割的起始位,然后继续扫描,直到遇到有一列中没有黑色像素,认为是这个字符的右终止位置,准备开始进行下一个字符的分割。按照上述方法继续扫描,直到扫描到图像的最右端。这样就得到了每个字符的比较精确的快读范围。
3,在已知的每个字符比较精确的宽度范围内,再按照第一步的方法,分别自下而上和自上而下,逐行扫描,来获取每个字符精确的高度范围。
完整实现代码如下:
/****************************************************************参数: 对前景目标(如字符)进行划分,将各个字符的轮廓矩形返回注 : 只能处理二值图像返回值:无***************************************************************/void Ctry::ObjectSegment(){// TODO: 在此添加命令处理程序代码IplImage* img = cvLoadImage("C:\\Users\\Administrator\\Desktop\\dst.jpg", -1);vector<RECT> vecRoughRECT; //粗略对象轮廓的矩形向量数组vector<RECT> vecRECT; //精化后对象轮廓的矩形向量数组//清空用来表示每个对象的vectorvecRoughRECT.clear();vecRECT.clear();int nTop, nBttom; //整体前景区域的上下边界int nObjCnt = 0; //对象数目 //从上向下扫描,找到整体区域的前景的上边界for (int i = 0; i < img->height; i++){for (int j = 0; j < img->width; j++){double pixel = cvGetReal2D(img, i, j);if (int(pixel)==0){nTop = i;i = img->height; //对i赋大值,使得在break跳出内存循环后,直接在跳出外层循环break;}}}//从下向上扫描,找到整体区域的前景的下边界for (int i = img->height -1; i >=0; i--){for (int j = 0; j < img->width; j++){double pixel = cvGetReal2D(img, i, j);if (int(pixel) == 0){nBttom = i;i = -1; //对i赋小值,使得在break跳出内存循环后,直接在跳出外层循环break;}}}bool bStartSeg = false; //是否已经开始某一个对象的分割bool bBlackInCol; //某一列中是否包含黑色像素RECT rt;//按列扫描,找到每一个目标的左右边界for (int j = 0; j < img->width; j++){bBlackInCol = false;for (int i = 0; i < img->height; i++){double pixel = cvGetReal2D(img, i, j);if (int(pixel) == 0){bBlackInCol = true; //该列中发现黑点if (!bStartSeg) //还没有进入一个对象的分割{bStartSeg = true;//进入一个对象的分割rt.left = j;}elsebreak;}}if (j == (img->width - 1)) //扫描到最后一列了,说明整个图像扫描完毕{break;}//正处在分割状态,且扫描完一列都没有发现黑像素,表明当前对象分割完毕if (bStartSeg && !bBlackInCol){rt.right = j; //对象右边界确定//对象的粗略上下边界(有待精化)rt.top = nTop;rt.bottom = nBttom;::InflateRect(&rt, 1, 1); //矩形框膨胀一个像素,以免绘制时压到字符vecRoughRECT.push_back(rt); //插入vectorbStartSeg = false; //当前分割结束nObjCnt++; //对象数目加1}}RECT rtNEW; //存放精化对象区域的矩形框//由于得到了精确的左右边界,现在可以精化矩形框的上下边界int nSize = vecRoughRECT.size();for (int nObj = 0; nObj < nSize; nObj++){rt = vecRoughRECT[nObj];rtNEW.left = rt.left - 1;rtNEW.right = rt.right + 1;//从上向下逐行扫描边界for (int i = rt.top; i < rt.bottom; i++){for (int j = rt.left; j < rt.right; j++){double pixel = cvGetReal2D(img, i, j);if (int(pixel) == 0){rtNEW.top = i - 1;//对i赋大值,使得在break跳出内存循环后,直接在跳出外层循环i = rt.bottom;break;}}}//从下向上逐行扫描边界for (int i = rt.bottom - 1; i > rt.top; i--){for (int j = rt.left; j < rt.right; j++){double pixel = cvGetReal2D(img, i, j);if (int(pixel) == 0){rtNEW.bottom = i + 1;//对i赋小值,使得在break跳出内存循环后,直接在跳出外层循环i = rt.top-1;break;}}}vecRECT.push_back(rtNEW);}//画矩形框,显示分割字符for (int i = 0; i < vecRECT.size(); i++){int x = vecRECT[i].left-1;int y = vecRECT[i].top-1;int x1 = vecRECT[i].right+1;int y1 = vecRECT[i].bottom + 1;CvPoint pt1(x, y);CvPoint pt2(x1, y1);cvRectangle(img, pt1, pt2, CV_RGB(255, 0, 0), 1);}cvSaveImage("C:\\Users\\Administrator\\Desktop\\rect.jpg", img);cvNamedWindow("image1", 1);cvShowImage("image1", img);cvWaitKey(0);cvDestroyWindow("image1");cvReleaseImage(&img);}
效果图:
注:此算法对图像的进行处理前,需要对图形进行预处理,尤其是去噪,这里代码没有给出。图片质量不好,或预处理方法不对,效果也就不理想。
0 0
- 分割字符
- 字符分割
- 字符分割
- 字符分割
- 字符定位与字符分割
- 字符定位与字符分割
- 字符串插入分割字符
- 字符分割函数.
- 用javascript分割字符
- 字符分割拆分妙用
- asp之字符分割
- C++ string 分割字符
- matlab字符分割程序
- awk 二次分割字符
- Oracle SQL 字符分割
- 批处理字符分割
- 字符的分割函数
- Matlab字符分割程序
- 在使用select标签,请老老实实使用document.getElementById()
- AndroidSweetSheet
- SpringMVC的理解
- Android控件动画
- gzexe.XXXXXXXXXX decode
- 字符分割
- 一个ClassCastException引发的思考
- win10桌面图标自己排例恢复
- 快速索引
- 最近的一些想法(1)
- 用递归程序编写斐波那契
- 关键词密度多少比较好?
- 解决mysql"Access denied for user'root'@'IP地址'"问题
- poj 1250 Tanning Salon 【模拟题】