First acquaintance with image processing: from entry to career change

After the last failure, I learned to be smart this time.
I can't make things by myself. I can't mess around with anything. I follow others and gnaw others' codes. Isn't it good for me to learn from others?
So this time I use python for bank card number recognition.
Not much to say, start!

import cv2
import numpy as np

Define drawing function

def imshow(name, img):
cv2.imshow(name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
1
2
3
4
5
6
7
8
cv2.imshow() Draw a picture and a set of combined punches, We young people can't stand it after receiving chemical hair, let's first define a function package.

Read template image

0 means that it can be read as a single-channel picture, that is, a grayscale image can also be used

ref = cv2.cvtColor(img_num, cv2.COLOR_BGR2GRAY) converted to grayscale

img_num = cv2.imread('images/ocr_a_reference.png',0)
imshow('img_num',img_num)
1
2
3
4
5
Insert picture description here

Convert to binary image

cv2.threshold (input image, threshold, assignment, method) Here the method is 0 for higher than the threshold and 255 for lower than the threshold

cv2.threshold returns two values ​​The second value is the processed image I need

img_num_bin = cv2.threshold(img_num,10,255,cv2.THRESH_BINARY_INV)[1]
imshow('img_num_bin',img_num_bin)
1
2
3
4
Insert the picture description here
because the next bank card number will be white, so it turns into white Black background to facilitate subsequent template matching

Contour extraction

The parameters accepted by the cv2.findContours() function is a binary image, that is, black and white (not grayscale), cv2.RETR_EXTERNAL only detects the outer contour, cv2.CHAIN_APPROX_SIMPLE only retains the end point coordinates

Each element in the returned list is an outline in the image

num_cnts list, =cv2.findContours(img_num_bin.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img_num_bin, num_cnts_list, -1, (0,0,255), 3)
imshow_num('img_num)
1
2
3
4
5 The outline of the
picture inserted here is
not displayed, but the contrast is narrower. Is it because the outline has automatically turned black? Don't care for the time being, next you have to circle each outline, and you will know when you have a look.

Contour sorting
num_rect_list = num_cnts_sort(num_cnts_list)
1
num_cnts_sort is my custom function to sort the contours and return them in a certain order

def num_cnts_sort(list,right=1,up=0):

up=1 means from top to bottom, right=1 means from left to right, -1 means vice versa

reverse = False
if up==-1 or right== -1:
    reverse = True

if up == 0:
    # 左右方向排序 权重选x
    i = 0

if right == 0:
    i = 1

# 找到的轮廓用外接矩形框起来 cv2.boundingRect(c)返回x,y,w,h
boundingBoxs = [cv2.boundingRect(c) for c in list] #生成器
# sorted(输入序列,排序规则,reverse=True 由小到大否则由大到小)
# lambda 匿名函数 输入序列的每个元素 输出b[i]
boxs = sorted(boundingBoxs,key= lambda b: b[i],reverse=reverse )

return boxs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Draw each contour circumscribing rectangle in order

for num_rect in num_rect_list:
(x,y,w,h)=num_rect
num_rect_img = cv2.rectangle(img_num_bin.copy(),(x,y),(x+w,y+h),(255,0,0),2)
imshow('num_rect_img',num_rect_img)

1
2
3
4
5
There is
no problem inserting the picture description and sorting here , and then cut the corresponding digital template to correspond to the number

Match pictures to numbers

num_rect_dic = {}
for (i,num_rect) in enumerate(num_rect_list):
(x, y, w, h) = num_rect

num_rect_item = img_num_bin[y:y+h,x:x+w]
num_rect_item = num_resize(num_rect_item,h_size=88)
# 把数字和截下来的图像对应
num_rect_dic[i]=num_rect_item
imshow('num_rect_item', num_rect_item)

1
2
3
4
5
6
7
8
9
10
num_resize is a custom function, enter the height or width to automatically calculate the zoom

def num_resize(img,w_size=0,h_size=0):
(w,h)=img.shape # size返回总元素个数 和matlab不一样
if w_size == 0:
r = h_size/float(h)
w_size = int(rh)
if h_size == 0:
r = w_size/float(w)
h_size = int(w
h)
resized = cv2.resize(img,(w_size,h_size))
return resized

1
2
3
4
5
6
7
8
9
10
11
pairs of bank card image preprocessing

Preprocessing bank card image

Read image

bank_img = cv2.imread('images/credit_card_01.png')
bank_img_gray = cv2.cvtColor(bank_img,cv2.COLOR_BGR2GRAY)
imshow('bank_img',bank_img)
imshow('bank_img_gray',bank_img_gray)

Define the convolution kernel

rectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 3)) # Rectangular convolution kernel
sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))

Top hat operation highlights bright parts

bank_img_tophat = cv2.morphologyEx(bank_img_gray,cv2.MORPH_TOPHAT, rectKernel)
imshow('bank_img_tophat',bank_img_tophat)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Insert
the horizontal line of the picture description number here is too dark, I think If performing binarization, choose an appropriate parameter or perform an edge detection.

Edge detection

X direction edge detection processing

bank_img_grad = cv2.Sobel(bank_img_tophat,cv2.CV_32F,1,0,ksize=-1)
imshow('bank_img_tophat',bank_img_grad)

Normalized

bank_img_grad_abs = np.absolute(bank_img_grad)
(max,min) = (np.max(bank_img_grad_abs),np.min(bank_img_grad_abs))
bank_img_grad_abs = (255*(bank_img_grad_abs-min)/(max-min))
bank_img_grad_abs = bank_img_grad_abs.astype('uint8')
imshow('s',bank_img_grad_abs)

Binarization cv2.THRESH_OTSU will select the appropriate threshold for binarization cv2.threshold returns two elements and the second is the processed image

bank_img_bin = cv2.threshold (bank_img_grad_abs, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) [1]

imshow('s',bank_img_bin)

Guess you like

Origin blog.51cto.com/14308903/2550977