opencv 手写选择题阅卷 (一)表格设计与识别
(一)答题表格设计与识别
实际设计好的表格如下图

为了图像精确,表格和四角的标记都是由程序生成的,文字和数据是后期排版软件添加上去的.
图中四角的四个黑方块主要用来定位表格,然后就可以切割出每个单元格,最后去做字符识别.
具体步骤为:
1,灰度化并二值化;
2,查找轮廓,把找出四个定位标记;
3,透视变换,校正变形;
4,切割表格,分别识别每个表格;
实际操作中发现最关键的是表格一定要平整,变形对识别影响较大;
部分代码:
int table_recognition(IplImage* img,unsigned char * result)
{
//大图二值化
IplImage* bin_img = cvCloneImage(img);
image_threshold(bin_img);
//去噪
IplImage* tmp_img = cvCloneImage(bin_img);
cvErode(tmp_img, tmp_img, NULL, ); //腐蚀
cvDilate(tmp_img, tmp_img, NULL, ); //膨胀
//查找轮廓
CvSeq* contours;
CvMemStorage * storage = cvCreateMemStorage();
cvSetImageROI(tmp_img, cvRect(, , bin_img->width, bin_img->height));
cvFindContours(tmp_img, storage, &contours, , ));
];
];
];
CvPoint points[][];
;
// 检测每个轮廓
for (; contours; contours = contours->h_next)
{
//用指定精度逼近多边形曲线
CvSeq* result;
result = cvApproxPoly(contours, );
//不是四边形的不要
)
continue;
//不是凸多边形不要
if (!cvCheckContourConvexity(result))
continue;
//面积大小或小于指定值的排除
));
)
continue;
//解码每个轮廓标志,正确的保存下来**********************************************
CvPoint2D32f srcQuad[];
; i < ; i++){
CvPoint* pt = (CvPoint*)cvGetSeqElem(result, i);//取标记四边形的四个顶点
points[n][i] = *pt;
srcQuad[i].x = (float)pt->x;
srcQuad[i].y = (float)pt->y;
}
//透视变换取出marker
IplImage * mark_img = cvCreateImage(cvSize(,), , );
perspective(bin_img, mark_img, srcQuad);
//
int rt = marker_decode(mark_img, &ids[n], &rotates[n], &vals[n]);
)
continue;
//
n++;
)
break;
}
)//发现四个标记
;
//if (rotates[0] != rotates[1] || rotates[1] != rotates[2] || rotates[2] != rotates[3])//四个标记旋转一致
// return -1;
//marker 0123
] != && ids[] != && ids[] != && ids[] != )
;
] != && ids[] != && ids[] != && ids[] != )
;
] != && ids[] != && ids[] != && ids[] != )
;
] != && ids[] != && ids[] != && ids[] != )
;
//确定表格四个点
CvPoint2D32f pts[];
; i < ; i++)
{
int id = ids[i];
int rotate = rotates[i];
CvPoint pt;
){
pt = points[i][( + rotate)%];
}
){
pt = points[i][( + rotate) % ];
}
){
pt = points[i][( + rotate) % ];
}
){
pt = points[i][( + rotate) % ];
}
pts[id].x = pt.x;
pts[id].y = pt.y;
}
//CvPoint2D32f tmp_ptf = pts[1];
//pts[1] = pts[3];
//pts[3] = tmp_ptf;
IplImage * table_img = cvCreateImage(cvSize(*, *+), , );
perspective(img, table_img, pts);
//表格分割
;
IplImage* gird_img = cvCreateImage(cvSize(, ), , );
; j < ; j+=)
{
; i < ; i++)
{
cvSetImageROI(table_img, cvRect(+*i, +*j, , ));
cvCopy(table_img, gird_img);
#ifdef _WIN32
save_gird(gird_img, nt);
#endif
int rt = svm_recognition(gird_img);
result[nt] = rt;
nt++;
}
}
//cvNamedWindow("Image", CV_WINDOW_NORMAL);
//cvShowImage("Image", gird_img);
//cvWaitKey(0);
cvReleaseImage(&bin_img);
cvClearMemStorage(storage);
;
}
opencv 手写选择题阅卷 (一)表格设计与识别的更多相关文章
- opencv 手写选择题阅卷 (二)字符识别
opencv 手写选择题阅卷 (二)字符识别 选择题基本上只需要识别ABCD和空五个内容,理论上应该识别率比较高的,识别代码参考了网上搜索的代码,因为参考的网址比较多,现在也弄不清是参考何处的代码了, ...
- opencv 手写选择题阅卷 (四)Android端 手机应用开发
opencv 手写选择题阅卷 (四)Android 手机应用开发 在PC端把代码调通以后开始开发Android 手机应用,因为主要功能代码为C++代码,所以需要通过NDK编译,JAVA通过JNI方式调 ...
- opencv 手写选择题阅卷 (三)训练分类器
opencv 手写选择题阅卷 (三)训练分类器 1,分类器选择:SVM 本来一开始用的KNN分类器,但这个分类器目前没有实现保存训练数据的功能,所以选择了SVN分类器; 2,样本图像的预处理和特征提取 ...
- OpenCV手写数字字符识别(基于k近邻算法)
摘要 本程序主要参照论文,<基于OpenCV的脱机手写字符识别技术>实现了,对于手写阿拉伯数字的识别工作.识别工作分为三大步骤:预处理,特征提取,分类识别.预处理过程主要找到图像的ROI部 ...
- TF:TF分类问题之MNIST手写50000数据集实现87.4%准确率识别:SGD法+softmax法+cross_entropy法—Jason niu
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data # number 1 to 10 ...
- AI应用开发实战 - 手写识别应用入门
AI应用开发实战 - 手写识别应用入门 手写体识别的应用已经非常流行了,如输入法,图片中的文字识别等.但对于大多数开发人员来说,如何实现这样的一个应用,还是会感觉无从下手.本文从简单的MNIST训练出 ...
- 背水一战 Windows 10 (62) - 控件(媒体类): InkCanvas 保存和加载, 手写识别
[源码下载] 背水一战 Windows 10 (62) - 控件(媒体类): InkCanvas 保存和加载, 手写识别 作者:webabcd 介绍背水一战 Windows 10 之 控件(媒体类) ...
- 5 TensorFlow入门笔记之RNN实现手写数字识别
------------------------------------ 写在开头:此文参照莫烦python教程(墙裂推荐!!!) ---------------------------------- ...
- 用tensorflow搭建RNN(LSTM)进行MNIST 手写数字辨识
用tensorflow搭建RNN(LSTM)进行MNIST 手写数字辨识 循环神经网络RNN相比传统的神经网络在处理序列化数据时更有优势,因为RNN能够将加入上(下)文信息进行考虑.一个简单的RNN如 ...
随机推荐
- Linux用户及用户组设置
查看当前用户所属的组 groups 查看<user1>, <user2> 和 <user3>所属的组 groups <user1> <user2 ...
- npm获取配置,设置代理
npm获取配置有6种方式,优先级由高到底. 命令行参数. --proxy http://server:port即将proxy的值设为http://server:port. 环境变量. 以npm_con ...
- win7系统激活最简单方法
利用激活工具快速激活WIN7系统! 工具/原料 小马Oem7.未激活的WIN7系统 步骤/方法 1 复制BT种子 http://www.pccppc.com/download/oem7F.rar粘贴到 ...
- iOS: 属性声明strong和retain竟然不一样
今天和同事在处理一处用strong声明的Block属性引发的问题时偶然发现的.在诸多教程中都会讲到:声明属性时用strong或者retain效果是一样的(貌似更多开发者更倾向于用strong).不过在 ...
- SQL 生成一个日期范围
有时想按日或月生成一个序列,就像2014-1-1.2014-1-2.2014-1-3... 在sql server中可以写个函数来实现. /* 生成一个日期范围,如2014.01.2014.02... ...
- oracle的控制语句if和循环语句loop while for
pl/sql的控制结构if-then if-then-else if-then-elsif-else 案例1:编写一个过程,可以输入一个雇员名,如果该雇员的工资低于2000,就给该雇员工资增加10% ...
- 在vs环境中跑动sift特征提取(代码部分)
因为在前两天的学习中发现.在opencv环境中跑动sift特征点提取还是比较困难的. 所以在此,进行记述. 遇到的问题分别有,csdn不愿意花费积分.配置gtk困难.教程海量然而能跑者鲜.描述不详尽等 ...
- 有关ftp4j的FTPListParseException异常
昨天换了个ftp服务器,发现程序出现了异常it.sauronsoftware.ftp4j.FTPListParseException,网上搜了下,说是FTPClient.list()时it.sauro ...
- 伸展树 Splay Tree
Splay Tree 是二叉查找树的一种,它与平衡二叉树.红黑树不同的是,Splay Tree从不强制地保持自身的平衡,每当查找到某个节点n的时候,在返回节点n的同时,Splay Tree会将节点n旋 ...
- 自定义android Dialog
1.自定义Dialog: import android.app.AlertDialog; import android.app.Dialog; import android.content.Conte ...