opencv——实战(一)

准备

  1. python环境
  2. pycharm编译器
  3. opencv库安装

实战

  1. 测试用图:
    opencv——实战(一)_第1张图片
    opencv——实战(一)_第2张图片
  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. 注意问题:
  • 二值化也可以用系统自动设置阈值
  • 二值化的图像注意分辨黑白,防止后续操作出问题

你可能感兴趣的:(python)