OpenCV example (8) license plate character recognition technology (3) Chinese character recognition

License plate character recognition technology (3) Chinese character recognition

Compared with the recognition of numbers and English characters, the recognition of Chinese characters in car license plates is more difficult, mainly due to the following four aspects:

(1) Character strokes are lost due to segmentation errors.

(2) The car license plate is contaminated causing dirt on the characters.

(3) The low resolution of the collected vehicle images makes it difficult to distinguish Chinese characters with multiple strokes.

(4) The differences in the lighting effects of vehicle image acquisition lead to lighter strokes.

Considering these difficulties in Chinese character recognition, it is difficult to directly extract the local features of characters. As the most important feature, strokes only exist in Chinese characters, which is known by prior knowledge. Once the stroke features of Na, horizontal, vertical, and left strokes are extracted, a lot of work for character recognition of Chinese characters has been completed. In the horizontal direction, the fluctuation of the gray value of horizontal strokes is low-frequency, and the gray-scale change of vertical strokes is low-frequency; in the vertical direction, the gray-scale variation of horizontal strokes is for high frequency. In the process of character feature extraction of Chinese characters, it is obviously a good choice to use the multi-resolution feature of wavelet.

For the work related to the recognition of Chinese characters, it can be carried out after a series of related operations such as preprocessing the image and extracting the features of the image. The first step is to preprocess the original image; the second step is to extract the original features of the characters (mainly by wavelet transform), and reduce the dimensionality of the original features (mainly by linear discriminant analysis (LDA) transformation matrix), to obtain The final feature of the character; the third step is to read the final feature obtained in the feature template matching and minimum distance classifier to obtain the final recognition result of the character.

1. Code example

Recognition of Chinese license plates (including new energy vehicles)

import cv2 as cv
from PIL import Image
import pytesseract as tess


def recoginse_text(image):
    """
    步骤:
    1、灰度,二值化处理
    2、形态学操作去噪
    3、识别
    :param image:
    :return:
    """

    # 灰度 二值化
    gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
    # 如果是白底黑字 建议 _INV
    ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV| cv.THRESH_OTSU)


    # 形态学操作 (根据需要设置参数(1,2))
    kernel = cv.getStructuringElement(cv.MORPH_RECT,(1,2))  #去除横向细线
    morph1 = cv.morphologyEx(binary,cv.MORPH_OPEN,kernel)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (2, 1)) #去除纵向细线
    morph2 = cv.morphologyEx(morph1,cv.MORPH_OPEN,kernel)
    cv.imshow("Morph",morph2)

    # 黑底白字取非,变为白底黑字(便于pytesseract 识别)
    cv.bitwise_not(morph2,morph2)
    textImage = Image.fromarray(morph2)

    # 图片转文字
    text=tess.image_to_string(textImage)
    n=10 #根据不同国家车牌固定数目进行设置
    print("识别结果:")
    print(text[1:n])
   


def main():
    # 读取需要识别的数字字母图片,并显示读到的原图
    src = cv.imread("cp.jpg")
    cv.imshow("src",src)

    # 识别
    recoginse_text(src)

    cv.waitKey(0)
    cv.destroyAllWindows()

if __name__=="__main__":
    main()





2. Encountered a problem

insert image description here

No module named ‘pytesseract’

The pytesseract module is missing.

Install the module in the environment

insert image description here
After the installation was completed and the program was run, a bunch of problems appeared as a result:

insert image description here
The reason is that the Tesseract-OCR tool required by pytesseract is not installed. The download path of the Windows version of the installation package is https://github.com/UB-Mannheim/tesseract/wiki

insert image description here

Just double-click the file to install it. The installation location here (remember this path, it will be used later) adopts the default value:

     C:\Program Files\Tesseract-OCR

Configure pytesseract.py to open "My Computer", enter \Users==\AppData\Local\Programs\Python\Python38\Lib\site-packages\pytesseract\, find the pytesseract.py file, open this file with a text editor, Find the "tesseract_cmd" keyword

