openCV实践项目之银行卡卡号识别功能

  

OpenCV实践项目之银行卡卡号识别功能

项目简介

本项目利用OpenCV实现银行卡卡号的自动识别功能,能够对输入的照片或摄像头视频进行实时的卡号识别,并且将识别结果呈现在界面上,方便用户进行后续操作。

项目流程

以下是本项目的主要流程:

  1. 图像预处理
  2. 字符分割
  3. 字符识别
  4. 结果呈现

下面将对每个流程进行详细的说明。

图像预处理

图像预处理是整个卡号识别过程中的关键步骤。主要任务是对输入的银行卡图像进行处理,以便后续的字符分割和字符识别操作可以顺利进行。

具体实现方式通常包括以下几个步骤:

  1. 转为灰度图像
  2. 图像二值化
  3. 去除噪声
  4. 边缘检测

示例代码如下:

import cv2

# 加载输入图像
image = cv2.imread("input.jpg")

# 转为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 图像二值化
threshold = 100
ret, binary = cv2.threshold(gray, threshold, 255, cv2.THRESH_BINARY)

# 去除噪声
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
morphology = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)

# 边缘检测
canny = cv2.Canny(morphology, 40, 150)

# 显示预处理后的图像
cv2.imshow("Preprocessed", canny)
cv2.waitKey(0)
cv2.destroyAllWindows()

字符分割

字符分割是将预处理后的银行卡图像中的字符分离出来的过程。由于每个字符之间的间隔大小不同,而且银行卡中的字符也存在不同的字体、大小等差异,因此字符分割是整个卡号识别过程中最为困难的一个环节。

传统的字符分割方法通常包括以下几个步骤:

  1. 水平投影
  2. 垂直投影
  3. 按列切割
  4. 去除多余字符

示例代码如下:

import cv2

# 加载预处理后的图像
image = cv2.imread("preprocessed.jpg")

# 水平投影
horizontal = cv2.reduce(image, 1, cv2.REDUCE_AVG)
horizontal = cv2.threshold(horizontal, 250, 255, cv2.THRESH_BINARY)[1]

# 垂直投影
vertical = cv2.reduce(image, 0, cv2.REDUCE_AVG)
vertical = cv2.threshold(vertical, 250, 255, cv2.THRESH_BINARY)[1]

# 按列切割
width = len(image[0])
height = len(image)
split_lines = []
for i in range(width):
    if vertical[0, i] == 0:
        continue
    start = max(0, i-1)
    end = min(width-1, i+1)
    for j in range(1, height):
        if vertical[j, i] != 0 and vertical[j-1, i] == 0:
            split_lines.append((start, i, end, j-1))
            break
        if j == height - 1 and vertical[j, i] != 0:
            split_lines.append((start, i, end, j))
            break

# 去除多余字符
split_images = []
for line in split_lines:
    if line[3] - line[1] > 10 and line[2] - line[0] > 3:
        roi = image[line[1]:line[3], line[0]:line[2]]
        split_images.append(roi)

# 显示分割后的字符图像
for i, split_image in enumerate(split_images):
    cv2.imshow(f"Split {i}", split_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

字符识别

字符识别是整个卡号识别过程中的最后一步,任务是将分离出来的字符进行识别,输出卡号字符串。

常用的字符识别方法包括基于传统图像处理方法的模板匹配、基于机器学习的卷积神经网络等方法。本项目中使用了一种先进的字符识别算法——深度学习中的卷积神经网络(Convolutional Neural Networks,简称CNN)。

示例代码如下:

import cv2
import numpy as np
from tensorflow.keras.models import load_model

# 加载分割后的字符图像
split_images = []
for i in range(16):
    split_image = cv2.imread(f"split_{i}.jpg")
    split_image = cv2.cvtColor(split_image, cv2.COLOR_BGR2GRAY)
    split_image = split_image.astype(np.float32) / 255.
    split_images.append(split_image)

# 加载字符识别模型
model = load_model("model.h5")

# 对每个字符进行识别
card_number = ""
for split_image in split_images:
    preprocessed = cv2.resize(split_image, (32, 32))
    preprocessed = preprocessed.reshape((1, 32, 32, 1))
    prediction = model.predict(preprocessed, batch_size=1)
    card_number += str(np.argmax(prediction))

# 显示识别结果
print("Card number:", card_number)

结果呈现

最后一步是将识别出来的卡号字符串呈现在界面上,方便用户进行后续操作。

示例代码如下:

import cv2
from PIL import ImageFont, ImageDraw, Image

# 加载原始图像
image = cv2.imread("input.jpg")

# 绘制卡号
font = ImageFont.truetype("arial.ttf", 40)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = Image.fromarray(image)
draw = ImageDraw.Draw(image)
draw.text((50, 50), card_number, fill=(255, 0, 0), font=font)

# 显示最终结果
result = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
cv2.imshow("Result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

以上代码片段只是本项目的一个简单示例,实际上还需要进行一些调试和优化。在实际实现过程中,还需要考虑更复杂的情况,例如图片倾斜、模糊等问题的处理。

相关文章