Embedded_game/chepai/矫正车牌.py

97 lines
3.2 KiB
Python
Raw Normal View History

2025-01-02 12:48:11 +08:00
# -*- coding: utf-8 -*-
# @Time : 2024/2/18 11:06
# @Author : len
# @File : 矫正车牌.py
# @Software: PyCharm
# @Comment :
import cv2
import numpy as np
# 读取图像
image_path = './img/img_2.png'
image = cv2.imread(image_path)
# 检查图像是否正确加载
if image is None:
raise ValueError("未能加载图像文件。")
# 转换为灰度图
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 应用自适应阈值来突出车牌
thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
# 查找轮廓
contours, _ = cv2.findContours(thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
# 车牌候选的轮廓
candidates = []
for cnt in contours:
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.intp(box)
(x, y), (w, h), angle = rect
if w > 0 and h > 0 and (w * h) > 1000: # 面积要大于1000过滤掉太小的轮廓
aspect_ratio = max(w, h) / min(w, h)
if 2 < aspect_ratio < 5: # 车牌的宽高比大约在2到5之间
candidates.append((box, angle))
# 对每个候选轮廓进行透视变换
for box, angle in candidates:
# 调整角度以使车牌水平
if angle < -45:
angle += 90
# 旋转原始图像,使车牌水平
center = (int(image.shape[1] / 2), int(image.shape[0] / 2))
rotation_matrix = cv2.getRotationMatrix2D(center, angle, 1.0)
rotated = cv2.warpAffine(image, rotation_matrix, (image.shape[1], image.shape[0]))
# 获取旋转后的灰度图像并重新寻找边缘
rotated_gray = cv2.cvtColor(rotated, cv2.COLOR_BGR2GRAY)
rotated_thresh = cv2.adaptiveThreshold(rotated_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
rotated_contours, _ = cv2.findContours(rotated_thresh, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
# 重新定位车牌
rotated_candidates = []
for rotated_cnt in rotated_contours:
rotated_rect = cv2.minAreaRect(rotated_cnt)
rotated_box = cv2.boxPoints(rotated_rect)
rotated_box = np.intp(rotated_box)
(rx, ry), (rw, rh), rangle = rotated_rect
if rw > 0 and rh > 0 and (rw * rh) > 1000:
aspect_ratio_rotated = max(rw, rh) / min(rw, rh)
if 2 < aspect_ratio_rotated < 5:
rotated_candidates.append(rotated_box)
# 对第一个候选框应用透视变换
if rotated_candidates:
box = rotated_candidates[0]
width = int(rotated_rect[1][0])
height = int(rotated_rect[1][1])
# 确保宽度大于高度
if width < height:
width, height = height, width
# 定义透视变换的目标坐标
dst_pts = np.array([[0, height - 1],
[0, 0],
[width - 1, 0],
[width - 1, height - 1]], dtype="float32")
src_pts = np.array(box, dtype="float32")
# 计算透视变换矩阵
M = cv2.getPerspectiveTransform(src_pts, dst_pts)
# 应用透视变换
warped = cv2.warpPerspective(rotated, M, (width, height))
break
# 显示结果
cv2.imshow("Original Image", image)
cv2.imshow("Rotated and Corrected Plate", warped)
cv2.waitKey(0)
cv2.destroyAllWindows()