opencv识别身份证号

opencv 识别身份证号

python模块

  • opencv
  • pytesseract
  • PIL

1.模块安装

1.1 opencv安装

通过pip进行安装,在此不再叙述 注意安装版本,以下是python3的安装方式

pip install opencv-python

1.2 pytesseract安装

通过pip进行安装,在此不再叙述 注意安装版本,以下是python3的安装方式

pip install pytesseract

除此之外,需要安装 Tesseract-OCR。

windows 环境

前往Teaseract-OCR 下载exe,然后双击程序安装即可,可以勾选Additional language data(download)选项来安装OCR识别支持的语言包,但下载语言包实在是慢,我们可以直接从 tessdata下载zip的语言包压缩文件,解压后将tessdata-master中的文件复制到Tesseract的安装目录C:\Program Files (x86)\Tesseract-OCR\tessdata目录下,最后我们配置下环境变量,我们将C:\Program Files (x86)\Tesseract-OCR添加到环境变量中。

linux 环境

在Ubuntu、Debian、Deepin系统中,安装命令如下:

#安装tesseract
sudo apt-get install -y tesseract-ocr libtesseract-dev libleptonica-dev

#安装语言包
git clone https://github.com/tesseract-ocr/tessdata.git
sudo mv tessdata/* /usr/share/tesseract-ocr/tessdata

在CentOS、Red Hat系统下,安装命令如下:

#安装tesseract
yum install -y tesseract

#安装语言包
git clone https://github.com/tesseract-ocr/tessdata.git
mv tessdata/* /usr/share/tesseract/tessdata

1.3 PIL安装

通过pip进行安装,在此不再叙述 注意安装版本,以下是python3的安装方式

pip install pillow

2. 实现步骤

2.1 方向矫正

图片拍摄过程中,可能因为拍摄角度以及操作过程造成图片角度倾斜,影响识别的准确率,或者无法识别问题。通过透视矫正,可以很好的解决这一问题

  # 对图片进行旋转,得到变换矩阵
  M = cv2.getRotationMatrix2D(center, angle, 1.0)
  # 仿射变换,使得原图片根据变换矩阵进行变换
  cv2.warpAffine(img, M, (w, h), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)

2.2 形态学变换

通过形态学的腐蚀膨胀来,使得去除一些干扰的噪点,使得身份证号区域进行合并,区域更大,能够更好的判断位置

   # 卷积核  5 x 5  此参数不是固定,根据实际情况调整,最好是奇数且不宜过大 如: 3,5,7,9
   kernel = np.ones((5,5),np.uint8)
   # 膨胀两个像素  iterations=2
   dst = cv2.erode(rotated,kernel,iterations=2)

2.3 寻找边框

寻找图片中所有边框,然后通过身份证号的边框特征,(如:宽度,高度,边框左上坐标,右下坐标,面积等等)进行筛选,最终确定身份证号边框,从而截取边框内容

contours, hierarchy = cv2.findContours(dst, cv2.RETR_TREE , cv2.CHAIN_APPROX_NONE)
# 遍历边框
for i in contours:
     
    # area = cv2.contourArea(i)
    # 边框最小矩形
    rect = cv2.minAreaRect(i)
	
	# 边框左上,左下,右上,右下坐标
    box = cv2.boxPoints(rect)
    box = np.int0(box)
    # 计算高和宽
    height = abs(box[0][1] - box[2][1])
    width = abs(box[0][0] - box[2][0])
    
	# 判断 身份证号 边框 特征
    if width > 0.4 * w and  10  0.5 * h:
		print(box)

2.4 识别文字

通过pyteaseract进行识别身份证号文字,将截取的身份证号图片区域,识别出结果。注意:不可将cv2图片直接识别,需转换成pillow,识别时,添加白名单进行识别限定。

# cv2 转 pillow
image = Image.fromarray(cv2.cvtColor(idcard_img,cv2.COLOR_BGR2RGB))
# 识别
idcard = pytesseract.image_to_string(image,config="-c tessedit_char_whitelist=0123456789X")

3. 代码

import cv2
import pytesseract
from PIL import Image

# tesseract 位置配置
tesseract_cmd = r'D:\\Tesseract-OCR\tesseract'
pytesseract.pytesseract.tesseract_cmd =tesseract_cmd

# 获取边框
def num_box(path):
	img = cv2.imread(path)
	#灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
	#二值化
    retval, threshold = cv2.threshold(gray, 127, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)	    
	# 双边模糊,降噪
    threshold=cv2.bilateralFilter(src=threshold, d=0, sigmaColor=20, sigmaSpace=5)
    # 获取边框
    coords = np.column_stack(np.where(threshold < 127))
	#倾斜角度
    angle = cv2.minAreaRect(coords)[-1]
    if abs(angle) < 70:
        if angle < -45:
            angle = -(90+ angle)
        else:
            angle = -angle
    else:
        angle = 0 
    
    #仿射变换
    h, w = threshold.shape[:2]
    center = (w//2, h//2)  #旋转中心
    M = cv2.getRotationMatrix2D(center, angle, 1.0)
    rotated_color = cv2.warpAffine(img, M, (w, h), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)
    
    
    rotated = cv2.warpAffine(threshold, M, (w, h), flags=cv2.INTER_CUBIC, borderMode=cv2.BORDER_REPLICATE)
	# 双边滤波降噪
    rotated =cv2.bilateralFilter(src=rotated, d=0, sigmaColor=5, sigmaSpace=5)
    
	# 寻找边框
    kernel = np.ones((5,5),np.uint8)
    dst = cv2.erode(rotated,kernel,iterations=2)
    contours, hierarchy = cv2.findContours(dst, cv2.RETR_TREE , cv2.CHAIN_APPROX_NONE)
    #遍历边框
    for i in contours:
		#边框点
        rect = cv2.minAreaRect(i)
        box = cv2.boxPoints(rect)
        box = np.int0(box)
        # 计算高和宽
        height = abs(box[0][1] - box[2][1])
        width = abs(box[0][0] - box[2][0])
        # 判断边框特征
        if width > 0.4 * w and  10  0.5 * h:
 			# 截取图片
            idcard_img =  rotated_color[min(box[2][1],box[0][1]):max(box[2][1],box[0][1]),min(box[0][0],box[2][0]):max(box[0][0],box[2][0])]
            # 灰度图识别便于识别
            gray_idcard = cv2.cvtColor(idcard_img, cv2.COLOR_BGR2GRAY)
            #cv2.imwrite("gray_idcard.png",gray_idcard)
            return gray_idcard
    return None


#识别号码
def get_num(idcard_img):
    image = Image.fromarray(cv2.cvtColor(idcard_img,cv2.COLOR_BGR2RGB))
    idcard = pytesseract.image_to_string(image,config="-c tessedit_char_whitelist=0123456789X")
    return idcard


def ocr(path):
    idcard_img = num_box(path)
    if idcard_img is not None:
        idcard = get_num(idcard_img)
        return idcard
    return "" 


idcard = ocr("idcard1.png")
print(idcard)

效果

原图:
opencv识别身份证号_第1张图片

识别结果: 123456196108047890
opencv识别身份证号_第2张图片

你可能感兴趣的:(opencv,python,图像处理)