国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別

這篇具有很好參考價值的文章主要介紹了計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

0 簡介

?? 優(yōu)質(zhì)競賽項目系列,今天要分享的是

基于機(jī)器視覺的試卷系統(tǒng) - opencv python 視覺識別

該項目較為新穎,適合作為競賽課題方向,學(xué)長非常推薦!

?? 更多資料, 項目分享:

https://gitee.com/dancheng-senior/postgraduate文章來源地址http://www.zghlxwxcb.cn/news/detail-732552.html

1 項目背景

機(jī)器視覺的發(fā)展對存在的作業(yè)批改問題, 提供了有效的解決方案。 通過基于機(jī)器視覺的作業(yè)批改系統(tǒng)可以對老師的教學(xué)工作進(jìn)行輔助,改變傳統(tǒng)的批改作業(yè)方式,
幫助老師減輕教學(xué)壓力和工作負(fù)擔(dān), 老師可以快速完成批改過程,及時反饋給學(xué)生。 家長同樣需要從繁重的重復(fù)性檢查作業(yè)工作中解脫出來,
將更多的精力放在關(guān)注學(xué)生的學(xué)習(xí)情況和發(fā)現(xiàn)學(xué)習(xí)問題上。 學(xué)生可以通過自我批改作業(yè)中發(fā)現(xiàn)問題、加深理解, 培養(yǎng)自主學(xué)習(xí)意識, 提高分析問題和解決問題的能力。
因此, 自動批改作業(yè)系統(tǒng)在教育領(lǐng)域的應(yīng)用表現(xiàn)出了無可比擬的教育價值和發(fā)展前景。
計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

2 項目目的

在教育領(lǐng)域中人工智能應(yīng)用愈加廣泛, 作業(yè)在教學(xué)過程中起到重要的作用,當(dāng)前作業(yè)批改存在著重復(fù)勞動、 效率低下等諸多問題,
這種傳統(tǒng)的批改作業(yè)方式占據(jù)了老師寶貴的時間。 本文設(shè)計一種作業(yè)批改視覺系統(tǒng), 將人工智能應(yīng)用到教育領(lǐng)域中, 改變老師傳統(tǒng)的批改作業(yè)方式,
實現(xiàn)自動批改數(shù)學(xué)算式作業(yè)的任務(wù)。

學(xué)長設(shè)計了一個系統(tǒng)系統(tǒng),可以協(xié)助老師和家長完成繁重和重復(fù)的作業(yè)批改和檢查工作, 提高工作效率。

3 系統(tǒng)設(shè)計

3.1 目標(biāo)對象

學(xué)長這里以數(shù)學(xué)作業(yè)試卷識別為目標(biāo)。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

數(shù)學(xué)作業(yè)圖像中一列包含多個算式, 字符主要包括印刷體的算式題目和手寫體答案組成, 如上圖 所示為一張數(shù)學(xué)算式作業(yè)圖像。
本課題的難點在于如何有效的去除光線等外部干擾因素, 準(zhǔn)確的提取到作業(yè)圖像中的單個算式信息;選取有效的字符識別算法,
針對印刷體字符和手寫體字符設(shè)計混合字符分類器,進(jìn)行有效、 快速的識別; 選取適合的嵌入式設(shè)備, 進(jìn)行軟件與硬件的系統(tǒng)集成,實現(xiàn)視覺系統(tǒng)的基本功能,
完成穩(wěn)定性的批改過程。

3.2 系統(tǒng)架構(gòu)

通過對視覺系統(tǒng)的研究以及完成作業(yè)批改解決方案的設(shè)計目標(biāo), 采取 PC 平臺與嵌入式平臺相結(jié)合的設(shè)計方案。 針對 PC 平臺進(jìn)行軟件設(shè)計與算法優(yōu)化,
完成系統(tǒng)的功能要求后, 將程序移植到嵌入式系統(tǒng)中, 在嵌入式設(shè)備實現(xiàn)系統(tǒng)的便捷化應(yīng)用。 對于設(shè)計的系統(tǒng)采取多平臺測試分析, 保證系統(tǒng)在 PC
平臺準(zhǔn)確高效的運(yùn)行, 同時保證嵌入式系統(tǒng)中表現(xiàn)出穩(wěn)定的性能。 系統(tǒng)的總體結(jié)構(gòu)框圖如下。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

首先按照系統(tǒng)功能需求進(jìn)行分析, 確定要完成的設(shè)計任務(wù)和目標(biāo), 并對系統(tǒng)的功能和性能分析做出設(shè)計要求。 其次根據(jù)系統(tǒng)的功能劃分, 選取基于 PC
平臺的軟件設(shè)計方案完成軟件編程, 對系統(tǒng)實現(xiàn)的功能進(jìn)行驗證, 測試其功能和性能是否符合設(shè)計要求。 選取視覺系統(tǒng)的嵌入式開發(fā)平臺,
進(jìn)行硬件模塊設(shè)計和開發(fā)環(huán)境及軟件平臺的搭建, 將系統(tǒng)軟硬件集成在一起進(jìn)行調(diào)試進(jìn)行, 對系統(tǒng)存在的問題做出改進(jìn)和優(yōu)化。

最后通過系統(tǒng)測試, 分別對系統(tǒng)的功能和性能進(jìn)行測試驗證, 是否滿足設(shè)計的要求。 最終構(gòu)建一款多平臺應(yīng)用, 基于機(jī)器視覺的自動作業(yè)批改視覺系統(tǒng)。

3.3 軟件設(shè)計方案

