使用 OpenVINO™ 工具組的智慧電錶電錶掃描:AI 物件偵測與分割

查看所有邊緣 AI 參考文件

author-image

作者

概述

在本教學課程中,瞭解如何透過 upyter* Notebook 使用 OpenVINO™ 工具組,建立智慧電錶掃描應用程式。查看實際評測基準資料後,您可以執行自己所設的實際評測基準。

透過 OpenVINO 工具組,您可以使用物件偵測、適用於數位電錶的 OCR,以及適用於指針型電錶的分割,開發數位讀取的工業電錶專用 AI 應用程式。OpenVINO 工具組可大幅縮短處理輸入資料和產生預測輸出的時間, 加速決策,同時提升系統互動效率, 所以您可以使用電腦視覺讀取電錶、減少錯誤,並實現更高的準確度。

在能源使用等領域,人工檢查類比電錶並不精確,但升級為數位電錶可能所費不貲。各家公司可以使用這個應用程式的即時資料,預先識別需要改善和安全的區域,甚至透過異常使用模式,偵測出可能的設備故障。

此外,這個解決方案可以應用於物件偵測與分割相關的類比資料轉換為數位資料。

預先要求

步驟 1:複製存放庫

若要複製智慧電錶電錶掃描存放庫至系統,請使用以下命令:

git clone -b recipes https://github.com/openvinotoolkit/openvino_notebooks.git

這個命令會複製存放庫至資料夾「openvino_notebooks」。接著,瀏覽至資料夾:

cd openvino_notebooks/recipes/meter_reader

這個應用程式使用 Python 設定這個專案的虛擬環境。如果您未安裝虛擬環境套件,請執行以下操作:

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install python3-ven

如果您的裝置搭載 Intel 內建顯示卡並可啟用推斷,請安裝 oneAPI Level Zero 與 OpenCL™ 驅動程式適用的 Intel® 顯示晶片運算時間。Ubuntu* 20.04 的命令:

sudo apt-get install intel-opencl-icd

接著,準備虛擬環境。

步驟 2:建立並啟用虛擬環境

為避免影響系統全域,最佳的做法是在專屬環境隔離 Python 專案。若要設定虛擬環境,請開啟終端或命令提示字元,然後瀏覽至您要建立環境的目錄。接著,執行以下命令,建立新的虛擬環境: 

如果是 UNIX* 型作業系統(例如 Linux* 或 macOS*),請使用:

python3 -m venv venv

如果是 Windows*,請使用:

python -m venv venv

這個命令會在目前的資料夾中,建立新的虛擬環境「venv」。接著,啟用剛建立的環境。使用的命令因作業系統而異。 

如果是 UNIX 型作業系統(例如 Linux 或 macOS),請使用:

source venv/bin/activate

如果是 Windows,請使用:

 venvScriptsactivate

這個命令會啟用虛擬環境,並變更命令介面的提示。

步驟 3:安裝要求

若要執行智慧電錶掃描應用程式,請安裝幾個依賴項。這些依賴項列於所附的要求檔案,並可使用 Python 套件安裝程式安裝。 

若要安裝必要的 Python 程式庫(包括 OpenVINO 工具組),請使用以下命令:

python -m pip install --upgrade pip 

pip install -r requirements.txt

已安裝所有依賴項與要求。接著,請準備模型並設定應用程式。

步驟 4:準備模型

電錶讀取器解決方案的模型包含偵測與分割模型。您可以使用 PyTorch*、TensorFlow* 等 AI 訓練架構訓練偵測與分割模型。在本範例中,請使用以下命令,從 PaddlePaddle* 下載預先訓練的模型:

cd model

sudo sh ./download_pdmodel.sh

步驟 5:設定智慧電錶電錶掃描應用程式

這個專案的測試圖片包含不同類型的工業電錶,所以您必須預先定義這些電錶的參數,才能計算最終讀數。這些參數包括電錶的範圍、刻度區間值與單位,並可參考以下設定:

"meter_config": [

 {

 "scale_interval_value": 0.5,

 "range": 25.0,

 "unit": "(MPa)"

 },

 {

 "scale_interval_value": 0.05,

 "range": 1.6,

 "unit": "(MPa)"

 }

	],

除了電錶設定,模型的參數也需定義,包括模型檔案路徑、輸入形式、標準化參數和色彩格式。這些參數會在每個模型的操作步驟實作:

"model_config": {

 "detector": {

 "model_path": "./model/meter_det_model/model.pdmodel",

 "device": "CPU",

 "input_shape": 608,

 "model_shape": {"image": [1, 3, 608, 608], "im_shape": [1, 2], "scale_factor": [1, 2]},

 "scale": 255,

 "color_format": "bgr",

 "mean": [

 0.485,

 0.456,

 0.406

 ],

 "std": [

 0.229,

 0.224,

 0.225

 ]

 },

 "segmenter": {

 "model_path": "./model/meter_seg_model/model.pdmodel",

 "device": "CPU",

 "batch_size": 2,

 "input_shape": 512,

 "model_shape": {"image": [-1, 3, 512, 512]},

 "scale": 255,

 "color_format": "bgr",

  "mean": [

 0.5,

 0.5,

 0.5

 ],

 "std": [

 0.5,

 0.5,

 0.5

 ]

 }

 } 