insert image description here

At this point, the character recognition development environment is ready, and the code can be written below.

Code example:

import cv2 as cv
from PIL import Image
import pytesseract as tess


def recoginse_text(image):
    """
    步骤:
    1、灰度,二值化处理
    2、形态学操作去噪
    3、识别
    :param image:
    :return:
    """

    # 灰度 二值化
    gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY)
    # 如果是白底黑字 建议 _INV
    ret,binary = cv.threshold(gray,0,255,cv.THRESH_BINARY_INV| cv.THRESH_OTSU)


    # 形态学操作 (根据需要设置参数(1,2))
    kernel = cv.getStructuringElement(cv.MORPH_RECT,(1,2))  #去除横向细线
    morph1 = cv.morphologyEx(binary,cv.MORPH_OPEN,kernel)
    kernel = cv.getStructuringElement(cv.MORPH_RECT, (2, 1)) #去除纵向细线
    morph2 = cv.morphologyEx(morph1,cv.MORPH_OPEN,kernel)
    cv.imshow("Morph",morph2)

    # 黑底白字取非,变为白底黑字(便于pytesseract 识别)
    cv.bitwise_not(morph2,morph2)
    textImage = Image.fromarray(morph2)

    # 图片转文字
    text=tess.image_to_string(textImage)
    n=10 #根据不同国家车牌固定数目进行设置
    print("识别结果:")
    print(text[1:n])
   


def main():
    # 读取需要识别的数字字母图片,并显示读到的原图
    src = cv.imread("cp.jpg")
    cv.imshow("src",src)

    # 识别
    recoginse_text(src)

    cv.waitKey(0)
    cv.destroyAllWindows()

if __name__=="__main__":
    main()



insert image description here

3. Example of Chinese character recognition code

code example

import tkinter as tk
from tkinter.filedialog import *
from tkinter import ttk
import predict
import cv2
from PIL import Image, ImageTk
import threading
import time



