Python에서 opencv LED 화면 디지털 인식 사용(번호판 인식에도 사용 가능, 동일한 원리)

프로젝트 요구 사항에 따라 CPU 기반 LED 디지털 식별이 필요하며 요구 사항을 충족하기 위해 전통적인 방법을 사용하여 실험을 수행합니다. 센서에 표시된 숫자를 확인하세요. 따라서 opencv 함수는 기능적 요구 사항을 달성하기 위해 일부 처리를 수행하는 데 사용됩니다.

여기에 이미지 설명을 삽입하세요.

먼저 이미지를 읽어보세요. LED 화면의 면적을 대략적으로 구하고 싶지 않아서 RGB를 HSV 공간으로 변환하고 각각 H, S, V의 임계값을 설정하여 면적이 나타나도록 했습니다. 코드에서 크기 조정 작업이 수행되는 것을 볼 수 있습니다. 이 작업은 필요하지 않습니다. H, S 및 V의 특정 값은 특정 이미지에 따라 설정됩니다.

img = cv2.imread('pic.jpg')
#start = time.time()
new_size = (640, 400)
img = cv2.resize(img, new_size)
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask = np.zeros(hsv_img.shape[:2], dtype=np.uint8)
mask[(hsv_img[:,:,0] >= 130) & (hsv_img[:,:,0] <= 255) & (hsv_img[:,:,1] >= 0) &
(hsv_img[:,:,1] <= 255) & (hsv_img[:,:,2] >= 0) & (hsv_img[:,:,2] <= 90)] = 1
result = cv2.bitwise_and(img, img, mask=mask)

원본 이미지를 처리한 후의 결과:

여기에 이미지 설명을 삽입하세요.

다음으로 윤곽정보를 검출해야 하므로 그레이스케일 처리를 수행한다.

gray = cv2.cvtColor(result,cv2.COLOR_BGR2GRAY)

처리 후 결과:

여기에 이미지 설명을 삽입하세요.

등고선 검출은 Canny를 이용하여 모든 등고선 정보를 저장하고 모든 등고선 정보 프레임을 선택합니다.선택한 영역이 직사각형이므로 작은 영역은 삭제하고 큰 영역만 표시하는 영역 전략을 사용합니다.

#转灰度,做单通道计算比较节省时间
edges = cv2.Canny(gray,50,150,apertureSize = 3)

#所有轮廓的列表contours和分层信息
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# print("轮廓数量:", len(contours))

img_copy = img.copy() # 复制原图,避免在原图上直接画框

for cnt in contours:
    x, y, w, h = cv2.boundingRect(cnt) # 获取轮廓的边界矩形
    area = w * h
    if area > 10000:
        x, y, w, h = cv2.boundingRect(cnt)
        area = w * h
        # print("xywh", x, y, w, h)
        # print("矩形面积:", area)
        roi = img_copy[y:y + h + 26, x:x + w+2]
        # cv2.imshow("ROI", roi)
        # cv2.waitKey(0)
        # print("矩形面积:", area)

이 그림은 프레임에서 선택한 모든 윤곽을 보여줍니다.

여기에 이미지 설명을 삽입하세요.

영역 임계값 처리를 수행한 후 LCD 화면 영역의 직사각형 프레임이 얻어집니다.

여기에 이미지 설명을 삽입하세요.

나중에 처리하기 위해 프레임 영역을 제거합니다. 그레이스케일 처리를 위해 원본 이미지에서 프레임 영역을 직접 꺼내서 엣지 검출을 수행합니다. 엣지 검출 전에 가우시안 처리를 수행하여 노이즈를 제거합니다.

gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
# 高斯滤波
blur = cv2.GaussianBlur(gray, (3, 3), 0)

# 边缘检测
edges = cv2.Canny(gray, 50, 255)

프레임 선택 영역을 가져오고 가장자리 감지 결과를 수행합니다.

여기에 이미지 설명을 삽입하세요.

여기에 이미지 설명을 삽입하세요.

이 시점에서 LED 화면의 윤곽선이 감지되었는데, 우리가 촬영하여 얻은 프레임이 기울어져 있음을 알 수 있으므로 원근보정을 수행해야 하며, 원근보정을 위해서는 4개의 꼭지점의 좌표값이 필요합니다. 여기서는 두 가지 방법을 시도했습니다: 1. 최소 둘러싸는 직사각형을 그립니다. 2. 흰색 픽셀의 좌표를 얻습니다(여기서 생각한 전략은 각각 x축과 y축에 따라 찾고 최소값과 최대값을 찾습니다). x축의 흰색 가장자리 좌표, y축의 가장 작은 흰색 가장자리 값 및 최대 좌표)

1. 원근교정을 위해 최소외접사각형을 사용한다

# 获得轮廓信息
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 绘制最小外接矩形
for cnt in contours:
    rect = cv2.minAreaRect(cnt)
    box = cv2.boxPoints(rect)
    box = np.int0(box)

    cv2.drawContours(roi, [box], 0, (0, 255, 0), 1)

    # 获取矩形的四个顶点坐标
    rect_points = np.int0(cv2.boxPoints(rect))
    # print("矩形的四个顶点坐标:", rect_points)

# cv2.imshow('Contours', roi)
# cv2.waitKey(0)

# 定义原图像的四个角点坐标
src = np.float32([[-8,61],[186 , -3],[ 23, 156], [218 , 91]])

# 定义输出图像的四个角点坐标
dst = np.float32([[0, 0],[200, 0],[0, 100],[200, 100]])

# 计算变换矩阵
M = cv2.getPerspectiveTransform(src, dst)

# 应用变换矩阵
result = cv2.warpPerspective(roi, M, (200, 100))


显示图像
cv2.imshow('Contours', result)
cv2.waitKey(0)

가장 작은 둘러싸는 직사각형을 얻으십시오:

여기에 이미지 설명을 삽입하세요.

원근 교정 결과:

여기에 이미지 설명을 삽입하세요.

최소 외부 직사각형을 통해 프레임 영역이 LED 화면 외에 다른 영향을 미치는 것을 볼 수 있으며, 후속 실험에서는 이러한 중복 영역이 후속 실험의 정확도에 영향을 미치는 것으로 나타났습니다.

2. x축과 y축에서 각각 흰색 픽셀의 좌표를 얻습니다.

# 获取白色像素点坐标
coordinates = np.column_stack(np.where(edges == 255))

# # 打印白色像素点坐标
# print(coordinates)

# 在x轴方向上找到最小和最大的两个坐标
x_min = coordinates[np.argmin(coordinates[:,0])].copy()
x_min[0], x_min[1] = x_min[1], x_min[0]
x_max = coordinates[np.argmax(coordinates[:,0])].copy()
x_max[0], x_max[1] = x_max[1], x_max[0]

# 在y轴方向上找到最小和最大的两个坐标
y_min = coordinates[np.argmin(coordinates[:,1])].copy()
y_min[0], y_min[1] = y_min[1], y_min[0]
y_max = coordinates[np.argmax(coordinates[:,1])].copy()
y_max[0], y_max[1] = y_max[1], y_max[0]

# # # 打印最小和最大的两个坐标
# print('x_min:', x_min)
# print('x_max:', x_max)
# print('y_min:', y_min)
# print('y_max:', y_max)


# 定义原图像的四个角点坐标
src = np.float32([y_min,x_min,x_max, y_max])

# 定义输出图像的四个角点坐标
dst = np.float32([[0, 0],[200, 0],[0, 100],[200, 100]])

# 计算变换矩阵
M = cv2.getPerspectiveTransform(src, dst)

# 应用变换矩阵
result = cv2.warpPerspective(roi, M, (200, 100))
#显示图像
# cv2.imshow('result', result)
# cv2.waitKey(0)

아이디어에 따라 x축과 y축의 최대값과 최소값에 대한 흰색 픽셀 좌표를 찾고 상자를 그립니다.

여기에 이미지 설명을 삽입하세요.

원근 교정 후:

여기에 이미지 설명을 삽입하세요.

원근 보정된 이미지 영역을 RGB에서 HSV로 변환하고 임계값을 설정하여 디지털 영역을 더 잘 표시합니다.

hsv_img = cv2.cvtColor(result, cv2.COLOR_BGR2HSV)
# cv2.imshow('hsv_img', hsv_img)
# cv2.waitKey(0)
mask = np.zeros(hsv_img.shape[:2], dtype=np.uint8)
mask[(hsv_img[:,:,0] >= 0) & (hsv_img[:,:,0] <= 255) & (hsv_img[:,:,1] >= 0) &
(hsv_img[:,:,1] <= 255) & (hsv_img[:,:,2] >= 0) & (hsv_img[:,:,2] <= 100)] = 1
result1 = cv2.bitwise_and(hsv_img, hsv_img, mask=mask)

