• 网上阅卷系统自动识别功能代码


    想让自己轻松点就要让计算机多为你做点! 

    前几天一个朋友找到我让我做一个网上阅卷系统,就是实现这么几个功能:高速扫描仪扫描试卷后得到一张一张的图片,软件的功能就是处理图片,计算成绩。再详细点就是自动识别考生涂的学号,自动识别考生的选择题答案并记录,后面的大题要分块,把每一个题从试卷中分离出来,转发给老师进行阅卷。最后就是实现成绩的汇总与分析。

    说起来功能也不算复杂,实现起来细节性的东西还是挺多的,比如每一科的试卷都不相同,要做一个通用型的软件,适合各种类型的试卷,还有就是服务器的设置呀,学生信息的保密呀,各种错误的处理啊……反正挺麻烦的,都怪我知识不够。
     
    下面说说识别的方法:这实际上就是一个概率算法,只要是被涂了的方格就是黑色的,没有涂的就只有红色或浅色的数字还有外面的框,如下图,这样的话我们就能根据方格的颜色来判断是不是被涂了。一个方格里面有很多点,我们通过取每个点的颜色,得到相应的RGB颜色分量,由于黑色是RGB(0,0,0),白色是RGB(255,255,255),其他的颜色就介于两者之间了,我是用RGB三个分量直接求和来判断这个点是不是被涂黑了,当然要有一个判断标准,我的标准是三个数的和小于30就被认为是黑色。当然这个数字可以变,根据扫描出来的图片质量来看了,如果质量不是很好,有点模糊的话,就应该比30大了。这样的话我们只是得到一个点,要判断整个方格的话就要把里面的所有点都判断一次,只要两个for循环就可以得到所有的点,然后我们要做好相应的统计,假设方格里面总共有total个点,黑色的点有count个,这样我们count/total就会得到一个概率,我假设概率大于0.5也就是有一半的点是黑色的我认为这个点是被涂过了,当然这也是一个可变参数,根据实际情况来确定吧。既然这个点被涂过了,我们就能得到这个点的位置,然后就可以推断出这个位置对应的数字或者选择题的ABCD,把所有的数字组合起来就是学号了,把所有的ABCD组合起来就是答案了,然后我们就可以和标准答案进行比较,得出结果。

    软件运行截图(可以正确识别学号):

     

    程序源码: 

     /*    

        功能:网上阅卷系统的识别
        作者:ma6174
        邮箱:ma6174@163.com
        时间:2012年2月23日
        其他:包含的头文件<graphics.h>来则easyx的图形库
    */
    #include<stdio.h>
    #include<graphics.h>
    #include<stdlib.h>
    #include<string.h>
    #include<conio.h>
    #include<windows.h>
    //定义方格的大小和方格的间距,根据实际情况做相应的修改
    #define BOX_X 42
    #define BOX_Y 13
    #define BLANK_X 18
    #define BLANK_Y 25
    //颜色分量类
    class rgb
    {
    public:
        BYTE red;
        BYTE green;
        BYTE blue;
    };
    //判断一个点是不是黑色
    bool judge_black(rgb color)
    {
        if(color.blue+color.green+color.red<30)//可能会有点误差,根据实际情况调整
            return true;//黑色,有标记
        return false;
    }
    //判断一个方格有没有被填涂
    bool judge_box(int x,int y,HDC hdc)
    {
        int i,j,total=0,count=0;
        COLORREF color;
        for(i=x+2;i<x+BOX_X-2;i++)//循环判断所有点
        {
            for(j=y+1;j<y+BOX_Y-1;j++)
            {
                total++;
                color=GetPixel(hdc,i,j);
                rgb temp;
                temp.red=GetRValue(color);
                temp.green=GetGValue(color);
                temp.blue=GetBValue(color);
                if(judge_black(temp)==true)
                    count++;
            }
        }
        if(double(count)/total>0.5)//黑色的比例大于50%则认为该方格被填涂
            return true;
        return false;
    }
    //判断所有的,入口参数分别是起始横坐标,起始纵坐标,行数,列数,窗口句柄
    void judge_all(int start_x,int start_y,int hangshu,int lieshu,HDC hdc)
    {
        int i,j;
        for(i=0;i<hangshu;i++)
        {
            for(j=0;j<lieshu;j++)
            {
    //            Sleep(50);
    //            circle(start_x+i*(BOX_X+BLANK_X),start_y+j*(BOX_Y+BLANK_Y),10);
                if(judge_box(start_x+i*(BOX_X+BLANK_X),start_y+j*(BOX_Y+BLANK_Y),hdc)==true)
                {
                    printf("%d",j);
    //                outtextxy(start_x+i*(BOX_X+BLANK_X),start_y+j*(BOX_Y+BLANK_Y),"A");
                }
            }
    //        printf("\n");
        }
    }
    int main()
    {
        int start_x,start_y,total=0,count=0;
        initgraph(1440,900);
        cleardevice();
        IMAGE img;
        loadimage(NULL,"d:\\1.jpg");
        HDC hdc = GetImageHDC();
        MOUSEMSG m;
        while(1)//通过鼠标点击得到起始位置
        {
            m=GetMouseMsg();
            if(m.uMsg==WM_LBUTTONDOWN)
            {
                start_x=m.x;
                start_y=m.y;
                break;
            }
        }
        judge_all(start_x,start_y,18,10,hdc);
        printf("\n");
        getch();
    }

    目前只是实现了基本的识别功能。当然如果仅仅是识别只有学号和选择的答题卡这些功能就够了。真正使用的话还要进行完善,比如增加选择题的识别,控制功能等。当然软件功能也可以进一步扩展,比如自动识别开始位置等。


    博主ma6174对本博客文章(除转载的)享有版权,未经许可不得用于商业用途。转载请注明出处http://www.cnblogs.com/ma6174/

    对文章有啥看法或建议,可以评论或发电子邮件到ma6174@163.com


  • 相关阅读:
    net use命令详解(转)
    SQL Server架构SQL Server的执行模式和SQLOS
    SQL Server架构SQL Server的执行模式和SQLOS
    利用xcopy命令实现本地文件复制到远程服务器的方法
    利用xcopy命令实现本地文件复制到远程服务器的方法
    xcopy部署
    xcopy部署
    css样式—字体垂直、水平居中
    音视频&流媒体
    分布式编译工具
  • 原文地址:https://www.cnblogs.com/ma6174/p/2365407.html
Copyright © 2020-2023  润新知