網上閱卷系統自動識別功能代碼


 

想讓自己輕松點就要讓計算機多為你做點! 

前幾天一個朋友找到我讓我做一個網上閱卷系統,就是實現這么幾個功能:高速掃描儀掃描試卷后得到一張一張的圖片,軟件的功能就是處理圖片,計算成績。再詳細點就是自動識別考生塗的學號,自動識別考生的選擇題答案並記錄,后面的大題要分塊,把每一個題從試卷中分離出來,轉發給老師進行閱卷。最后就是實現成績的匯總與分析。

說起來功能也不算復雜,實現起來細節性的東西還是挺多的,比如每一科的試卷都不相同,要做一個通用型的軟件,適合各種類型的試卷,還有就是服務器的設置呀,學生信息的保密呀,各種錯誤的處理啊……反正挺麻煩的,都怪我知識不夠。
 
下面說說識別的方法:這實際上就是一個概率算法,只要是被塗了的方格就是黑色的,沒有塗的就只有紅色或淺色的數字還有外面的框,如下圖,這樣的話我們就能根據方格的顏色來判斷是不是被塗了。一個方格里面有很多點,我們通過取每個點的顏色,得到相應的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();
}

目前只是實現了基本的識別功能。當然如果僅僅是識別只有學號和選擇的答題卡這些功能就夠了。真正使用的話還要進行完善,比如增加選擇題的識別,控制功能等。當然軟件功能也可以進一步擴展,比如自動識別開始位置等。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM