opencv——實戰(一)

準備

  1. python環境
  2. pycharm編譯器
  3. opencv庫安裝

實戰

  1. 測試用圖:
    在這裏插入圖片描述
    在這裏插入圖片描述
  2. 代碼實現
import cv2 as cv
import numpy as np


card = cv.imread("D:/pics/card.png")
num = cv.imread("D:/pics/num.png")


# 命名窗口並打開圖像
def show_image(win_name, image_src):
    cv.namedWindow(win_name, cv.WINDOW_AUTOSIZE)  # 命名窗口
    cv.imshow(win_name, image_src)  # 顯示窗口


# 字模預處理
def num_preInit():
    show_image("num", num)

    # 轉換爲灰度圖,並展示
    numGray = cv.cvtColor(num, cv.COLOR_BGR2GRAY)

    # 二值化,10爲閾值,THRESH_BINARY_INV:反轉二值
    ret, num2Value = cv.threshold(numGray, 10, 255, cv.THRESH_BINARY_INV)

    # 對字模輪廓檢測:cv.RETR_EXTERNAL只檢測外輪廓
    contours, hierarchy = cv.findContours(num2Value, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
    cv.drawContours(num, contours, -1, (0, 0, 255), 3)

    # 挖出各個字模
    single_num = {}
    minBox = [cv.boundingRect(c) for c in contours] # 取最小外接矩形
    nsize =  len(minBox)
    for i in range(nsize):
        x, y, w, h = minBox[nsize-i-1]
        roi = num2Value[y:y + h, x:x + w]
        roi = cv.resize(roi,(57,88))
        single_num[i] = roi

    return single_num


# 卡號預處理
def card_preInit():
    show_image("card", card)

    rectKernel = cv.getStructuringElement(cv.MORPH_RECT, (7, 7))

    # 轉化爲灰度圖
    cardGray = cv.cvtColor(card, cv.COLOR_BGR2GRAY)

    # 頂帽操作,突出明亮地區
    tophat = cv.morphologyEx(cardGray, cv.MORPH_TOPHAT, rectKernel)
    tophat = cv.dilate(tophat, rectKernel, iterations=3) # 膨脹
    tophat = cv.erode(tophat, rectKernel, iterations=2) # 腐蝕

    # 二值化
    ret, card2Value = cv.threshold(tophat, 10, 255, cv.THRESH_BINARY_INV)
    contours, hierarchy = cv.findContours(card2Value, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE) #尋找輪廓

    # 找到卡號數字組
    count = 0
    nums_rect= {}
    minBox = [cv.boundingRect(c) for c in contours]
    nsize =  len(minBox)
    for i in range(nsize):
        xi, yi, wi, hi = minBox[i]
        for j in range(nsize):
            xj, yj, wj, hj = minBox[j]
            if abs(yi-yj)<=3:
                nums_rect[count] = minBox[j]
                count = count + 1
        if count>=3:
            break
        else:
            count = 0
            nums_rect.clear()

    # 對數字組進行排序
    temp = {}
    for i in range(len(nums_rect)):
        x, y, w, h = nums_rect[i]
        for j in range(len(nums_rect)):
            x2, y2, w2, h2 = nums_rect[j]
            if x2 > x:
                temp[0] = nums_rect[j]
                nums_rect[j] = nums_rect[i]
                nums_rect[i] = temp[0]

    # 挖取卡號
    nums_img = {}
    for i in range(len(nums_rect)):
        x, y, w, h = nums_rect[i]
        nums_img[i] = card[y:y + h, x:x + w]

    # 挖出各個卡號
    card_num = []
    card_single_num = {}
    count = 0
    for i in range(len(nums_img)):
        nums_img_gray = cv.cvtColor(nums_img[i], cv.COLOR_BGR2GRAY)
        ret, tooValue = cv.threshold(nums_img_gray, 0, 255, cv.THRESH_OTSU)
        contours, hierarchy = cv.findContours(tooValue, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)

        minBox = [cv.boundingRect(c) for c in contours]
        nsize =  len(minBox)
        for j in range(nsize):
            x, y, w, h = minBox[nsize-j-1]
            if j == 0:
                nw = w
            if abs(w-nw)>10 :
                continue
            roi = tooValue[y:y + h, x:x + w]
            roi = cv.resize(roi, (57, 88))
            card_single_num[count] = roi
            # show_image(str(count), roi)
            count = count + 1

    card_num.append(card_single_num)
    return card_num


# 模板匹配
def card_matchTemplate(mynums,mycard):
    card_nums = []
    scores = []
    for i in range(16):
        for j in range(10):
            result = cv.matchTemplate(mycard[0][i], mynums[j], cv.TM_CCOEFF)
            (_, score, _, _) = cv.minMaxLoc(result)
            scores.append(score)
        the_num = str((np.argmax(scores)))
        card_nums.append(the_num)
        scores.clear()

    return card_nums

def main():
    print("-------------- read_card demo----------------")

    mynums = num_preInit()
    mycard = card_preInit()

    the_nums = card_matchTemplate(mynums,mycard)

    print(the_nums)

    cv.waitKey(0)
    cv.destroyAllWindows()

main()
  1. 注意問題:
  • 二值化也可以用系統自動設置閾值
  • 二值化的圖像注意分辨黑白,防止後續操作出問題
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章