該系統(tǒng)基于機(jī)器視覺的圖像處理和字符識別技術(shù), 整個系統(tǒng)的核心是軟件設(shè)計部分。 能否對作業(yè)有效和快速的批改,
很大程度上取決于軟件設(shè)計部分圖像處理的效果和字符識別的準(zhǔn)確率。 軟件設(shè)計主要完成系統(tǒng)相關(guān)的功能操作,設(shè)計流程可分為圖 中的模塊組成。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

圖像獲取是將攝像頭等設(shè)備獲取的作業(yè)圖像信息轉(zhuǎn)化為數(shù)字圖像信息; 預(yù)處理是對圖像進(jìn)行二值化轉(zhuǎn)換, 去除多余噪聲, 進(jìn)行每一組算式提取,
分割獲得單個清晰字符輪廓的過程; 特征提取是對預(yù)處理后的字符圖像, 進(jìn)行字符特征提取, 將提取好的特征量輸入到分類器, 為字符識別做準(zhǔn)備;
字符識別是系統(tǒng)的核心, 對字符分類器進(jìn)行設(shè)計, 通過分析訓(xùn)練樣本的特征, 將待預(yù)測的樣本進(jìn)行分類, 對字符完成準(zhǔn)確識別;
結(jié)果輸出是通過公式計算器計算印刷體算式結(jié)果與手寫結(jié)果進(jìn)行對比, 判斷算式作業(yè)是否作答正確完成反饋的程。

4 圖像預(yù)處理

試卷字符識別過程中, 通過攝像頭采集到的紙張作業(yè)圖像信息由于受到光線產(chǎn)生的噪聲、 書寫的污點等干擾因素, 影響字符圖像的提取效果。
為了得到完整的字符區(qū)域特征, 同時去除無關(guān)信息的干擾, 需要對圖像進(jìn)行預(yù)處理操作。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

4.1 灰度二值化

灰度二值化是將圖像先進(jìn)行灰度處理, 再進(jìn)行二值化處理。 經(jīng)過灰度二值化處理的圖像降低了像素的運(yùn)算量, 同時突出圖像中算式的特征。
灰度化是將采取到的彩色圖像進(jìn)行灰度值轉(zhuǎn)換, 灰度化后的圖像去除了彩色信息, 只保留了算式字符與背景之間的亮度信息, 圖像中每個像素點都是介于 0 至 255
灰度值中的一種。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

關(guān)鍵代碼

?
#3、將 RGB 轉(zhuǎn)為灰度圖
def rgb2gray(rgb):
return np.dot(rgb[…,:3], [0.299, 0.587, 0.114])

gray = rgb2gray(lena)    
# 也可以用 plt.imshow(gray, cmap = plt.get_cmap('gray'))
plt.imshow(gray, cmap='Greys_r')
plt.axis('off')
plt.show()

from scipy import misc
lena_new_sz = misc.imresize(lena, 0.5) # 第二個參數(shù)如果是整數(shù),則為百分比,如果是tuple,則為輸出圖像的尺寸
plt.imshow(lena_new_sz)
plt.axis('off')
plt.show()

附上imresize的用法
功能:改變圖像的大小。
用法:
B = imresize(A,m)
B = imresize(A,m,method)
B = imresize(A,[mrows ncols],method)
B = imresize(...,method,n)
B = imresize(...,method,h)

imrersize函數(shù)使用由參數(shù)method指定的插值運(yùn)算來改變圖像的大小。
method的幾種可選值:
'nearest'(默認(rèn)值)最近鄰插值
'bilinear'雙線性插值
'bicubic'雙三次插值
B = imresize(A,m)表示把圖像A放大m倍
B = imresize(...,method,h)中的h可以是任意一個FIR濾波器(h通常由函數(shù)ftrans2、fwind1、fwind2、或fsamp2等生成的二維FIR濾波器)。

?

4.2 形態(tài)學(xué)處理

形態(tài)學(xué)處理是通過一定形態(tài)的結(jié)構(gòu)元素, 對圖像產(chǎn)生基于形狀的操作 。它可以在保持圖像基本形狀的基礎(chǔ)上簡化數(shù)據(jù), 去除多余結(jié)構(gòu)。
形態(tài)學(xué)運(yùn)算主要包括開運(yùn)算和閉運(yùn)算, 這兩個操作包含了膨脹和腐蝕。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

算式圖像經(jīng)過形態(tài)學(xué)處理后, 實驗效果如上圖所示。 在圖中可以看出左側(cè)的算式圖像經(jīng)過形態(tài)學(xué)處理之后, 其斷裂的乘號字符在右側(cè)的算式圖像中形成了連通區(qū)域。
形態(tài)處理后字符整體趨于完整, 邊界變的平滑。

在手寫字符識別的過程中, 由于手寫字符的字跡大小、 粗細(xì)程度存在的隨意性很大, 在特征提取的過程中, 相同字符的冗余度導(dǎo)致特征向量差異很大 。

因此對獲取字符圖像要進(jìn)行適當(dāng)?shù)募?xì)化處理, 有利于特征提取的準(zhǔn)確性。 圖像細(xì)化指將二值圖像進(jìn)行骨架化操作的運(yùn)算, 細(xì)化操作過程就是剝離字符圖像上邊緣輪廓的點,
細(xì)化操作要求字符骨架保持原有的筆畫特征, 不能造成筆劃斷開, 同時具有連續(xù)性, 字符圖像應(yīng)盡量保留原始的結(jié)構(gòu)特征。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

關(guān)鍵代碼

?
import cv2 as cv

