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如 ...
随机推荐
- Particle Editor 无法启动此程序,因为计算机中丢失MSCP110.dll。尝试重新安装该程序以解决此问题。
昨天下载了一个Particle Editor V2.1,打开时显示下面错误 网上百度了也不知是什么原因,回到家在另一台电脑上打开就行了,很奇怪... 两台电脑vs一台是vs2010,家里的一台是vs2 ...
- c语言指针函数与函数指针
例一:指针函数 指针函数是指带指针的函数,即本质是一个函数.函数返回类型是某一类型的指针 类型标识符 *函数名(参数表) int *f(x,y); 首先它是一个函数,只不过这个函数的返回值是一个 ...
- 小白日记29:kali渗透测试之Web渗透-扫描工具-Vega
WEB扫描工具-Vega 纯图形化界面,Java编写的开源web扫描器.两种工作模式:扫描模式和代理模式[主流扫描功能].用于爬站.处理表单,注入测试等.支持SSL:http://vega/ca.cr ...
- VB读写INI文件的四个函数以及相关API详细说明
WritePrivateProfileString函数说明 来源:http://blog.csdn.net/wjb9921/article/details/2005000 在我们写的程序当中,总有一 ...
- oracle存储过程分页
1.首先在oracle中建包体,用于游标返回当前数据记录集 CREATE OR REPLACE PACKAGE pkg_query AS TYPE cur_query IS REF CURSOR; E ...
- Scala中的数组
数组 数组的两种声明方式,建议声明数组时指定类型. 访问数组元素时获取数组下标 数组Array类本身有很多非常方便的方法 变长数组ArrayBuffer,能够动态增加元素,也可以实现与Array的互转 ...
- [改善Java代码]不同的场景使用不同的泛型通配符
Java泛型支持通配符(Wildcard),可以单独使用一个"?"表示任意类,也可以使用extends关键字标识某一类(接口)的子类型,还可以使用super关键字标识某一类(接口) ...
- Flexible 弹性盒子模型之CSS flex-direction
实例 设置 <div> 元素内弹性盒元素的方向为相反的顺序: div { display:flex; flex-direction:row-reverse; } 复制 效果预览 浏览器支持 ...
- tools安装
1.ruby安装 下载安装包 勾选中间一个 2.sass 安装 转换TB镜像 $ gem sources --remove https://rubygems.org/$ gem sources - ...
- Spring(3.2.3) - Beans(1): Spring 容器
BeanFactory & ApplicationContext org.springframework.beans.factory.BeanFactory 是最基本的 Spring 容器接口 ...