您可以在「config/config.json」資料夾找到這些參數。如果是使用不同電錶的其他案例,請因應電錶調整這些值。

步驟 6:瞭解預先處理與後製

類比電錶讀取可以細分預先處理(電錶偵測或分割的圖片格式化)、後製(處理資料並輸出最終電錶讀數)。

應用程式一開始會處理圖片。這個流程包括配置轉置、標準化,以及調整圖片為符合模型的輸入要求。接著圖片即可搭配物件偵測模型使用,目標是偵測圖片中所有的電錶。

def detect(self, input):  

 # Prepare the input data for meter detection model 

 im_shape = np.array([[self.input_shape, self.input_shape]]).astype('float32') 

 scale_factor = np.array([[1, 2]]).astype('float32') 

 input_image = self.det_preprocess(input, self.input_shape) 

 inputs_dict = {'image': input_image, "im_shape": im_shape, "scale_factor": scale_factor} 

 # Run meter detection model 

 det_results = self.det_compiled_model(inputs_dict)[self.det_output_layer] 

 # Filter out the bounding box with low confidence 

 filtered_results = self.filter_bboxes(det_results, self.score_threshold) 

 # Prepare the input data for meter segmentation model 

 scale_x = input.shape[1] / self.input_shape * 2 

 scale_y = input.shape[0] / self.input_shape 

 # Create the individual picture for each detected meter 

 roi_imgs, self.loc = self.roi_crop(input, filtered_results, scale_x, scale_y)  

 roi_imgs, resize_imgs = self.roi_process(roi_imgs, self.METER_SHAPE) 

 # Create the pictures of detection results 

 roi_stack = np.hstack(resize_imgs) 

 cv2.imwrite("./data/detection_results.jpg", roi_stack) 

 return roi_imgs 

同時篩除不可靠的偵測結果,並返回相關的重點區域(ROI)。然後裁切這些圖片,進一步分割處理。

def roi_crop(image, results, scale_x, scale_y): 

 roi_imgs = [] 

 loc = [] 

 for result in results: 

 bbox = result[2:] 

 xmin, ymin, xmax, ymax = [int(bbox[0] * scale_x), int(bbox[1] * scale_y), int(bbox[2] * scale_x), int(bbox[3] * scale_y)] 

 sub_img = image[ymin:(ymax + 1), xmin:(xmax + 1), :] 

 roi_imgs.append(sub_img) 

 loc.append([xmin, ymin, xmax, ymax]) 

 return roi_imgs, loc 

在這個案例中,相片中可能偵測到的電錶數量是不定。換言之,分割模型的輸入形式會因批次大小有所不同, 亦即動態形式。處理不定大小輸入的方法有幾種,例如填補、模型重設、多個預先編譯的模型。 

OpenVINO 工具組的優勢包含可直接載入動態形式的資料至 OpenVINO 執行階段。如果可以預測圖片中電錶的最大數量,十分建議您透過範圍尺寸,設定輸入資料大小的上限,因為記憶體使用量較低、推斷效能更佳。

def segment(self, input):  

 seg_results = list() 

 num_imgs = len(input) 

 image_list = list() 

 # Run meter segmentation model on all detected meters 

 for i in range(0, num_imgs, self.seg_batch_size): 

 batch = input[i : min(num_imgs, i + self.seg_batch_size)] 

 seg_result = self.seg_compiled_model({"image": np.array(batch)})[self.seg_output_layer] 

 seg_results.extend(seg_result) 

 results = [] 

 for i in range(len(seg_results)): 

 results.append(np.argmax(seg_results[i], axis=0))  

 seg_results = self.erode(results, self.erode_kernel) 

 # Create the pictures of segmentation results 

 for i in range(len(seg_results)): 

  image_list.append(self.segmentation_map_to_image( 

	 seg_results[i], self.COLORMAP)) 

 # Create the pictures of segmentation results 

 mask_stack = np.hstack(image_list) 

 cv2.imwrite("./data/segmentation_results.jpg", cv2.cvtColor(mask_stack, cv2.COLOR_RGB2BGR)) 

 return seg_results 

分割後,即完成預先處理並可在後製輸入結果。偵測並分割電錶後,請務必處理最終的電錶讀數並返回。這包括二值化刻度和指針為比例尺地圖中可計算的指針位置,並傳回最終電錶讀數。

