本文延續上兩篇文章,新增印出圖像中OCR的面積及位置,與驗證連通域分析計算的面積是否正確,利用cv2.countNonZero
來計算區域內非零的元素,因圖像OCR在連通域分析前就需轉換成黑底白字,剛好可利用此函數來計算面積。
import cv2
import numpy as np
def read_posion(img):
'''
輸入背景黑色,物件白色的圖
'''
num_labels, labels, stats, _ = cv2.connectedComponentsWithStats(img, connectivity=8)
components = []
# boxes_data = []
for i in range(1, num_labels): # 跳過背景
x, y, w, h, area = stats[i]
if area >100:
components.append((x, y, w, h,area))
return components
img = cv2.imread(f'F:/python/opencv/chars_training_01.png')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Otsu's 方法進行自動二值化
_, binary_image = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
# 需讓OCR轉換成白色字體才能用連通域分析
binary_image = 255 - binary_image
box = read_posion(binary_image)
# 設置文字的相關屬性
font = cv2.FONT_HERSHEY_SIMPLEX # 字體類型
font_scale = 0.5 # 字體大小
color = (0, 0, 0) # 文字顏色 (B, G, R),這裡是黑色
thickness = 1 # 文字粗細
for i,data in enumerate(box):
x,y,w,h,area = data
#印出OCR 位置,高寬
print(f'第{i}個OCR,x:{x},y:{y},h:{h},w:{w},area:{area}')
cv2.rectangle(img,(x,y), (x+w,y+h), (0,0,255), 1)
area_1 = cv2.countNonZero(binary_image[y:y+h,x:x+w]) # 擷取與OCR一樣的位置計算白色面積
print(f'第{i}個OCR_test,x:{x},y:{y},h:{h},w:{w},area:{area_1}')
# 在圖像上繪製數字
cv2.putText(img, str(area_1), (x - 10, y - 10), font, font_scale, color, thickness)
# 顯示結果圖像
cv2.imshow('reuslt', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
兩者計算結果幾乎一模一樣,只有略差1~2pixl,可以忽略不計。