class Surface(ttk.Frame):
	pic_path = ""
	viewhigh = 600
	viewwide = 600
	update_time = 0
	thread = None
	thread_run = False
	camera = None
	color_transform = {
    
    "green":("绿牌","#55FF55"), "yello":("黄牌","#FFFF00"), "blue":("蓝牌","#6666FF")}
		
	def __init__(self, win):
		ttk.Frame.__init__(self, win)
		frame_left = ttk.Frame(self)
		frame_right1 = ttk.Frame(self)
		frame_right2 = ttk.Frame(self)
		win.title("车牌识别")
		win.state("zoomed")
		self.pack(fill=tk.BOTH, expand=tk.YES, padx="5", pady="5")
		frame_left.pack(side=LEFT,expand=1,fill=BOTH)
		frame_right1.pack(side=TOP,expand=1,fill=tk.Y)
		frame_right2.pack(side=RIGHT,expand=0)
		ttk.Label(frame_left, text='原图:').pack(anchor="nw") 
		ttk.Label(frame_right1, text='车牌位置:').grid(column=0, row=0, sticky=tk.W)
		
		from_pic_ctl = ttk.Button(frame_right2, text="来自图片", width=20, command=self.from_pic)
		from_vedio_ctl = ttk.Button(frame_right2, text="来自摄像头", width=20, command=self.from_vedio)
		self.image_ctl = ttk.Label(frame_left)
		self.image_ctl.pack(anchor="nw")
		
		self.roi_ctl = ttk.Label(frame_right1)
		self.roi_ctl.grid(column=0, row=1, sticky=tk.W)
		ttk.Label(frame_right1, text='识别结果:').grid(column=0, row=2, sticky=tk.W)
		self.r_ctl = ttk.Label(frame_right1, text="")
		self.r_ctl.grid(column=0, row=3, sticky=tk.W)
		self.color_ctl = ttk.Label(frame_right1, text="", width="20")
		self.color_ctl.grid(column=0, row=4, sticky=tk.W)
		from_vedio_ctl.pack(anchor="se", pady="5")
		from_pic_ctl.pack(anchor="se", pady="5")
		self.predictor = predict.CardPredictor()
		self.predictor.train_svm()
		
	def get_imgtk(self, img_bgr):
		img = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2RGB)
		im = Image.fromarray(img)
		imgtk = ImageTk.PhotoImage(image=im)
		wide = imgtk.width()
		high = imgtk.height()
		if wide > self.viewwide or high > self.viewhigh:
			wide_factor = self.viewwide / wide
			high_factor = self.viewhigh / high
			factor = min(wide_factor, high_factor)
			
			wide = int(wide * factor)
			if wide <= 0 : wide = 1
			high = int(high * factor)
			if high <= 0 : high = 1
			im=im.resize((wide, high), Image.ANTIALIAS)
			imgtk = ImageTk.PhotoImage(image=im)
		return imgtk
	
	def show_roi(self, r, roi, color):
		if r :
			roi = cv2.cvtColor(roi, cv2.COLOR_BGR2RGB)
			roi = Image.fromarray(roi)
			self.imgtk_roi = ImageTk.PhotoImage(image=roi)
			self.roi_ctl.configure(image=self.imgtk_roi, state='enable')
			self.r_ctl.configure(text=str(r))
			self.update_time = time.time()
			try:
				c = self.color_transform[color]
				self.color_ctl.configure(text=c[0], background=c[1], state='enable')
			except: 
				self.color_ctl.configure(state='disabled')
		elif self.update_time + 8 < time.time():
			self.roi_ctl.configure(state='disabled')
			self.r_ctl.configure(text="")
			self.color_ctl.configure(state='disabled')
		
	def from_vedio(self):
		if self.thread_run:
			return
		if self.camera is None:
			self.camera = cv2.VideoCapture(0)
			if not self.camera.isOpened():
				mBox.showwarning('警告', '摄像头打开失败!')
				self.camera = None
				return
		self.thread = threading.Thread(target=self.vedio_thread, args=(self,))
		self.thread.setDaemon(True)
		self.thread.start()
		self.thread_run = True
		
	def from_pic(self):
		self.thread_run = False
		self.pic_path = askopenfilename(title="选择识别图片", filetypes=[("jpg图片", "*.jpg")])
		if self.pic_path:
			img_bgr = predict.imreadex(self.pic_path)
			self.imgtk = self.get_imgtk(img_bgr)
			self.image_ctl.configure(image=self.imgtk)
			resize_rates = (1, 0.9, 0.8, 0.7, 0.6, 0.5, 0.4)
			for resize_rate in resize_rates:
				print("resize_rate:", resize_rate)
				try:
					r, roi, color = self.predictor.predict(img_bgr, resize_rate)
				except:
					continue
				if r:
					break
			#r, roi, color = self.predictor.predict(img_bgr, 1)
			self.show_roi(r, roi, color)

	@staticmethod
	def vedio_thread(self):
		self.thread_run = True
		predict_time = time.time()
		while self.thread_run:
			_, img_bgr = self.camera.read()
			self.imgtk = self.get_imgtk(img_bgr)
			self.image_ctl.configure(image=self.imgtk)
			if time.time() - predict_time > 2:
				r, roi, color = self.predictor.predict(img_bgr)
				self.show_roi(r, roi, color)
				predict_time = time.time()
		print("run end")
		
		
def close_window():
	print("destroy")
	if surface.thread_run :
		surface.thread_run = False
		surface.thread.join(2.0)
	win.destroy()
	
	
if __name__ == '__main__':
	win=tk.Tk()
	
	surface = Surface(win)
	win.protocol('WM_DELETE_WINDOW', close_window)
	win.mainloop()
	

Output result:

insert image description here

Guess you like

Origin blog.csdn.net/qq_41600018/article/details/132247917