# cv2.imshow("Contours", result1)
# cv2.waitKey(0)

RGB를 HSV로 변환:

여기에 이미지 설명을 삽입하세요.

H, S 및 V는 디지털 영역을 표시하기 위한 임계값을 설정합니다.

여기에 이미지 설명을 삽입하세요.

결과 이미지를 이진화

# 转换为灰度图像
gray = cv2.cvtColor(result1, cv2.COLOR_BGR2GRAY)
# cv2.imshow('gray', gray)
# cv2.waitKey(0)
#
#二值化处理
_, binary = cv2.threshold(gray, 50, 255, cv2.THRESH_BINARY)

# 
# cv2.imshow("Contours", binary)
# cv2.waitKey(0)

그레이스케일 처리 및 이진화 후의 결과:

여기에 이미지 설명을 삽입하세요.
여기에 이미지 설명을 삽입하세요.

이미지에 중복된 부분이 포함되어 있고 형태학적 연산(침식)을 사용하여 계속 처리되고 있음을 알 수 있습니다. 여기서는 x 방향과 y 방향의 부식 작업이 각각 수행됩니다.

# 自定义 1x3 的核进行 x 方向的膨胀腐蚀
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 3))
xtx_img = cv2.dilate(binary, kernel, iterations=3)
xtx_img = cv2.erode(xtx_img, kernel, iterations=3)#y 腐蚀去除碎片

# cv2.imshow("Contours", xtx_img)
# cv2.waitKey(0)

# 自定义 3x1 的核进行 y 方向的膨胀腐蚀
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 1))
xtx_img = cv2.dilate(xtx_img, kernel, iterations=3)#x 膨胀回复形态
xtx_img = cv2.erode(xtx_img, kernel, iterations=3)#x 腐蚀去除碎片
#
# cv2.imshow("Contours", xtx_img)
# cv2.waitKey(0)

x 방향의 부식 결과:

여기에 이미지 설명을 삽입하세요.

y 방향의 부식 결과

여기에 이미지 설명을 삽입하세요.

그런 다음 opencv의 기본 기능이 흰색 윤곽선을 찾기 때문에 모든 윤곽선을 찾아야 하므로 이진화된 결과를 반전해야 합니다. 그런 다음 이 기능을 사용하여 모든 흰색 윤곽선을 얻습니다. 결과는 예상대로 4입니다.

