번호판 인식 프로젝트(完)
DB 조회 후 PASS 여부 출력
: 우선 DB(지금의 경우에는 MySQL)와 연결을 하기 위해서 "mysql.connector" 모듈을 설치해 준다.
pip install mysql.connector
그다음 DB연결을 위해 필요한 정보들을 변수를 지정해서 설정해 준다. (보안 문제로 별도에 폴더에서 사용하는 게 권장됨)
connection = mysql.connector.connect(
host='호스트명',
user='유저이름',
password='비밀번호',
database='데이터베이스명',
auth_plugin='mysql_native_password'
밑에 auth_plugin을 설정한 이유는 MySQL 데이터베이스에서 사용자 인증에 대한 플러그인을 설정하는 것이다. 주로 MySQL 서버에 연결하는 클라이언트가 비밀번호를 제공하여 인증하는 데 사용됩니다.
'mysql_native_password'는 MySQL의 기본 네이티브 비밀번호 인증 방법 중 하나이다. 이 방법은 비밀번호를 해싱하여 저장하고, 클라이언트가 인증 시에 제공한 비밀번호를 해시값과 비교하여 인증하는 방식이다.
더 안전한 인증 방법으로 'caching_sha2_password'나 'sha256_password'와 같은 플러그인을 사용하는 것이 권장된다. 이러한 방법은 더 강력한 보안을 제공하며, 해시된 비밀번호를 더 안전하게 저장하고 전송하는 데 사용된다.
마지막으로 tkinter에 gui를 추가하면 완성이다.
license_plate_pass_or_fail = Label(root, font=('Arial', 25))
license_plate_pass_or_fail.pack()
최종. py
import cv2
import pytesseract
from tkinter import *
from tkinter import filedialog
from PIL import Image, ImageTk
import mysql.connector
# MySQL 연결 정보
mysql_config = {
'host': '호스트명, 주로 localhost로 설정 되어있음',
'user': '유저 이름',
'password': '비밀번호',
'database': '데이터베이스명'
}
pytesseract.pytesseract.tesseract_cmd = 'C:/Program Files/Tesseract-OCR/tesseract' # 테서렉트 파일위치
# 데이터 전처리
def preprocess_text(text):
processed_text = ''.join(char for char in text if char.isdigit() or '가' <= char <= '힣')
processed_text = processed_text[:8]
return processed_text
# 이미지 가져오기
def load_image():
global image_data
path = filedialog.askopenfilename()
if path:
image_data = cv2.imread(path)
image_data = cv2.cvtColor(image_data, cv2.COLOR_BGR2RGB)
display_image()
# tkinter에서 이미지를 display하기 위한 함수
def display_image():
global image_label, image_data, license_plate_label
gray_image = cv2.cvtColor(image_data, cv2.COLOR_RGB2GRAY)
canny_edge = cv2.Canny(gray_image, 170, 200)
contours, new = cv2.findContours(canny_edge.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:30]
contour_with_license_plate = None
license_plate = None
x = None
y = None
w = None
h = None
for contour in contours:
perimeter = cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, 0.01 * perimeter, True)
if len(approx) == 4:
contour_with_license_plate = approx
x, y, w, h = cv2.boundingRect(contour)
license_plate = gray_image[y:y + h, x:x + w]
break
if license_plate is not None:
(thresh, license_plate) = cv2.threshold(license_plate, 127, 255, cv2.THRESH_BINARY)
license_plate = cv2.bilateralFilter(license_plate, 11, 17, 17)
(thresh, license_plate) = cv2.threshold(license_plate, 150, 180, cv2.THRESH_BINARY)
text = pytesseract.image_to_string(license_plate, lang='kor')
text = preprocess_text(text)
image_with_plate = cv2.rectangle(image_data.copy(), (x, y), (x + w, y + h), (0, 0, 255), 3)
image_with_plate = cv2.putText(image_with_plate, text, (x - 100, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)
image_with_plate = Image.fromarray(image_with_plate)
image_with_plate = ImageTk.PhotoImage(image_with_plate)
license_plate_label.config(image=image_with_plate)
license_plate_label.image = image_with_plate
license_plate_label.pack()
license_plate_text.set("License Plate: " + text)
pass_or_fail(text)
else:
license_plate_text.set("License Plate: Not Found")
# DB(MySQL) 조회 후 pass or fail 여부 출력
def pass_or_fail(license_plate_text):
try:
# MySQL에 연결
connection = mysql.connector.connect(
host='호스트명',
user='유저이름',
password='비밀번호',
database='데이터베이스명',
auth_plugin='mysql_native_password'
)
# MySQL 쿼리 실행
cursor = connection.cursor()
if len(license_plate_text) >= 6:
query = "SELECT * FROM Vehicle_num2 WHERE car_num LIKE CONCAT('%', %s, '%')"
cursor.execute(query, (license_plate_text,))
result = cursor.fetchone()
else:
# 데이터 길이가 6자 미만인 경우에 대한 처리
result = None
# pass면 초록색, fail이면 빨간색으로 출력
if result:
license_plate_pass_or_fail.config(text="PASS", fg="green")
else:
license_plate_pass_or_fail.config(text="FAIL", fg="red")
connection.close()
except mysql.connector.Error as err:
print("MySQL Error: {}".format(err))
# Tkinter GUI 생성
root = Tk()
root.title("License Plate Recognition")
# 메뉴 생성
menu_bar = Menu(root)
file_menu = Menu(menu_bar, tearoff=0)
file_menu.add_command(label="Open", command=load_image)
file_menu.add_command(label="Exit", command=root.quit)
menu_bar.add_cascade(label="File", menu=file_menu)
root.config(menu=menu_bar)
# 이미지 프레임 생성
image_frame = Frame(root)
image_frame.pack()
# 이미지 표시 라벨 생성
image_label = Label(image_frame)
image_label.pack()
# 번호판 텍스트 라벨 생성
license_plate_label = Label(root)
license_plate_label.pack()
license_plate_text = StringVar()
license_plate_text_label = Label(root, textvariable=license_plate_text, font=('Arial', 25))
license_plate_text_label.pack()
# pass 여부 표시 라벨 생성
license_plate_pass_or_fail = Label(root, font=('Arial', 25))
license_plate_pass_or_fail.pack()
root.mainloop()
이제 마지막으로 자동차 정보를 추가할 수 있게 기능을 더해보자.
def register_vehicle():
register_window = Toplevel(root)
register_window.title("Register Vehicle")
def insert_data():
try:
# MySQL에 연결
connection = mysql.connector.connect(
host='호스트명',
user='유저네임',
password='비밀번호',
database='DB이름',
auth_plugin='mysql_native_password')
# MySQL 쿼리 실행
cursor = connection.cursor()
owner_name = owner_name_entry.get()
car_num = car_num_entry.get()
query = "INSERT INTO Vehicle_num2 (car_id, car_owner, car_num) VALUES (NULL, %s, %s)"
cursor.execute(query, (owner_name, car_num))
connection.commit()
messagebox.showinfo("Success", "Vehicle registered successfully!")
connection.close()
except mysql.connector.Error as err:
print("MySQL Error: {}".format(err))
messagebox.showerror("Error", "Failed to register vehicle!")
owner_name_label = Label(register_window, text="Owner Name:")
owner_name_label.grid(row=0, column=0, padx=10, pady=5)
owner_name_entry = Entry(register_window)
owner_name_entry.grid(row=0, column=1, padx=10, pady=5)
car_num_label = Label(register_window, text="Car Number:")
car_num_label.grid(row=1, column=0, padx=10, pady=5)
car_num_entry = Entry(register_window)
car_num_entry.grid(row=1, column=1, padx=10, pady=5)
submit_button = Button(register_window, text="Submit", command=insert_data)
submit_button.grid(row=2, columnspan=2, padx=10, pady=5)
: car_id는 AUTO_INCREMENT로 설정해 놓았기 때문에 따로 지정할 필요가 없다.
>> 그리고 마지막으로 DB 조회하는 기능까지 만들면 완성이다.
def show_registered_vehicles():
try:
# MySQL에 연결
connection = mysql.connector.connect(
host='호스트명',
user='유저네임',
password='비밀번호',
database='DB이름',
auth_plugin='mysql_native_password'
)
# MySQL 쿼리 실행
cursor = connection.cursor()
query = "SELECT * FROM Vehicle_num2"
cursor.execute(query)
results = cursor.fetchall()
if results:
for row in results:
print(row)
else:
print("No registered vehicles found.")
connection.close()
except mysql.connector.Error as err:
print("MySQL Error: {}".format(err))
- 메뉴 추가
register_menu = Menu(menu_bar, tearoff=0)
register_menu.add_command(label="Register Vehicle", command=register_vehicle)
register_menu.add_command(label="Show Registered Vehicles", command=show_registered_vehicles)
menu_bar.add_cascade(label="Register", menu=register_menu)
- 결과물
'AIoT' 카테고리의 다른 글
AIoT 정규 66일차 (0) | 2024.04.17 |
---|---|
AIoT 정규 65일차 (0) | 2024.04.15 |
AIoT 정규 63일차 (0) | 2024.04.09 |
AIoT 정규 62일차 (0) | 2024.04.08 |
AIoT 정규 61일차 (0) | 2024.04.05 |