一、opencv+python银行卡号的分割
1.函数
opencv+python的银行卡号的分割。我们得先将图片进行高斯模糊,转换成灰路图像,再将灰路图像二值化,再继续将图片进行膨胀和腐蚀等操作,最后进行垂直投影。这样我们就可以得到分割之后的银行卡号了。
代码如下(函数):
import cv2
import numpy as np
def image_process(file_path):
img = cv2.imread(file_path, 0)
blur = cv2.GaussianBlur(img, (3, 3), 0) #高斯模糊
ret, binary = cv2.threshold(blur, 50, 255, cv2.THRESH_BINARY) #二值化
kernel = np.ones((1, 50), np.uint8)
erosion = cv2.erode(binary, kernel) # 膨胀
dilation = cv2.dilate(erosion, kernel) # 腐蚀
contours, hierarchy = cv2.findContours(dilation, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
sp = dilation.shape
x, y, w, h = 0, 0, 0, 0
for i in range(0, len(contours)):
x, y, w, h = cv2.boundingRect(contours[i])
if h > sp[0]*0.05 and w > sp[1]*0.5 and y > sp[0]*0.2 and y < sp[0]*0.8 and w/h > 5:
img = binary[y:y + h, x:x + w]
break
return num_split(img)
def num_split(img):
height, width = img.shape
v = [0] * width
z = [0] * height
a = 0
# 垂直投影:统计并存储每一列的黑点数
for x in range(0, width):
for y in range(0, height):
if img[y, x] == 255:
continue
else:
a = a + 1
v[x] = a
a = 0
# 创建空白图片,绘制垂直投影图
l = len(v)
emptyImage = np.full((height, width), 255, dtype=np.uint8)
for x in range(0, width):
for y in range(0, v[x]):
emptyImage[y, x] = 0
#分割字符
Position = []
Wstart = 0
Wend = 0
W_Start = 0
W_End = 0
v[0], v[l-1] = 0, 0
for j in range(l):
if v[j] > 0 and Wstart == 0:
W_Start = j
Wstart = 1
Wend = 0
if v[j] <= 0 and Wstart == 1:
W_End = j
Wstart = 0
Wend = 1
if Wend == 1:
Position.append([W_Start, 0, W_End, height])
Wend = 0
data = []
for m in range(len(Position)):
temp_img = img[Position[m][1]:Position[m][3], Position[m][0]:Position[m][2]]
h1, w1 = temp_img.shape
if w1 > h1:
return []
temp_img = cv2.resize(temp_img, (16, 16))
h0, w0 = temp_img.shape
temp_data = []
for hx in range(h0):
for wx in range(w0):
temp_data.append(float(temp_img[hx, wx]))
data.append(temp_data)
#cv2.imshow("jiange",temp_img)
return data
2.代码
下面这个分割的代码本人调试了好多次,但是还是没有达到理想的状态,但是也大致将银行卡号分割了出来。
代码如下(示例):
import cv2
# 1、读取图像,并把图像转换为灰度图像并显示
img = cv2.imread("D:\\1342.png") # 读取图片
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换了灰度化
cv2.imshow('gray', img_gray) # 显示图片
cv2.waitKey(0)
# 2、将灰度图像二值化,设定阈值是100
img_thre = img_gray
cv2.threshold(img_gray, 59, 255, cv2.THRESH_BINARY_INV, img_thre)
cv2.imshow('threshold', img_thre)
cv2.waitKey(0)
# 3、保存黑白图片
cv2.imwrite('thre_res.png', img_thre)
# 4、分割字符
white = [] # 记录每一列的白色像素总和
black = [] # ..........黑色.......
height = img_thre.shape[0]
width = img_thre.shape[1]
white_max = 0
black_max = 0
# 计算每一列的黑白色像素总和
for i in range(width):
s = 0 # 这一列白色总数
t = 0 # 这一列黑色总数
for j in range(height):
if img_thre[j][i] == 255:
s += 1
if img_thre[j][i] == 0:
t += 1
white_max = max(white_max, s)
black_max = max(black_max, t)
white.append(s)
black.append(t)
print(s)
print(t)
arg = False # False表示白底黑字;True表示黑底白字
if black_max > white_max:
arg = True
# 分割图像
def find_end(start_):
end_ = start_ + 1
for m in range(start_ + 1, width - 1):
if (black[m] if arg else white[m]) > (0.55 * black_max if arg else 0.55 * white_max): # 0.95这个参数请多调整,对应下面的0.05
end_ = m
break
return end_
n = 1
start = 1
end = 2
while n < width - 2:
n += 1
if (white[n] if arg else black[n]) > (0.45 * white_max if arg else 0.45 * black_max):
# 上面这些判断用来辨别是白底黑字还是黑底白字
# 0.05这个参数请多调整,对应上面的0.95
start = n
end = find_end(start)
n = end
if end - start > 5:
cj = img_thre[1:height, start:end]
cv2.imshow('caijian', cj)
cv2.waitKey(0)
总结
提示:这里对文章进行总结:代码运行结果就不展示了,希望大家可以用到。
鸣谢
https://blog.csdn.net/dieju8330/article/details/82631514