# 将二值化图像取反
binary_inv = cv2.bitwise_not(xtx_img)
# cv2.imshow("Contours", binary_inv)
# cv2.waitKey(0)
#所有轮廓的列表contours和分层信息
contours, hierarchy = cv2.findContours(binary_inv, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 打印轮廓数量

print("轮廓数量:", len(contours))

여기에 이미지 설명을 삽입하세요.

윤곽선을 잡은 후 원본 이미지 위에 그려서 살펴보세요.

img_contour = cv2.drawContours(result, contours, -1, (0, 255, 0), 1)

# cv2.imshow("img_contour", img_contour)
# cv2.waitKey(0)

다음과 같은 느낌이 듭니다.

여기에 이미지 설명을 삽입하세요.

등고선을 얻은 후 후속 인식 시 혼란을 피하기 위해 x축 좌표에 따라 정렬하고 여기에서 각 숫자를 별도로 꺼냅니다.

# 存储所有轮廓的图像
plate_imgs = []

# 获取所有轮廓的x坐标
x_coordinates = []
for contour in contours:
    x, y, w, h = cv2.boundingRect(contour)
    x_coordinates.append(x)

# 将轮廓按照x坐标排序
sorted_contours = [contours[i] for i in np.argsort(x_coordinates)]

이 숫자를 얻은 후에는 이 숫자가 어떤 숫자인지 식별해야 합니다. 여기서는 분류 작업을 사용하여 이러한 숫자를 식별하는 자체 모델을 훈련할 수 있습니다. 여기서는 대학원 연구에서 배운 구조적 유사성을 사용하여 다음을 수행합니다. , 인식할 수 있는 한 구조적 유사도 값은 0~1 사이이며, 클수록 두 이미지가 유사하다는 것을 의미하므로(대략 이해가 가능) 숫자의 사진을 미리 저장해 두고, 그리고 사진의 이름은 숫자와 일치하므로 식별 후 사진의 이름을 직접 인쇄하여 숫자가 무엇인지 알 수 있습니다. 이 LED에는 숫자 2, 7, 1 세 개만 있기 때문입니다. 화면에서는 식별을 위해 이 세 장의 사진만 저장합니다. , 앞의 첫 번째 상자 영역은 인식되지 않는 것은 이 숫자 외에도 CO, 메탄 등 인식되지 않는 것들이 있기 때문입니다. 여기. 분할된 각 번호와 폴더에 미리 저장된 번호의 구조적 유사성을 비교하고, 구조적 유사성이 가장 높은 번호와 파일명을 유지하여 최종적으로 인식 결과를 얻습니다.

# 初始化最高相似度和对应文件名
max_sim = -1
max_sim_filename = ''

# 按x轴逐个绘制
for i, contour in enumerate(sorted_contours):
    x, y, w, h = cv2.boundingRect(contour)
    cv2.rectangle(xtx_img, (x, y), (x + w, y + h), (0, 255, 0), 1)
    plate_img1 = binary_inv[y:y + h, x:x + w].copy()
    # 生成文件名,加上时间戳
    # filename = f"saved_image_{i}_{int(time.time())}.jpg"
    # cv2.imwrite(filename, plate_img1)
    # cv2.imshow("img_contour", plate_img1)
    # cv2.waitKey(0)
    plate_img = cv2.resize(plate_img1, (22, 60))
    # cv2.imshow("img_contour", plate_img)
    # cv2.waitKey(0)

    max_sim = 0
    # 遍历result文件夹下的所有文件
    for filename in os.listdir('Desktop\\count\\result2'):
        if filename.endswith('.png'):
            # 读取图像并resize//C:\\Users\\12561\\Desktop\\count\\result\\
            img2 = cv2.imread(os.path.join('Desktop\\count\\result2', filename), cv2.IMREAD_GRAYSCALE)
            img2 = cv2.resize(img2, (22, 60))

            # 计算相似度
            similarity = ssim(plate_img, img2)
            print(similarity, end=' ')
            # 如果相似度更高,则更新最高相似度和对应文件名
            if similarity > max_sim:
                max_sim = similarity
                max_sim_filename = os.path.splitext(filename)[0]  # 去掉文件后缀
    #if max_sim_filename == '_':
        #max_sim_filename = '.'
    # print(max_sim_filename, end='')
    print(f"{
      
      max_sim_filename} ({
      
      max_sim:.5f})", end=' ')
    print()

최종 실행 결과는 각 이미지의 구조적 유사도 값이 가장 큰 값을 출력하며, 처리 속도도 매우 빨라 CPU 하에서 빠르게 처리할 수 있다.

여기에 이미지 설명을 삽입하세요.

전체 프로젝트 코드:

import cv2
import numpy as np
import time
import os
from skimage.metrics import structural_similarity as ssim


img = cv2.imread('304.jpg')
start = time.time()
new_size = (640, 400)
img = cv2.resize(img, new_size)
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
mask = np.zeros(hsv_img.shape[:2], dtype=np.uint8)
mask[(hsv_img[:,:,0] >= 130) & (hsv_img[:,:,0] <= 255) & (hsv_img[:,:,1] >= 0) &
(hsv_img[:,:,1] <= 255) & (hsv_img[:,:,2] >= 0) & (hsv_img[:,:,2] <= 90)] = 1
result = cv2.bitwise_and(img, img, mask=mask)

# cv2.imshow("Contours", result)
# cv2.waitKey(0)

gray = cv2.cvtColor(result,cv2.COLOR_BGR2GRAY)

# cv2.imshow("Contours", gray)
# cv2.waitKey(0)


#边缘检测
#转灰度,做单通道计算比较节省时间
edges = cv2.Canny(gray,50,150,apertureSize = 3)

#所有轮廓的列表contours和分层信息
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# print("轮廓数量:", len(contours))

img_copy = img.copy() # 复制原图,避免在原图上直接画框

for cnt in contours:
    x, y, w, h = cv2.boundingRect(cnt) # 获取轮廓的边界矩形
    area = w * h
    if area > 10000:
        x, y, w, h = cv2.boundingRect(cnt)
        area = w * h
        # print("xywh", x, y, w, h)
        # print("矩形面积:", area)
        roi = img_copy[y:y + h + 26, x:x + w+2]
        # cv2.imshow("ROI", roi)
        # cv2.waitKey(0)
        # print("矩形面积:", area)
        # cv2.rectangle(img_copy, (x, y), (x + w, y + h + 25), (0, 255, 0), 1)  # 画矩形框,绿色,宽度为2

# cv2.imshow("ROI", roi)
# cv2.waitKey(0)

# 转换为灰度图像
gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
# 高斯滤波
blur = cv2.GaussianBlur(gray, (3, 3), 0)

# 边缘检测
edges = cv2.Canny(gray, 50, 255)
# cv2.imshow("ROI", edges)
# cv2.waitKey(0)

# # 获得轮廓信息
# contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
#
# # 绘制最小外接矩形
# for cnt in contours:
#     rect = cv2.minAreaRect(cnt)
#     box = cv2.boxPoints(rect)
#     box = np.int0(box)
#
#     cv2.drawContours(roi, [box], 0, (0, 255, 0), 1)
#
#     # 获取矩形的四个顶点坐标
#     rect_points = np.int0(cv2.boxPoints(rect))
#     # print("矩形的四个顶点坐标:", rect_points)
#
# # cv2.imshow('Contours', roi)
# # cv2.waitKey(0)
#
# # 定义原图像的四个角点坐标
# src = np.float32([[-8,61],[186 , -3],[ 23, 156], [218 , 91]])
#
# # 定义输出图像的四个角点坐标
# dst = np.float32([[0, 0],[200, 0],[0, 100],[200, 100]])
#
# # 计算变换矩阵
# M = cv2.getPerspectiveTransform(src, dst)
#
# # 应用变换矩阵
# result = cv2.warpPerspective(roi, M, (200, 100))
#
#
# 显示图像
# cv2.imshow('Contours', result)
# cv2.waitKey(0)

#
# 获取白色像素点坐标
coordinates = np.column_stack(np.where(edges == 255))

# # 打印白色像素点坐标
# print(coordinates)

# 在x轴方向上找到最小和最大的两个坐标
x_min = coordinates[np.argmin(coordinates[:,0])].copy()
x_min[0], x_min[1] = x_min[1], x_min[0]
x_max = coordinates[np.argmax(coordinates[:,0])].copy()
x_max[0], x_max[1] = x_max[1], x_max[0]

# 在y轴方向上找到最小和最大的两个坐标
y_min = coordinates[np.argmin(coordinates[:,1])].copy()
y_min[0], y_min[1] = y_min[1], y_min[0]
y_max = coordinates[np.argmax(coordinates[:,1])].copy()
y_max[0], y_max[1] = y_max[1], y_max[0]

# # # 打印最小和最大的两个坐标
# print('x_min:', x_min)
# print('x_max:', x_max)
# print('y_min:', y_min)
# print('y_max:', y_max)


# 定义原图像的四个角点坐标
src = np.float32([y_min,x_min,x_max, y_max])

# 定义输出图像的四个角点坐标
dst = np.float32([[0, 0],[200, 0],[0, 100],[200, 75]])

# 计算变换矩阵
M = cv2.getPerspectiveTransform(src, dst)

# 应用变换矩阵
result = cv2.warpPerspective(roi, M, (200, 75))
#显示图像
# cv2.imshow('result', result)
# cv2.waitKey(0)

# gray = cv2.cvtColor(result, cv2.COLOR_BGR2GRAY)
# cv2.imshow('hsv_img', gray)
# cv2.waitKey(0)

hsv_img = cv2.cvtColor(result, cv2.COLOR_BGR2HSV)
# cv2.imshow('hsv_img', hsv_img)
# cv2.waitKey(0)
mask = np.zeros(hsv_img.shape[:2], dtype=np.uint8)
mask[(hsv_img[:,:,0] >= 0) & (hsv_img[:,:,0] <= 255) & (hsv_img[:,:,1] >= 0) &
(hsv_img[:,:,1] <= 255) & (hsv_img[:,:,2] >= 0) & (hsv_img[:,:,2] <= 100)] = 1
result1 = cv2.bitwise_and(hsv_img, hsv_img, mask=mask)

# cv2.imshow("Contours", result1)
# cv2.waitKey(0)

# 转换为灰度图像
gray = cv2.cvtColor(result1, cv2.COLOR_BGR2GRAY)
# cv2.imshow('gray', gray)
# cv2.waitKey(0)
#
#二值化处理
_, binary = cv2.threshold(gray, 50, 255, cv2.THRESH_BINARY)

#
# cv2.imshow("Contours", binary)
# cv2.waitKey(0)

# 自定义 1x3 的核进行 x 方向的膨胀腐蚀
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 3))
xtx_img = cv2.dilate(binary, kernel, iterations=3)
xtx_img = cv2.erode(xtx_img, kernel, iterations=3)#y 腐蚀去除碎片

