應(yīng)項目要求需要基于cpu的LED數(shù)字識別,為了滿足需求,使用傳統(tǒng)方法進行實驗。識別傳感器中顯示的數(shù)字。因此使用opencv的函數(shù)做一些處理,實現(xiàn)功能需求。
首先讀取圖像,因為我沒想大致得到LED屏幕的區(qū)域,因此將RGB轉(zhuǎn)換為HSV空間,并分別設(shè)置H、S和V的閾值,讓該區(qū)域顯現(xiàn)出來??梢钥吹酱a中進行了resize操作,這個操作不是必須的,具體H、S和V的數(shù)值根據(jù)具體的圖像自行設(shè)置。
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)
原圖處理后結(jié)果:
接下來需要檢測輪廓信息,因此進行灰度化處理。
gray = cv2.cvtColor(result,cv2.COLOR_BGR2GRAY)
處理后結(jié)果:
使用Canny做輪廓檢測,并保存所有輪廓信息,將所有輪廓信息框選出來,因為框選區(qū)域矩形,所以采用面積策略刪掉小塊區(qū)域面積只顯示大塊的面積。
#轉(zhuǎn)灰度,做單通道計算比較節(jié)省時間
edges = cv2.Canny(gray,50,150,apertureSize = 3)
#所有輪廓的列表contours和分層信息
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# print("輪廓數(shù)量:", len(contours))
img_copy = img.copy() # 復(fù)制原圖,避免在原圖上直接畫框
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)
該圖為框選的所有輪廓
做面積閾值處理后得到液晶屏幕區(qū)域的矩形框:
后邊拿出框選的區(qū)域做處理就行了,直接從原圖中拿出框選區(qū)域做灰度處理,并作邊緣檢測,邊緣檢測前做高斯處理,去除一下噪聲。
gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY)
# 高斯濾波
blur = cv2.GaussianBlur(gray, (3, 3), 0)
# 邊緣檢測
edges = cv2.Canny(gray, 50, 255)
得到框選區(qū)域并進行邊緣檢測結(jié)果:
到這里已經(jīng)檢測到LED屏的輪廓了,可以看出我們的拍攝得到的框是斜的,因此需要進行透視校正,而透視校正需要得到四個頂點的坐標(biāo)值,這里我嘗試了兩種方法:一、繪制最小外接矩形;二、獲取白色像素點坐標(biāo)(這里自己思考的一種策略,分別按照x軸和y軸找,分別找x軸白色邊緣最小值和最大值坐標(biāo),y軸白色邊緣最小值和最大值坐標(biāo))
一、使用最小外接矩形做透視校正
# 獲得輪廓信息
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)
# 獲取矩形的四個頂點坐標(biāo)
rect_points = np.int0(cv2.boxPoints(rect))
# print("矩形的四個頂點坐標(biāo):", rect_points)
# cv2.imshow('Contours', roi)
# cv2.waitKey(0)
# 定義原圖像的四個角點坐標(biāo)
src = np.float32([[-8,61],[186 , -3],[ 23, 156], [218 , 91]])
# 定義輸出圖像的四個角點坐標(biāo)
dst = np.float32([[0, 0],[200, 0],[0, 100],[200, 100]])
# 計算變換矩陣
M = cv2.getPerspectiveTransform(src, dst)
# 應(yīng)用變換矩陣
result = cv2.warpPerspective(roi, M, (200, 100))
顯示圖像
cv2.imshow('Contours', result)
cv2.waitKey(0)
得到最小外接矩形:
透視校正結(jié)果:
從最小外接矩形可以看出框選的區(qū)域除了LED屏幕還有一些其他區(qū)域影響,這邊后邊的實驗中發(fā)現(xiàn),這些多余地方會影響后序的實驗準(zhǔn)確性。
二、分別獲取x軸和y軸白色像素點坐標(biāo)
# 獲取白色像素點坐標(biāo)
coordinates = np.column_stack(np.where(edges == 255))
# # 打印白色像素點坐標(biāo)
# print(coordinates)
# 在x軸方向上找到最小和最大的兩個坐標(biāo)
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軸方向上找到最小和最大的兩個坐標(biāo)
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]
# # # 打印最小和最大的兩個坐標(biāo)
# print('x_min:', x_min)
# print('x_max:', x_max)
# print('y_min:', y_min)
# print('y_max:', y_max)
# 定義原圖像的四個角點坐標(biāo)
src = np.float32([y_min,x_min,x_max, y_max])
# 定義輸出圖像的四個角點坐標(biāo)
dst = np.float32([[0, 0],[200, 0],[0, 100],[200, 100]])
# 計算變換矩陣
M = cv2.getPerspectiveTransform(src, dst)
# 應(yīng)用變換矩陣
result = cv2.warpPerspective(roi, M, (200, 100))
#顯示圖像
# cv2.imshow('result', result)
# cv2.waitKey(0)
按照思路找x軸和y軸最大最小值對于的白色像素點坐標(biāo)并繪制框:
透視校正后:
將透視校正后的圖像區(qū)域繼續(xù)進行RGB轉(zhuǎn)換HSV,并設(shè)置閾值使數(shù)字區(qū)域更好的顯示出來
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轉(zhuǎn)換HSV:
H、S和V設(shè)置閾值使數(shù)字區(qū)域顯示:
將得到的圖像進行二值化處理
# 轉(zhuǎn)換為灰度圖像
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)
灰度處理和二值化后的結(jié)果:
可以看到圖像中含有多余的部分,繼續(xù)使用形態(tài)學(xué)操作(腐蝕)處理。這里分別進行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 膨脹回復(fù)形態(tài)
xtx_img = cv2.erode(xtx_img, kernel, iterations=3)#x 腐蝕去除碎片
#
# cv2.imshow("Contours", xtx_img)
# cv2.waitKey(0)
x方向腐蝕結(jié)果:
y方向腐蝕結(jié)果
然后需要找到所有的輪廓,因為opencv中默認(rèn)函數(shù)找到的是白色輪廓,因此需要將得到的二值化結(jié)果取反操作。再使用函數(shù)獲取所有的白色輪廓。運行出來的結(jié)果符合預(yù)期,確實是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)
# 打印輪廓數(shù)量
print("輪廓數(shù)量:", len(contours))
得到輪廓后繪制在原圖上看一下
img_contour = cv2.drawContours(result, contours, -1, (0, 255, 0), 1)
# cv2.imshow("img_contour", img_contour)
# cv2.waitKey(0)
感覺像那么回事了:
得到輪廓后按照輪廓的x軸坐標(biāo)進行排序,以免后序識別中順序亂了,從這每個數(shù)字就被我們單獨拿出來了。
# 存儲所有輪廓的圖像
plate_imgs = []
# 獲取所有輪廓的x坐標(biāo)
x_coordinates = []
for contour in contours:
x, y, w, h = cv2.boundingRect(contour)
x_coordinates.append(x)
# 將輪廓按照x坐標(biāo)排序
sorted_contours = [contours[i] for i in np.argsort(x_coordinates)]
有了這些數(shù)字后,就需要分別識別這些數(shù)字都是數(shù)字幾了,這里可以使用分類任務(wù),訓(xùn)練一個自己的模型識別這些數(shù)字,這里我們采用一種自己研究生方向?qū)W到的結(jié)構(gòu)相似性來做識別,只要能識別出來就行,結(jié)構(gòu)相似性的值在0-1之間,越大說明兩個圖像越像(大概可以這么理解),因此我們提前保存好數(shù)字的圖片,并且圖片的名字分別對應(yīng)數(shù)字的編號,這樣在識別出來后,就直接打印圖片的命名就知道這個數(shù)字是幾了,因為這個LED屏幕中只有2、7、1三個數(shù)字因此我們只保存了這三張圖片,用來識別,至于前邊的第一個框區(qū)域不識別,是因為除過這些數(shù)字外還有CO甲烷等東西,這里沒有做識別。我們分別將分割出來的每個數(shù)字和提前保存到文件夾中的數(shù)字對比結(jié)構(gòu)相似性,保留結(jié)構(gòu)相似性最高的數(shù)字以及文件名最終得到識別結(jié)果。
# 初始化最高相似度和對應(yīng)文件名
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=' ')
# 如果相似度更高,則更新最高相似度和對應(yīng)文件名
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()
最終運行結(jié)果打印了每種圖像的結(jié)構(gòu)相似性值,得到最大的,并且處理速度很快,完全可以在CPU下實現(xiàn)快速處理。
項目完整代碼:
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)
#邊緣檢測
#轉(zhuǎn)灰度,做單通道計算比較節(jié)省時間
edges = cv2.Canny(gray,50,150,apertureSize = 3)
#所有輪廓的列表contours和分層信息
contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# print("輪廓數(shù)量:", len(contours))
img_copy = img.copy() # 復(fù)制原圖,避免在原圖上直接畫框
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)
# 轉(zhuǎn)換為灰度圖像
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)
#
# # 獲取矩形的四個頂點坐標(biāo)
# rect_points = np.int0(cv2.boxPoints(rect))
# # print("矩形的四個頂點坐標(biāo):", rect_points)
#
# # cv2.imshow('Contours', roi)
# # cv2.waitKey(0)
#
# # 定義原圖像的四個角點坐標(biāo)
# src = np.float32([[-8,61],[186 , -3],[ 23, 156], [218 , 91]])
#
# # 定義輸出圖像的四個角點坐標(biāo)
# dst = np.float32([[0, 0],[200, 0],[0, 100],[200, 100]])
#
# # 計算變換矩陣
# M = cv2.getPerspectiveTransform(src, dst)
#
# # 應(yīng)用變換矩陣
# result = cv2.warpPerspective(roi, M, (200, 100))
#
#
# 顯示圖像
# cv2.imshow('Contours', result)
# cv2.waitKey(0)
#
# 獲取白色像素點坐標(biāo)
coordinates = np.column_stack(np.where(edges == 255))
# # 打印白色像素點坐標(biāo)
# print(coordinates)
# 在x軸方向上找到最小和最大的兩個坐標(biāo)
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軸方向上找到最小和最大的兩個坐標(biāo)
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]
# # # 打印最小和最大的兩個坐標(biāo)
# print('x_min:', x_min)
# print('x_max:', x_max)
# print('y_min:', y_min)
# print('y_max:', y_max)
# 定義原圖像的四個角點坐標(biāo)
src = np.float32([y_min,x_min,x_max, y_max])
# 定義輸出圖像的四個角點坐標(biāo)
dst = np.float32([[0, 0],[200, 0],[0, 100],[200, 75]])
# 計算變換矩陣
M = cv2.getPerspectiveTransform(src, dst)
# 應(yīng)用變換矩陣
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)
# 轉(zhuǎn)換為灰度圖像
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 膨脹回復(fù)形態(tài)
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)
# 打印輪廓數(shù)量
print("輪廓數(shù)量:", len(contours))
# # 創(chuàng)建一個空圖像,與原圖像大小和通道數(shù)相同
# 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坐標(biāo)
x_coordinates = []
for contour in contours:
x, y, w, h = cv2.boundingRect(contour)
x_coordinates.append(x)
# 將輪廓按照x坐標(biāo)排序
sorted_contours = [contours[i] for i in np.argsort(x_coordinates)]
# 初始化最高相似度和對應(yīng)文件名
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=' ')
# 如果相似度更高,則更新最高相似度和對應(yīng)文件名
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) # 保存結(jié)果為 PNG 文件
# cv2.imshow("Contours", plate_img1)
# cv2.waitKey(0)
print()
end = time.time();
print("time =",end-start)
項目中很多閾值都需要按照特殊圖片特殊設(shè)置。文章來源:http://www.zghlxwxcb.cn/news/detail-461599.html
總體步驟:文章來源地址http://www.zghlxwxcb.cn/news/detail-461599.html
- 輪廓檢測
- 透視校正
- 字符分割
- 字符識別
到了這里,關(guān)于python中使用opencv LED屏數(shù)字識別(可用做車牌識別,一樣的原理)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!