使用python3+opencv3實現的識別答題卡的例子(01)

2021-01-15 我是攻城師

由於工作需要,最近在研究關於如何通過程序識別答題卡的客觀題的答案,之前雖然接觸過python,但對於計算機視覺這一塊卻完全是一個陌生的領域,經過各種調研,發現網上大多數的例子都是採用的OpenCV這個開源庫來做的,OpenCV是計算機視覺領域的處理的一個非常優秀的開源庫,原生由C++編寫,也提供了各個主流程式語言的接口支持,這裡選擇python完全是因為python在計算機科學領域有著壓倒性的優勢和生態系統,所以使用它毫無疑問,最快上手的方式莫過於直接閱讀網上已有的例子或者輪子了,通過閱讀源碼以問題驅動的方式來學習和研究某一項技術是比較高效的一種方式。

例子01是參考:pyimagesearch網站上一個識別例子,參考作者的源碼,先在本地運行成功之後,然後加上自己的理解,給大多數核心代碼加上了詳細的中文注釋,並在每一個關鍵階段都會彈出具體的窗體展示識別流程,這樣便於大家更能詳細的看到核心部分的細節,感興趣的同學,可以自己在再嘗試加一些更細部分的debug彈窗。

例子01的在我本地PyCharm運行後一些截圖:

(1)原圖

(2)灰度+高斯模糊後的圖

(3)使用邊緣檢測後的圖

(4)透視變換後提取指定答題區域的灰度圖

(5)使用ostu的二值化後的圖

(6)識別答案成功後的圖

(7)標記出做對和做錯的圖並計算得分

代碼如下:

# -*- coding:utf-8 -*-

from imutils.perspective import four_point_transform

from imutils import contours

import numpy as np

import imutils

import cv2 as cv

ANSWER_KEY_SCORE = {0: 1, 1: 4, 2: 0, 3: 3, 4: 1}

ANSWER_KEY = {0: "A", 1: "B", 2: "C", 3: "D", 4: "E"}

# 加載一個圖片到opencv中

img = cv.imread('E:\\tmp\\t1.png')

cv.imshow("orgin",img)

#轉化成灰度圖片

gray=cv.cvtColor(img,cv.COLOR_BGR2GRAY)

cv.imshow("gray",gray)

gaussian_bulr = cv.GaussianBlur(gray, (5, 5), 0)  # 高斯模糊

cv.imshow("gaussian",gaussian_bulr)

edged=cv.Canny(gaussian_bulr,75,200) # 邊緣檢測,灰度值小於2參這個值的會被丟棄,大於3參這個值會被當成邊緣,在中間的部分,自動檢測

cv.imshow("edged",edged)

# 尋找輪廓