# cv2.imshow("Contours", xtx_img)
# cv2.waitKey(0)

# 自定义 3x1 的核进行 y 方向的膨胀腐蚀
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 1))
xtx_img = cv2.dilate(xtx_img, kernel, iterations=3)#x 膨胀回复形态
xtx_img = cv2.erode(xtx_img, kernel, iterations=3)#x 腐蚀去除碎片
#
# cv2.imshow("Contours", xtx_img)
# cv2.waitKey(0)

# 将二值化图像取反
binary_inv = cv2.bitwise_not(xtx_img)
# cv2.imshow("Contours", binary_inv)
# cv2.waitKey(0)
#所有轮廓的列表contours和分层信息
contours, hierarchy = cv2.findContours(binary_inv, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 打印轮廓数量

print("轮廓数量:", len(contours))

# # 创建一个空图像,与原图像大小和通道数相同
# contours_img = np.zeros_like(result)

# 绘制轮廓
img_contour = cv2.drawContours(result, contours, -1, (0, 255, 0), 1)

# cv2.imshow("img_contour", img_contour)
# cv2.waitKey(0)

# 存储所有轮廓的图像
plate_imgs = []

# 获取所有轮廓的x坐标
x_coordinates = []
for contour in contours:
    x, y, w, h = cv2.boundingRect(contour)
    x_coordinates.append(x)

# 将轮廓按照x坐标排序
sorted_contours = [contours[i] for i in np.argsort(x_coordinates)]

# 初始化最高相似度和对应文件名
max_sim = -1
max_sim_filename = ''

# 按x轴逐个绘制
for i, contour in enumerate(sorted_contours):
    x, y, w, h = cv2.boundingRect(contour)
    cv2.rectangle(xtx_img, (x, y), (x + w, y + h), (0, 255, 0), 1)
    plate_img1 = binary_inv[y:y + h, x:x + w].copy()
    # 生成文件名,加上时间戳
    # filename = f"saved_image_{i}_{int(time.time())}.jpg"
    # cv2.imwrite(filename, plate_img1)
    # cv2.imshow("img_contour", plate_img1)
    # cv2.waitKey(0)
    plate_img = cv2.resize(plate_img1, (22, 60))
    # cv2.imshow("img_contour", plate_img)
    # cv2.waitKey(0)

    max_sim = 0
    # 遍历result文件夹下的所有文件
    for filename in os.listdir('Desktop\\count\\result2'):
        if filename.endswith('.png'):
            # 读取图像并resize//C:\\Users\\12561\\Desktop\\count\\result\\
            img2 = cv2.imread(os.path.join('Desktop\\count\\result2', filename), cv2.IMREAD_GRAYSCALE)
            img2 = cv2.resize(img2, (22, 60))

            # 计算相似度
            similarity = ssim(plate_img, img2)
            print(similarity, end=' ')
            # 如果相似度更高,则更新最高相似度和对应文件名
            if similarity > max_sim:
                max_sim = similarity
                max_sim_filename = os.path.splitext(filename)[0]  # 去掉文件后缀
    if max_sim_filename == '_':
        max_sim_filename = '.'
    # print(max_sim_filename, end='')
    print(f"{
      
      max_sim_filename} ({
      
      max_sim:.5f})", end=' ')
    print()
    # print(max_sim_filename)
    # cv2.imwrite("C:\\Users\\12561\\Desktop\\count\\result\\plate_img1.png", dilation)  # 保存结果为 PNG 文件
    # cv2.imshow("Contours", plate_img1)
    # cv2.waitKey(0)

print()
end = time.time();
print("time =",end-start)

프로젝트의 많은 임계값은 특수 그림에 따라 특별히 설정되어야 합니다.

전체 단계:

  • 윤곽 감지
  • 원근교정
  • 문자 분할
  • 문자 인식

Guess you like

Origin blog.csdn.net/qq_44902386/article/details/130595901