img = cv.imread(r"C:\Users\Administrator\Desktop\chinese.png")
img_cvt = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
ret,img_thr = cv.threshold(img_cvt,100,255,cv.THRESH_BINARY)
kernel = cv.getStructuringElement(cv.MORPH_RECT,(30,1)) #由于是1*30的矩陣,字體會被橫向空隙的白色腐蝕掉,而下劃線橫向都是黑色,不會腐蝕
dst = cv.dilate(img_thr,kernel,iterations=1)  #由于是白底黑字,所有進(jìn)行膨脹操作來去除黑色字體
cv.imshow("img_thr",img_thr)
cv.imshow("dst",dst)
cv.waitKey(0)
cv.destroyAllWindows()

4.3 算式提取

算式提取的主要任務(wù)是從紙張中找到其中一組算式的字符區(qū)域, 并將算式從所在的區(qū)域中提取出來。 經(jīng)過算式提取操作,
可以針對每一組算式進(jìn)行批改,同時也便于下一步的字符分割, 算式提取準(zhǔn)確性對作業(yè)批改效果有直接的影響。二值化處理后的算式圖像中算式的灰度值為 255,
背景的灰度值為 0。

采取基于投影的方法, 進(jìn)行水平和垂直方向的投影對算式進(jìn)行提取 , 由于字符圖像和背景圖像對比度較大, 背景幾乎不存在噪音干擾,
因此投影分割可以取得較好的效果。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

對圖像進(jìn)行列掃描, 得到垂直方向投影圖, 投影后字符間隔的白色像素點的個數(shù)為 0, 在字符區(qū)域處形成波峰。 此時根據(jù)多個連續(xù)的波峰圖像,
記錄開始和結(jié)束的位置, 就可求得算式的左右邊界, 進(jìn)行分割得到僅包含一組算式區(qū)域的圖像。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java
計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

4.4 傾斜校正

在圖像獲取的過程中, 由于攝像頭拍攝角度和作業(yè)圖像有時會產(chǎn)生一個傾斜角度, 此時圖像會發(fā)生垂直傾斜, 如果不對算式圖像進(jìn)行傾斜校正處理,
可能會無法正確識別出字符。 因此算式提取后要對算式圖像進(jìn)行傾斜校正, 采用基于 Hough 變換的方法,
其原理為圖像中的直線和曲線經(jīng)過變換映射到參數(shù)空間上的一個點, 通過累加的峰值檢驗圖像中的直線和曲線。 Hough
變換的實質(zhì)是將圖像中一定形狀元素的點進(jìn)行聚類, 通過解析式將參數(shù)空間對應(yīng)的點聯(lián)系起來。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

4.5 字符分割

字符分割指是將一組算式中的多個字符圖像根據(jù)字符之間的空隙, 分割成多張只包含單個字符的圖像,
字符分割需要保證對每個字符進(jìn)行完整的提取。作業(yè)字符圖像是一連串的數(shù)字算式字符, 由于算式中包含除號和等號不連通的字符圖像,
因此不便采取投影法對字符進(jìn)行分割。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

5 字符識別

支持向量機(jī)是一種新的解決分類問題的機(jī)器學(xué)習(xí)方法, 基于統(tǒng)計學(xué)習(xí)理論,采用結(jié)構(gòu)風(fēng)險最小原則。 其原理是在訓(xùn)練樣本集通過少量支持向量,
自動構(gòu)造分類函數(shù)建立一個最大間隔分類平面, 以此解決分類問題。 支持向量機(jī)不需要構(gòu)建網(wǎng)絡(luò)結(jié)構(gòu)設(shè)計, 通過非線性變換解決高維空間中樣本識別問題。
支持向量機(jī)越來越多的應(yīng)用到了字符識別中, 表現(xiàn)出較好的字符識別效果。

5.1 支持向量機(jī)原理

支持向量機(jī)(Support Vector Machine, SVM), 是 Vapnik [35] 研究小組在統(tǒng)計學(xué)習(xí)理論基礎(chǔ)上, 于 1995
年針對分類問題提出的最佳分類準(zhǔn)則。 SVM 是一種基于統(tǒng)計學(xué)習(xí)理論的模式識別方法, 主要應(yīng)用于解決分類和回歸問題。
傳統(tǒng)的統(tǒng)計學(xué)理論基于樣本無窮大的統(tǒng)計性質(zhì), SVM 專門針對有限樣本, 算法轉(zhuǎn)化成一個二次型尋優(yōu)問題, 得到的是全局最優(yōu)解。 它具有解的唯一性,
經(jīng)過非線性變化轉(zhuǎn)化到高維特征空間, 其算法與樣本的復(fù)雜度無關(guān), 不依賴輸入空間的維數(shù),得到的最優(yōu)解優(yōu)于傳統(tǒng)的學(xué)習(xí)方法 。 因此迅速的發(fā)展起來,
在手寫字符識別領(lǐng)域取得了巨大的成功。

對于最優(yōu)間隔平面分類問題, 根據(jù)樣本分布的情況分為線性可分與非線性可分進(jìn)行討論。 在線性可分的情況下, 其目標(biāo)就是尋找最優(yōu)間隔超平面, 將樣本準(zhǔn)確的分開。
根據(jù)少量支持向量確定平面, 保證樣本數(shù)據(jù)與超平面距離最大,如圖所示。

最優(yōu)分類面示意圖
計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

5.2 基于SVM的字符識別

數(shù)學(xué)算式作業(yè)中包含印刷體字符和手寫體字符, 將這些字符全部放在一個分類器中會導(dǎo)致分類過于復(fù)雜, 類別過多會使識別速率降低。
因此按照字符的分布位置將分類器分為兩種類型: 印刷體字符分類器和手寫字符分類器。 采取一對一分類的方法對印刷體字符和手寫體字符分別設(shè)計了二分類器,
對于算式中同時包含印刷體和手寫體數(shù)字字符, 選用相應(yīng)的分類器, 會提高識別的準(zhǔn)確性和速率。 如圖所示, 根據(jù)字符在算式中的位置, 選用對應(yīng)的分類器。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