image, cts, hierarchy = cv.findContours( edged.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

# 給輪廓加標記,便於我們在原圖裡面觀察,注意必須是原圖才能畫出紅色,灰度圖是沒有顏色的

# cv.drawContours(img, cts, -1, (0,0,255), 3)

# 按面積大小對所有的輪廓排序

list=sorted(cts,key=cv.contourArea,reverse=True)

print("尋找輪廓的個數:",len(cts))

cv.imshow("draw_contours",img)

# 正確題的個數

correct_count=0

for c in list:

   # 周長,第1個參數是輪廓,第二個參數代表是否是閉環的圖形

   peri=0.01*cv.arcLength(c,True)

   # 獲取多邊形的所有定點,如果是四個定點,就代表是矩形

   approx=cv.approxPolyDP(c,peri,True)

   # 列印定點個數

   print("頂點個數:",len(approx))

   if len(approx)==4: #矩形

       # 透視變換提取原圖內容部分

       ox_sheet = four_point_transform(img, approx.reshape(4, 2))

       # 透視變換提取灰度圖內容部分

       tx_sheet = four_point_transform(gray, approx.reshape(4, 2))

       cv.imshow("ox", ox_sheet)

       cv.imshow("tx", tx_sheet)

       # 使用ostu二值化算法對灰度圖做一個二值化處理

       ret,thresh2 = cv.threshold(tx_sheet, 0, 255,cv.THRESH_BINARY_INV | cv.THRESH_OTSU)

       cv.imshow("ostu", thresh2)

       # 繼續尋找輪廓

       r_image, r_cnt, r_hierarchy = cv.findContours(thresh2.copy(), cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

       print("找到輪廓個數:",len(r_cnt))

       # 使用紅色標記所有的輪廓

       # cv.drawContours(ox_sheet,r_cnt,-1,(0,0,255),2)

       # 把所有找到的輪廓,給標記出來

       questionCnts = []

       for cxx in r_cnt:

           # 通過矩形,標記每一個指定的輪廓

           x, y, w, h = cv.boundingRect(cxx)

           ar = w / float(h)

           if w >= 20 and h >= 20 and ar >= 0.9 and ar <= 1.1:

               # 使用紅色標記,滿足指定條件的圖形

               # cv.rectangle(ox_sheet, (x, y), (x + w, y + h), (0, 0, 255), 2)

               # 把每個選項,保存下來

               questionCnts.append(cxx)

       cv.imshow("ox_1", ox_sheet)

       # 按坐標從上到下排序

       questionCnts = contours.sort_contours(questionCnts, method="top-to-bottom")[0]

       # 使用np函數,按5個元素,生成一個集合

       for (q, i) in enumerate(np.arange(0, len(questionCnts), 5)):

           # 獲取按從左到右的排序後的5個元素

           cnts = contours.sort_contours(questionCnts[i:i + 5])[0]

           bubble_rows=[]

           # 遍歷每一個選項

           for (j, c) in enumerate(cnts):

               # 生成一個大小與透視圖一樣的全黑背景圖布

               mask = np.zeros(tx_sheet.shape, dtype="uint8")

               # 將指定的輪廓+白色的填充寫到畫板上,255代表亮度值,亮度=255的時候,顏色是白色,等於0的時候是黑色

               cv.drawContours(mask, [c], -1, 255, -1)

               # 做兩個圖片做位運算,把每個選項獨自顯示到畫布上,為了統計非0像素值使用,這部分像素最大的其實就是答案

               mask = cv.bitwise_and(thresh2, thresh2, mask=mask)

               # cv.imshow("c" + str(i), mask)

               # 獲取每個答案的像素值

               total = cv.countNonZero(mask)

               # 存到一個數組裡面,tuple裡面的參數分別是,像素大小和答案的序號值

               # print(total,j)

               bubble_rows.append((total,j))

           bubble_rows=sorted(bubble_rows,key=lambda x: x[0],reverse=True)

           # 選擇的答案序號

           choice_num=bubble_rows[0][1]

           print("答案:{} 數據: {}".format(ANSWER_KEY.get(choice_num),bubble_rows))

           fill_color=None

           # 如果做對就加1

           if ANSWER_KEY_SCORE.get(q) == choice_num:

               fill_color = (0, 255, 0)   #正確 綠色

               correct_count = correct_count+1

           else:

               fill_color = (0, 0, 255)   #錯誤 紅色

           cv.drawContours(ox_sheet, cnts[choice_num], -1, fill_color, 2)

       cv.imshow("answer_flagged", ox_sheet)

       text1 = "total: " + str(len(ANSWER_KEY)) + ""

       text2 = "right: " + str(correct_count)

       text3 = "score: " + str(correct_count*1.0/len(ANSWER_KEY)*100)+""

       font = cv.FONT_HERSHEY_SIMPLEX

       cv.putText(ox_sheet, text1 + "  " + text2+"  "+text3, (10, 30), font, 0.5, (0, 0, 255), 2)

       cv.imshow("score", ox_sheet)

       break

cv.waitKey(0)

源碼已經上傳我的github上,歡迎大家fork學習.

https://github.com/qindongliang/answer_sheet_scan


相關焦點

  • python識別答題卡
    本期我們想要利用opencv識別答題卡。在上一次我們完成了圖形形狀的識別之後,我就一直在想,在已經獲取到指定區域的輪廓和位置之後,是否可以通過對不同區域的劃分,賦予不同的意義?在思考中我發現機器識別答題卡似乎就是生活中最貼近這一設想的實際應用。讀卡機會檢測答題區域,在精確到每一個選項之後,再判斷該選項是否被填塗。如果被填塗了,提取被填塗區域的信息,即屬於哪個選項。
  • mac使用python識別圖形驗證碼!
    在網上查了很多版本的圖形驗證碼識別,目前看到最多的兩個模塊是pytesseract和tesserocr,但是因為我這裡安裝tesserocr的時候各種出錯,所以最終我鎖定了使用pytesseract。那麼接下來,就記錄下安裝以及使用過程。這裡的系統環境是mac os 10.14.
  • 使用Python和Tesseract來識別圖形驗證碼
    很多時候驗證碼明明很簡單(對於非網際網路企業,或者企業內網中的應用來說特別如此),但因為沒有趁手的識別庫,也只能苦哈哈地進行人肉識別,或者無奈地放棄任務。在這裡,我分享一下自己使用Python和開源的tesseract OCR引擎做驗證碼識別的經驗,並提供相關的原始碼和示例供大家借鑑。
  • Python驗證碼識別:利用pytesser識別簡單圖形驗證碼
    三、一般思路驗證碼識別的一般思路為:1、圖片降噪2、圖片切割3、圖像文本輸出3.1 圖片降噪所謂降噪就是把不需要的信息通通去除,比如背景,幹擾線,幹擾像素等等,只剩下需要識別的文字,讓圖片變成2進位點陣最好。
  • python人工智慧-圖像識別
    我這裡使用的是python3.6,PIL不支持python3所以使用如下命令pip install pytesseractpip install pillow如果是python2,則在命令行執行如下命令:pip install pytesseractpip install PIL這時候我們去運行上面的代碼會發現如下錯誤
  • Python實現識別圖片中的所有人臉並顯示出來
    使用Python3實現識別圖片中的所有人臉並顯示出來,代碼如下:
  • 用python識別驗證碼
    今天,我們就簡單的說下,怎麼用python來處理驗證碼。(注意:我所有的python相關的文章用的都是python3。)準備工作1、tesseract-ocr軟體Tesseract的OCR引擎最先由HP實驗室於1985年開始研發,至1995年時已經成為OCR業內最準確的三款識別引擎之一。然而,HP不久便決定放棄OCR業務,Tesseract也從此塵封。
  • 223個Python小例子(1-60)
    能識別或可執行的代碼,也可以將文字讀成字符串再編譯。python五類參數:位置參數,關鍵字參數,默認參數,可變位置或關鍵字參數的使用。_x # 使用property類創建 property 屬性 x = property(getx, setx, delx, "I'm the 'x' property.")使用python裝飾器,實現與上完全一樣的效果代碼:class C: def __init__(self): self.
  • Python視頻教程網課編程零基礎入門數據分析網絡爬蟲全套Python...
    因篇幅有限,以下展示的只是課程裡部分內容如對python課程有更多疑問 請諮詢客服 1零基礎入門全能班 01 –python簡介 02 第一個程序 03-python執行方式和pycharm設置 04-程序的注釋和算術運算符 05 程序執行原理 06變量的使用以及類型 07
  • Python語言中使用pyqtgraph庫實現數據可視化
    儘管該庫完全用python編寫,但內部由於使用了高速計算的numpy信號處理庫以及Qt的GraphicsView框架,因此,它在大數據量的數字處理和快速顯示方面有著巨大的優勢,它適合於需要快速繪圖更新、視頻或實時交互性的操作場合。另外,它不僅為各種數據提供了快速可交互式的圖形顯示,同時也提供了用於快速開發應用程式的各種小工具,如屬性樹、流程圖等小部件。下面通過例子說明該庫的使用方法。
  • python|圖像識別
    影響力之大和最吸引人的技術就是圖像識別,圖像識別技術是人工智慧的一個重要領域,它是指利用計算機對圖像進行處理、分析和理解,以識別各種不同模式的目標和對象的技術。今天以女神宋慧喬的兩張不同照片為例,利用python識別其相似度,從而判定是否是同一人,同時讓我們對圖像識別有個初步的了解,什麼?照片可以換蒼老師和波老師嗎?我懷疑你們在開車,可是我沒有證據!
  • Python 三十大實踐、建議和技巧
    1、使用 python 3由於官方從2020年1月1日起就停止了對python2.7的更新支持,因此本教程的大部分例子都只能在python 3環境下運行。如果你仍然在使用2.7版本,請先升級到python 3。2、檢查並使用滿足需求的最小python版本你可以在代碼中檢查Python 版本,以確保你的代碼使用者沒有使用不兼容的版本運行腳本。
  • 驗證碼識別實例,python簡單圖像處理和實現
    問題來源某系統門戶登陸界面如下:現在我們要實現自動的驗證碼識別。圖像特徵首先,我們仔細觀察下這個驗證碼圖像,可以發現一些固定特徵:1、驗證碼中的字符數始終為6,並且是灰度圖像。2、字符間的間隔看起來每次都一樣。3、 每個字符都是完全定義的。
  • Python語言中使用array模塊實現動態數組的操作
    背景對於動態數組諸如創建、插入、刪除、查詢大小等操作,在C/C++語言中,可以使用標準庫中的vector類實現,而在python語言中,也同樣提供了內置的array模塊實現類似的功能。下面通過例子講解array模塊的常用操作。動態數組的創建創建方式為:array.array(typecode[, initializer]),第1個參數typecode定義了數組元素的類型,第2個可選參數給出了數組中的初始值。如下面的代碼創建了一個int型的包含3個元素的數組x,其初始值為分別為1、2、3。
  • Pytest丨如何使用全功能的Python測試框架?小白必看
    pytest斷言前面說到pytest的斷言比較強大,它直接可以使用python自帶的斷言內容,當然不止而已,pytest還有一個重要的功能是可以重寫assert關鍵字,pytest會截斷對python中自帶的assert的調用然後替換成自己定位的assert,從而可以獲取更多的錯誤信息,讓我們知道具體哪裡出現了問題。編寫一個加法進行通過斷言驗證。
  • 利用Python來識別並提取圖片中文字
    文字識別是利用計算機自動識別字符的技術,是模式識別應用的一個重要領域。文字識別一般包括文字信息的採集、信息的分析與處理、信息的分類判別等幾個部分。隨著我國信息化建設的全面開展,OCR文字識別技術誕生20餘年來,經歷從實驗室技術到產品的轉變,已經進入行業應用開發的成熟階段。相比發達國家的廣泛應用情況,OCR文字識別技術在國內各行各業的應用還有著廣闊的空間。隨著國家信息化建設進入內容建設階段,為OCR文字識別技術開創了一個全新的行業應用局面。文通,雲脈技術、漢王等中國文字識別的領軍企業將會更加深入到信息化建設的各個領域。
  • 基於python+OpenCV模塊的人臉識別定位技術
    本文將基於OpenCV模塊,在windows作業系統上,利用python語言,進行人臉識別技術的研究。當然OpenCV的應用領域很廣,除了人臉識別之外,它還支持圖像分割、動作識別、視頻處理等技術。首先看一下實現的效果:OpenCV模塊的下載與安裝OpenCV模塊下載安裝很簡單。
  • Python 實現色情圖片識別
    不管你是出於什麼目的點進來的,首先你要知道,這是一個正經的教程……╭(╯^╰)╮今天要介紹的項目是用 Python 製作一個鑑黃程序,它可以識別一張圖片是否為色情圖片
  • Python2 已終結,入手Python 3,你需要這30個技巧
    這份教程的很多例子都是只支持 Python 3 的,如果你還在用 Python 2.1,那也是時候與時俱進了。2. 檢查所需的最低 Python 版本你可以在代碼中先檢查一下你的 Python 版本,以免當前用戶的 Python 版本與你的腳本不適配。實現的代碼很簡單:3.
  • Agora新增支持Python:視頻通話中也可做圖像識別了
    Python 擁有很活躍的社區和豐富的第三方庫,Web 框架、爬蟲框架、數據分析框架、機器學習框架等,開發者無需重複造輪子,可以用 Python 進行 Web 編程、網絡編程,開發多媒體應用,進行數據分析,或實現圖像識別等應用。其中圖像識別是最熱門的應用場景之一,也是與實時音視頻契合度最高的應用場景之一。