def postprocess(self, input): 

 # Find the pointer location in scale map and calculate the meters reading  

 rectangle_meters = self.circle_to_rectangle(input) 

 line_scales, line_pointers = self.rectangle_to_line(rectangle_meters) 

 binaried_scales = self.mean_binarization(line_scales) 

 binaried_pointers = self.mean_binarization(line_pointers) 

 scale_locations = self.locate_scale(binaried_scales) 

 pointer_locations = self.locate_pointer(binaried_pointers) 

 pointed_scales = self.get_relative_location(scale_locations, pointer_locations) 

 meter_readings = self.calculate_reading(pointed_scales) 

另外,後製管道可如下視覺化: 

管道流程圖

 

 

步驟 7:執行智慧電錶掃描應用程式

瞭解預先處理與後製後,您可以立即執行應用程式,並取得最終電錶讀數。

若要載入並編譯電錶偵測與電錶分割的深度學習模型,請使用以下程式碼:

# Loading and compiling for meter detection: 

self.det_model = ie_core.read_model(det_model_path) 

self.det_model.reshape(det_model_shape) 

self.det_compiled_model = ie_core.compile_model( 

model=self.det_model, device_name=self.config["model_config"] 

	["detector"]["device"]) 

self.det_output_layer = self.det_compiled_model.output(0) 

 

# Loading and compiling for meter segmentation: 

 self.seg_model = ie_core.read_model(seg_model_path) 

self.seg_model.reshape(seg_model_shape) 

self.seg_compiled_model = ie_core.compile_model( 

model=self.seg_model, device_name=self.config["model_config"] 

	["segmenter"]["device"]) 

self.seg_output_layer = self.seg_compiled_model.output(0) 

注意在執行推斷的 device_name 中,您可以指定慣用的裝置或設為自動,讓 OpenVINO 工具組從可用的硬體裝置,代為選擇最佳推斷裝置。 

若要執行應用程式,請使用以下命令。請務必以您的設定檔案和測試圖片,取代「config/config.json」和「data/test.jpg」。結果的圖片會匯出至同一個資料夾,作為測試圖片。

python main.py -i data/test.jpg -c config/config.json -t "analog"

執行應用程式所需的輸入參數: 

  • -i:輸入圖片的路徑,即即時攝影機拍攝的工業電錶圖片。 
  • -c:設定檔案的路徑,包括模型推斷、預先處理與後製步驟的參數。 
  • -t:選擇類比數位,實作類比或數位工業電錶的自動電錶讀取。 

完成後,您會獲得電錶讀數。

步驟 8:使用 Benchmark_App 的效能評測基準

若要評估電錶讀取器管道模型的效能,請使用 OpenVINO 工具組 Benchmark_App。這個步驟提供模型實際效能的見解,方便您規劃部署。

新訓練的 YOLO* v8l 模型最好使用 Ultralytics 架構 (GPU 目前不支援 PPYOLO v2)。您可以從 GitHub* 的同一個存放庫下載 Ultralytics 架構。 

若要使用 YOLO v8l 管道執行這個應用程式,請使用以下命令,切換預設設定檔案為 ./config/yolov8.json

python main.py -i data/test.jpg -c config/yolov8.json 

  -t "analog"

若要執行 Intel® Developer Cloud 或本機電腦的 Benchmark_App,請參考以下範例:

!python benchmark_app -m ./model/yolov8.onnx  

	 -shape [1, 3, 608, 608]  

            -d $DEVICE  

            -niter 50  

            -hint $PERF_HINT  

            --report_type detailed_counters  

            --report_folder ${SAMPLEPATH}/${OUTPUT_FILE}/${JOB_ID} 

 

!python benchmark_app -m ./model/deeplabv3+.onnx  

	 -shape [1, 3, 512, 512]  

            -d $DEVICE  

            -niter 50  

            -hint $PERF_HINT  

            --report_type detailed_counters  

            --report_folder ${SAMPLEPATH}/${OUTPUT_FILE}/${JOB_ID}

這個階段測試了 Ultralytics 管道訓練的 YOLO v8l 電錶偵測效能,以及 PyTorch 架構訓練的 DeepLabv3+ 電錶分割效能。

結語

您已瞭解如何使用 OpenVINO 建立智慧電錶掃描應用程式,利用電腦視覺偵測和分割物件讀取類比工業電錶。這個方法提供可靠、可擴充的方案替代手動偵測,並改善準確度、時間效率與安全。 

在依靠類比電錶的行業(例如能源或製造業),有大量電錶需要持續檢查讀數,才能確保持續作業和安全。這些電錶類型五花八門,所在位置更是分散,且工作環境惡劣。

利用 AI 推斷讓建立的智慧應用可以執行視覺資料即時分析,摘錄出重要的見解並改善企業營運。OpenVINO 可確保這個流程高效能且低延遲。

如果您有任何問題或意見,請加入 GitHubIntel 社群支援頻道的討論。若要進一步瞭解如何使用 OpenVINO 工具組開發,請參閱這份文件。 

 

如需更詳細的效能評測資訊,請前往 GitHub