每個分類器只能將一個字符與其他字符分開, 對于手寫字符而言, 其中一類字符樣本的特征向量作為正集(標(biāo)簽對應(yīng)的值為+1), 其余 9
個樣本的特征向量做負(fù)集(標(biāo)簽對應(yīng)的值為-1)。 按照這種形式依次劃分, 將訓(xùn)練集依次進(jìn)行訓(xùn)練, 可得到 10 個二分類器, 測試階段將未知樣本輸入到這 10
個分類器進(jìn)行分類判斷, 決策結(jié)果取相應(yīng)結(jié)果的最大值。 若輸出的值為+1, 則對應(yīng)相應(yīng)類的字符。

網(wǎng)格特征是字符識別中常用的特征提取方法之一, 體現(xiàn)了字符形狀的整體分布。 其中粗網(wǎng)格特征提取的方法是將字符圖像等分成多個網(wǎng)格區(qū)域, 進(jìn)行特征提取。
首先將歸一化的字符樣本圖像, 其中大小為 128 128, 等分成 16 16 個網(wǎng)格, 如下圖所示。
統(tǒng)計每個網(wǎng)格中黑色像素點占整個網(wǎng)格圖像的有效像素比例, 最后將特征值按照網(wǎng)格排列轉(zhuǎn)換為向量形式。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

5.3 SVM算法實現(xiàn)

