背景:答题卡阅卷需要光标阅读机,有些小学校买不起光标阅读机。
主要开源库:opencv,版本3.0。
识别原理:把答题卡放在深色背景中,用查找轮廓定位好答题卡位置,用透视变换取出答题卡图像,根据位置判断是否被涂黑,识别出ABCD,对比标准答题计算出成绩。
打包应用下载:
http://veryjuly.com/anomr/anomr.apk
答题卡定位与识别代码先在windows下测试完成,然后通过NDK编译让android用JNI方式调用。
Windows下用图片做测试源,主函数如下:
int main(intargc, char ** argv)
{
cvNamedWindow("test", CV_WINDOW_NORMAL);
unsignedcharresults[64 * 24];
intret = 0;
char* img_file = ".\\samples\\save.jpg";
IplImage* src = NULL; //源图像
src =cvLoadImage(img_file, 1);
if(!src){
printf("Couldn't load %s\n", img_file);
return0;
}
clock_tstart, finish;
doubleTotal_time;
start= clock();
ret =cv_omr(src, results);
finish= clock();
Total_time= (double)(finish - start) ;
printf("%f ms\n", Total_time);
if(ret == 0)
printf("识别成功。\n");
if(ret == 1)
printf("答题卡四边形定位失败。\n");
if(ret == 2)
printf("行坐标获取失败。\n");
return0;
}
其中int cv_omr(IplImage *img_src, unsignedchar *results);为测试程序与android应用都要使用的主要识别函数,unsignedchar *results为返回识别结果。
Android通过下面的函数来调用识别函数:
int Yuv420sp_omr(unsignedchar*results, unsignedchar * yuvdata, intwidth, int height)
{
intret = 0;
IplImage*image;
image= cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3);
Yuv420sp2RGBimg(yuvdata,image, width, height);
//保存图像到SD卡,观察是否正确;win 下调试
//cvSaveImage("/storage/emulated/0/save.jpg",image, 0);
//可以开始识别了,保存测试图片时不运行下面的代码
ret =cv_omr(image, results);
//结束,释放图像
//cvReleaseImage(&image);
returnret;
}
此函数把Yuv420sp格式的图像数据转换成IplImage,再调用识别函数。