?


    import numpy as np
    import random
    import matplotlib.pyplot as plt


    '''
    類名稱:dataStruct
    功能:用于存儲一些需要保存或者初始化的數(shù)據(jù)
    '''
    class dataStruct:
        def __init__(self,dataMatIn,labelMatIn,C,toler,eps):
            self.dataMat = dataMatIn                        #樣本數(shù)據(jù)
            self.labelMat = labelMatIn                      #樣本標(biāo)簽
            self.C = C                                      #參數(shù)C
            self.toler = toler                              #容錯率
            self.eps = eps                                  #乘子更新最小比率
            self.m = np.shape(dataMatIn)[0]                 #樣本數(shù)
            self.alphas = np.mat(np.zeros((self.m,1)))      #拉格朗日乘子alphas,shape(m,1),初始化全為0
            self.b = 0                                      #參數(shù)b,初始化為0
            self.eCache = np.mat(np.zeros((self.m,2)))      #誤差緩存,

    '''
    函數(shù)名稱:loadData
    函數(shù)功能:讀取文本文件中的數(shù)據(jù),以樣本數(shù)據(jù)和標(biāo)簽的形式返回
    輸入?yún)?shù):filename       文本文件名
    返回參數(shù):dataMat        樣本數(shù)據(jù)
             labelMat       樣本標(biāo)簽
    '''
    def loadData(filename):
        dataMat = [];labelMat = []
        fr = open(filename)
        for line in fr.readlines():                 #逐行讀取
            lineArr = line.strip().split('\t')      #濾除行首行尾空格,以\t作為分隔符,對這行進(jìn)行分解
            num = np.shape(lineArr)[0]     
            dataMat.append(list(map(float,lineArr[0:num-1])))#這一行的除最后一個被添加為數(shù)據(jù)
            labelMat.append(float(lineArr[num-1]))#這一行的最后一個數(shù)據(jù)被添加為標(biāo)簽
        dataMat = np.mat(dataMat)
        labelMat = np.mat(labelMat).T
        return dataMat,labelMat



    '''
    函數(shù)名稱:takeStep
    函數(shù)功能:給定alpha1和alpha2,執(zhí)行alpha1和alpha2的更新,執(zhí)行b的更新
    輸入?yún)?shù):i1            alpha1的標(biāo)號
              i2            alpha2的標(biāo)號
              dataMat       樣本數(shù)據(jù)
              labelMat      樣本標(biāo)簽
    返回參數(shù):如果i1==i2 or L==H or eta<=0 or alpha更新前后相差太小,返回0
             正常執(zhí)行,返回1
    '''   
    def takeStep(i1,i2,dS):
        #如果選擇了兩個相同的乘子,不滿足線性等式約束條件,因此不做更新
        if(i1 == i2):
            print("i1 == i2")
            return 0
        #從數(shù)據(jù)結(jié)構(gòu)中取得需要用到的數(shù)據(jù)
        alpha1 = dS.alphas[i1,0]
        alpha2 = dS.alphas[i2,0]
        y1 = dS.labelMat[i1]
        y2 = dS.labelMat[i2]
        
        #如果E1以前被計算過,就直接從數(shù)據(jù)結(jié)構(gòu)的cache中讀取它,這樣節(jié)省計算量,#如果沒有歷史記錄,就計算E1
        if(dS.eCache[i1,0] == 1):
            E1 = dS.eCache[i1,1]
        else:
            u1 = (np.multiply(dS.alphas,dS.labelMat)).T * np.dot(dS.dataMat,dS.dataMat[i1,:].T) + dS.b     #計算SVM的輸出值u1
            E1 = float(u1 - y1)    #誤差E1
            #dS.eCache[i1] = [1,E1] #存到cache中
    
        #如果E2以前被計算過,就直接從數(shù)據(jù)結(jié)構(gòu)的cache中讀取它,這樣節(jié)省計算量,#如果沒有歷史記錄,就計算E2
        if(dS.eCache[i2,0] == 1):
            E2 = dS.eCache[i2,1]
        else:
            u2 = (np.multiply(dS.alphas,dS.labelMat)).T * np.dot(dS.dataMat,dS.dataMat[i2,:].T) + dS.b     #計算SVM的輸出值u2
            E2 = float(u2 - y2)    #誤差E2
            #dS.eCache[i2] = [1,E2] #存到cache中        
    
        s = y1*y2
        
        #計算alpha2的上界H和下界L
        if(s==1):       #如果y1==y2
            L = max(0,alpha1+alpha2-dS.C)
            H = min(dS.C,alpha1+alpha2)
        elif(s==-1):    #如果y1!=y2
            L = max(0,alpha2-alpha1)
            H = min(dS.C,dS.C+alpha2-alpha1)
        if(L==H):
            print("L==H")
            return 0
            
        #計算學(xué)習(xí)率eta
        k11 = np.dot(dS.dataMat[i1,::],dS.dataMat[i1,:].T)
        k12 = np.dot(dS.dataMat[i1,::],dS.dataMat[i2,:].T)
        k22 = np.dot(dS.dataMat[i2,::],dS.dataMat[i2,:].T)
        eta = k11 - 2*k12 +k22
        
        if(eta > 0):#正常情況下eta是大于0的,此時計算新的alpha2,新的alpha2標(biāo)記為a2
            a2 = alpha2 + y2*(E1-E2)/eta#這個公式的推導(dǎo),曾經(jīng)花費(fèi)了我很多精力,現(xiàn)在寫出來卻是如此簡潔,數(shù)學(xué)真是個好東西
            #對a2進(jìn)行上下界裁剪
            if(a2 < L):
                a2 = L
            elif(a2 > H):
                a2 = H
        else:#非正常情況下,也有可能出現(xiàn)eta《=0的情況
            print("eta<=0")
            return 0
            '''
            Lobj = 
            Hobj = 
            if(Lobj < Hobj-eps):
                a2 = L
            elif(Lobj > Hobj+eps):
                a2 = H
            else:
                a2 = alpha2
            '''
            
        #如果更新量太小,就不值浪費(fèi)算力繼續(xù)算a1和b,不值得對這三者進(jìn)行更新
        if(abs(a2-alpha2) < dS.eps*(a2+alpha2+dS.eps)):
            print("so small update on alpha2!")
            return 0
            
        #計算新的alpha1,標(biāo)記為a1
        a1 = alpha1 + s*(alpha2 - a2)
        
        #計算b1和b2,并且更新b
        b1 = -E1 + y1*(alpha1 - a1)*np.dot(dS.dataMat[i1,:],dS.dataMat[i1,:].T) + y2*(alpha2 - a2)*np.dot(dS.dataMat[i1,:],dS.dataMat[i2,:].T) + dS.b
        b2 = -E2 + y1*(alpha1 - a1)*np.dot(dS.dataMat[i1,:],dS.dataMat[i2,:].T) + y2*(alpha2 - a2)*np.dot(dS.dataMat[i2,:],dS.dataMat[i2,:].T) + dS.b
        if(a1>0 and a1<dS.C):
            dS.b = b1
        elif(a2>0 and a2<dS.C):
            dS.b = b2
        else:
            dS.b = (b1 + b2) / 2
    
        #用a1和a2更新alpha1和alpha2
        dS.alphas[i1] = a1
        dS.alphas[i2] = a2
        
        #由于本次alpha1、alpha2和b的更新,需要重新計算Ecache,注意Ecache只存儲那些非零的alpha對應(yīng)的誤差
        validAlphasList = np.nonzero(dS.alphas.A)[0]   #所有的非零的alpha標(biāo)號列表
        dS.eCache = np.mat(np.zeros((dS.m,2)))#要把Ecache先清空
        for k in validAlphasList:#遍歷所有的非零alpha
            uk = (np.multiply(dS.alphas,dS.labelMat).T).dot(np.dot(dS.dataMat,dS.dataMat[k,:].T)) + dS.b
            yk = dS.labelMat[k,0]
            Ek = float(uk-yk)
            dS.eCache[k] = [1,Ek]
        print ("updated")
        return 1


    '''
    函數(shù)名稱:examineExample
    函數(shù)功能:給定alpha2,如果alpha2不滿足KKT條件,則再找一個alpha1,對這兩個乘子進(jìn)行一次takeStep
    輸入?yún)?shù):i2            alpha的標(biāo)號
              dataMat       樣本數(shù)據(jù)
              labelMat      樣本標(biāo)簽
    返回參數(shù):如果成功對一對乘子alpha1和alpha2執(zhí)行了一次takeStep,返回1;否則,返回0
    '''
    def examineExample(i2,dS):
        #從數(shù)據(jù)結(jié)構(gòu)中取得需要用到的數(shù)據(jù)
        y2 = dS.labelMat[i2,0]
        alpha2 = dS.alphas[i2,0]
    
        #如果E2以前被計算過,就直接從數(shù)據(jù)結(jié)構(gòu)的cache中讀取它,這樣節(jié)省計算量,#如果沒有歷史記錄,就計算E2
        if(dS.eCache[i2,0] == 1):
            E2 = dS.eCache[i2,1]
        else:
            u2 = (np.multiply(dS.alphas,dS.labelMat)).T * np.dot(dS.dataMat,dS.dataMat[i2,:].T) + dS.b#計算SVM的輸出值u2
            E2 = float(u2 - y2)#誤差E2
            #dS.eCache[i2] = [1,E2]
    
        r2 = E2*y2
        #如果當(dāng)前的alpha2在一定容忍誤差內(nèi)不滿足KKT條件,則需要對其進(jìn)行更新
        if((r2<-dS.toler and alpha2<dS.C) or (r2>dS.toler and alpha2>0)):
            '''
            #隨機(jī)選擇的方法確定另一個乘子alpha1,多執(zhí)行幾次可可以收斂到很好的結(jié)果,就是效率比較低
            i1 = random.randint(0, dS.m-1)
            if(takeStep(i1,i2,dS)):
                return 1
            '''
            #啟發(fā)式的方法確定另一個乘子alpha1
            nonZeroAlphasList = np.nonzero(dS.alphas.A)[0].tolist()#找到所有的非0的alpha
            nonCAlphasList = np.nonzero((dS.alphas-dS.C).A)[0].tolist()#找到所有的非C的alpha
            nonBoundAlphasList = list(set(nonZeroAlphasList)&set(nonCAlphasList))#所有非邊界(既不=0,也不=C)的alpha
            
            #如果非邊界的alpha數(shù)量至少兩個,則在所有的非邊界alpha上找到能夠使\E1-E2\最大的那個E1,對這一對乘子進(jìn)行更新
            if(len(nonBoundAlphasList)  > 1):
                maxE = 0
                maxEindex = 0
                for k in nonBoundAlphasList:
                    if(abs(dS.eCache[k,1]-E2)>maxE):
                        maxE = abs(dS.eCache[k,1]-E2)
                        maxEindex = k
                i1 = maxEindex
                if(takeStep(i1,i2,dS)):
                    return 1
                    
                #如果上面找到的那個i1沒能使alpha和b得到有效更新,則從隨機(jī)開始處遍歷整個非邊界alpha作為i1,逐個對每一對乘子嘗試進(jìn)行更新
                randomStart = random.randint(0,len(nonBoundAlphasList)-1)
                for i1 in range(randomStart,len(nonBoundAlphasList)):
                    if(i1 == i2):continue
                    if(takeStep(i1,i2,dS)):
                        return 1
                for i1 in range(0,randomStart):
                    if(i1 == i2):continue
                    if(takeStep(i1,i2,dS)):
                        return 1


            #如果上面的更新仍然沒有return 1跳出去或者非邊界alpha數(shù)量少于兩個,這種情況只好從隨機(jī)開始的位置開始遍歷整個可能的i1,對每一對嘗試更新 
            randomStart = random.randint(0,dS.m-1)
            for i1 in range(randomStart,dS.m):
                if(i1 == i2):continue
                if(takeStep(i1,i2,dS)):
                    return 1
            for i1 in range(0,randomStart):
                if(i1 == i2):continue
                if(takeStep(i1,i2,dS)):
                    return 1   
            '''
            i1 = random.randint(0,dS.m-1)
            if(takeStep(i1,i2,dS)):
                return 1 
            '''
        #如果實在還更新不了,就回去重新選擇一個alpha2吧,當(dāng)前的alpha2肯定是有毒    
        return 0

    '''
    函數(shù)名稱:SVM_with_SMO
    函數(shù)功能:用SMO寫的SVM的入口函數(shù),里面采用了第一個啟發(fā)式確定alpha2,即在全局遍歷和非邊界遍歷之間來回repeat,直到不再有任何更新
    輸入?yún)?shù):dS            dataStruct類的數(shù)據(jù)
    返回參數(shù):None
    '''
    
    def SVM_with_SMO(dS):
        #初始化控制變量,確保第一次要全局遍歷
        numChanged = 0
        examineAll = 1
    
        #顯然,如果全局遍歷了一次,并且沒有任何更新,此時examineAll和numChanged都會被置零,算法終止
        while(numChanged > 0 or examineAll):
            numChanged = 0
            if(examineAll):
                for i in range(dS.m):
                    numChanged += examineExample(i,dS)
            else:
                for i in range(dS.m):
                    if(dS.alphas[i] == 0 or dS.alphas[i] == dS.C):continue
                    numChanged += examineExample(i,dS)
            if(examineAll == 1):
                examineAll = 0
            elif(numChanged == 0):
                examineAll = 1
    
    '''
    函數(shù)名稱:cal_W
    函數(shù)功能:根據(jù)alpha和y來計算W
    輸入?yún)?shù):dS         dataStruct類的數(shù)據(jù)
    返回參數(shù):W          超平名的法向量W            
    '''
    def cal_W(dS):
        W = np.dot(dS.dataMat.T,np.multiply(dS.labelMat,dS.alphas))
        return W
    
    '''
    函數(shù)名稱:showClassifer
    函數(shù)功能:畫出原始數(shù)據(jù)點、超平面,并標(biāo)出支持向量
    輸入?yún)?shù):dS         dataStruct類的數(shù)據(jù)
              W          超平名的法向量W    
    返回參數(shù):None
    '''    
    def showClassifer(dS,w):
    	#繪制樣本點
        dataMat = dS.dataMat.tolist()
        data_plus = []                                  #正樣本
        data_minus = []                                 #負(fù)樣本
        for i in range(len(dataMat)):
            if dS.labelMat[i,0] > 0:
                data_plus.append(dataMat[i])
            else:
                data_minus.append(dataMat[i])
        data_plus_np = np.array(data_plus)              #轉(zhuǎn)換為numpy矩陣
        data_minus_np = np.array(data_minus)            #轉(zhuǎn)換為numpy矩陣
        plt.scatter(np.transpose(data_plus_np)[0], np.transpose(data_plus_np)[1], s=30, alpha=0.7, c='r')   #正樣本散點圖
        plt.scatter(np.transpose(data_minus_np)[0], np.transpose(data_minus_np)[1], s=30, alpha=0.7,c='g') #負(fù)樣本散點圖
        #繪制直線
        x1 = max(dataMat)[0]
        x2 = min(dataMat)[0]
        a1, a2 = w
        b = float(dS.b)
        a1 = float(a1[0])
        a2 = float(a2[0])
        y1, y2 = (-b- a1*x1)/a2, (-b - a1*x2)/a2
        plt.plot([x1, x2], [y1, y2])
        #找出支持向量點
        for i, alpha in enumerate(dS.alphas):
            if abs(alpha) > 0.000000001:
                x, y = dataMat[i]
                plt.scatter([x], [y], s=150, c='none', alpha=0.7, linewidth=1.5, edgecolor='red')
        plt.xlabel("happy 520 day, 2018.06.13")
        plt.savefig("svm.png")
        plt.show()

    if __name__ == '__main__':
        dataMat,labelMat = loadData("testSet.txt")
        dS = dataStruct(dataMat, labelMat, 0.6, 0.001, 0.01)#初始化數(shù)據(jù)結(jié)構(gòu) dataMatIn, labelMatIn,C,toler,eps
        for i in range(0,1):#只需要執(zhí)行一次,效果就非常不錯
            SVM_with_SMO(dS)
        W = cal_W(dS)
        showClassifer(dS,W.tolist())



?

6 算法測試

輸入圖像

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

預(yù)處理結(jié)果

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

識別結(jié)果

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

7 系統(tǒng)實現(xiàn)

系統(tǒng)主要流程如下

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

對在 PC 軟件平臺通過 MFC 界面中實現(xiàn)各模塊操作, 系統(tǒng)界面如圖所示。

系統(tǒng)界面采用模塊化設(shè)計, 按照界面分布分為圖像顯示模塊、 按鍵功能模塊、 圖像預(yù)處理模塊、 批改結(jié)果輸出四個模塊組成。

主要內(nèi)容包括:

  • 顯示獲取作業(yè)圖像的基本信息;
  • 通過按鍵控制相應(yīng)功能;
  • 顯示預(yù)處理后圖像的效果;輸出識別的字符信息和批改的結(jié)果。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java
圖像顯示模塊, 通過打開攝像頭按鍵, 將攝像頭獲取到的紙張作業(yè)圖像實時信息傳送到計算機(jī)中, 獲取的圖像顯示在界面左側(cè)窗口, 界面運(yùn)行結(jié)果如圖所示。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

按鍵功能模塊, 通過算式提取按鍵, 對紙張中單個算式整體區(qū)域進(jìn)行選框提取, 運(yùn)行結(jié)果如圖所示,
此時算式檢測的結(jié)果在原圖像上用矩形框標(biāo)記,在界面右側(cè)顯示提取到的算式效果。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

圖像處理模塊, 通過檢測識別按鍵完成字符分割和識別, 在界面右側(cè)窗口顯示預(yù)處理后的圖像效果。 批改結(jié)果輸出模塊,
在界面下框中顯示字符的識別結(jié)果以及手寫的計算結(jié)果, 同時在右下角窗口顯示解答正誤, 輸出得到的批改信息。 同時對整個過程運(yùn)行的時間進(jìn)行統(tǒng)計,
最后保存按鍵將錯誤的批改結(jié)果保存, 便于后期修改。 此時系統(tǒng)運(yùn)行界面如圖所示。

計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別,python,java

8 最后

?? 更多資料, 項目分享:

https://gitee.com/dancheng-senior/postgraduate

到了這里,關(guān)于計算機(jī)競賽 機(jī)器視覺的試卷批改系統(tǒng) - opencv python 視覺識別的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 機(jī)器視覺 opencv 深度學(xué)習(xí) 駕駛?cè)四樒跈z測系統(tǒng) -python 計算機(jī)競賽

    機(jī)器視覺 opencv 深度學(xué)習(xí) 駕駛?cè)四樒跈z測系統(tǒng) -python 計算機(jī)競賽

    ?? 優(yōu)質(zhì)競賽項目系列,今天要分享的是 ?? 機(jī)器視覺 opencv 深度學(xué)習(xí) 駕駛?cè)四樒跈z測系統(tǒng) 該項目較為新穎,適合作為競賽課題方向,學(xué)長非常推薦! ??學(xué)長這里給一個題目綜合評分(每項滿分5分) 難度系數(shù):3分 工作量:3分 創(chuàng)新點:4分 ?? 更多資料, 項目分享: https:/

    2024年02月05日
    瀏覽(97)
  • 計算機(jī)競賽 車道線檢測(自動駕駛 機(jī)器視覺)

    計算機(jī)競賽 車道線檢測(自動駕駛 機(jī)器視覺)

    無人駕駛技術(shù)是機(jī)器學(xué)習(xí)為主的一門前沿領(lǐng)域,在無人駕駛領(lǐng)域中機(jī)器學(xué)習(xí)的各種算法隨處可見,今天學(xué)長給大家介紹無人駕駛技術(shù)中的車道線檢測。 在無人駕駛領(lǐng)域每一個任務(wù)都是相當(dāng)復(fù)雜,看上去無從下手。那么面對這樣極其復(fù)雜問題,我們解決問題方式從先嘗試簡化問

    2024年02月08日
    瀏覽(27)
  • 基于機(jī)器視覺的車道線檢測 計算機(jī)競賽

    基于機(jī)器視覺的車道線檢測 計算機(jī)競賽

    ?? 優(yōu)質(zhì)競賽項目系列,今天要分享的是 基于深度學(xué)習(xí)的視頻多目標(biāo)跟蹤實現(xiàn) 該項目較為新穎,適合作為競賽課題方向,學(xué)長非常推薦! ?? 更多資料, 項目分享: https://gitee.com/dancheng-senior/postgraduate 理解車道檢測的概念 那么什么是車道檢測?以下是百度百科對車道的定義:

    2024年02月08日
    瀏覽(29)
  • 計算機(jī)競賽 - 基于機(jī)器視覺的圖像拼接算法

    計算機(jī)競賽 - 基于機(jī)器視覺的圖像拼接算法

    圖像拼接在實際的應(yīng)用場景很廣,比如無人機(jī)航拍,遙感圖像等等,圖像拼接是進(jìn)一步做圖像理解基礎(chǔ)步驟,拼接效果的好壞直接影響接下來的工作,所以一個好的圖像拼接算法非常重要。 再舉一個身邊的例子吧,你用你的手機(jī)對某一場景拍照,但是你沒有辦法一次將所有你

    2024年02月13日
    瀏覽(26)
  • 計算機(jī)競賽 機(jī)器視覺目標(biāo)檢測 - opencv 深度學(xué)習(xí)

    計算機(jī)競賽 機(jī)器視覺目標(biāo)檢測 - opencv 深度學(xué)習(xí)

    ?? 優(yōu)質(zhì)競賽項目系列,今天要分享的是 ?? 機(jī)器視覺 opencv 深度學(xué)習(xí)目標(biāo)檢測 該項目較為新穎,適合作為競賽課題方向,學(xué)長非常推薦! ??學(xué)長這里給一個題目綜合評分(每項滿分5分) 難度系數(shù):3分 工作量:3分 創(chuàng)新點:4分 ?? 更多資料, 項目分享: https://gitee.com/dancheng

    2024年02月07日
    瀏覽(101)
  • 計算機(jī)競賽 基于機(jī)器視覺的行人口罩佩戴檢測

    計算機(jī)競賽 基于機(jī)器視覺的行人口罩佩戴檢測

    簡介 2020新冠爆發(fā)以來,疫情牽動著全國人民的心,一線醫(yī)護(hù)工作者在最前線抗擊疫情的同時,我們也可以看到很多科技行業(yè)和人工智能領(lǐng)域的從業(yè)者,也在貢獻(xiàn)著他們的力量。近些天來,曠視、商湯、???、百度都多家科技公司研發(fā)出了帶有AI人臉檢測算法的紅外測溫、口罩

    2024年02月10日
    瀏覽(19)
  • 計算機(jī)競賽 基于機(jī)器視覺的手勢檢測和識別算法

    計算機(jī)競賽 基于機(jī)器視覺的手勢檢測和識別算法

    ?? 優(yōu)質(zhì)競賽項目系列,今天要分享的是 基于深度學(xué)習(xí)的手勢檢測與識別算法 該項目較為新穎,適合作為競賽課題方向,學(xué)長非常推薦! ?? 更多資料, 項目分享: https://gitee.com/dancheng-senior/postgraduate 廢話不多說,先看看學(xué)長實現(xiàn)的效果吧 主流的手勢分割方法主要分為靜態(tài)手

    2024年02月11日
    瀏覽(30)
  • 計算機(jī)競賽 基于機(jī)器視覺的停車位識別檢測

    計算機(jī)競賽 基于機(jī)器視覺的停車位識別檢測

    簡介 你是不是經(jīng)常在停車場周圍轉(zhuǎn)來轉(zhuǎn)去尋找停車位。如果你的車輛能準(zhǔn)確地告訴你最近的停車位在哪里,那是不是很爽?事實證明,基于深度學(xué)習(xí)和OpenCV解決這個問題相對容易,只需獲取停車場的實時視頻即可。 該項目較為新穎,適合作為競賽課題方向,學(xué)長非常推薦!

    2024年02月11日
    瀏覽(39)
  • python 機(jī)器視覺 車牌識別 - opencv 深度學(xué)習(xí) 機(jī)器學(xué)習(xí) 計算機(jī)競賽

    python 機(jī)器視覺 車牌識別 - opencv 深度學(xué)習(xí) 機(jī)器學(xué)習(xí) 計算機(jī)競賽

    ?? 優(yōu)質(zhì)競賽項目系列,今天要分享的是 ?? 基于python 機(jī)器視覺 的車牌識別系統(tǒng) ??學(xué)長這里給一個題目綜合評分(每項滿分5分) 難度系數(shù):3分 工作量:3分 創(chuàng)新點:3分 ?? 更多資料, 項目分享: https://gitee.com/dancheng-senior/postgraduate 車牌識別其實是個經(jīng)典的機(jī)器視覺任務(wù)了,

    2024年02月06日
    瀏覽(27)
  • 計算機(jī)競賽 python 機(jī)器視覺 車牌識別 - opencv 深度學(xué)習(xí) 機(jī)器學(xué)習(xí)

    計算機(jī)競賽 python 機(jī)器視覺 車牌識別 - opencv 深度學(xué)習(xí) 機(jī)器學(xué)習(xí)

    ?? 優(yōu)質(zhì)競賽項目系列,今天要分享的是 ?? 基于python 機(jī)器視覺 的車牌識別系統(tǒng) ??學(xué)長這里給一個題目綜合評分(每項滿分5分) 難度系數(shù):3分 工作量:3分 創(chuàng)新點:3分 ?? 更多資料, 項目分享: https://gitee.com/dancheng-senior/postgraduate 車牌識別其實是個經(jīng)典的機(jī)器視覺任務(wù)了,

    2024年02月12日
    瀏覽(34)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包