概要
このチュートリアルでは、Jupyter* 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
インテルのグラフィックス・カードを統合した CPU がある場合、このデバイスで推論を有効化するため、Intel® Graphics Compute Runtime for oneAPI Level Zero and OpenCL™ Driver をインストールします。Ubuntu* 20.04 のコマンドは、次のとおりです。
sudo apt-get install intel-opencl-icd
次に、仮想環境を準備します。
手順 2: 仮想環境を作成してアクティブにする
システム上でグローバルな影響を避けるには、Python プロジェクトを独自の環境に分離するのが最善です。仮想環境をセットアップするには、ターミナルまたはコマンドプロンプトを開き、環境を構築するディレクトリーに移動します。次に、以下のコマンドを実行して、新しい仮想環境を作成します。
Linux* や macOS* などの UNIX* 系のオペレーティング・システムでは、次のコマンドを使用します。
python3 -m venv venv
Windows* では、次のコマンドを使用します。
python -m venv venv
これにより、新しい仮想環境 venv が現在のフォルダーに作成されます。次に、先ほど作成した環境をアクティブにします。使用するコマンドは、オペレーティング・システムによって異なります。
Linux や macOS などの UNIX 系のオペレーティング・システムでは、次のコマンドを使用します。
source venv/bin/activate
Windows では、次のコマンドを使用します。
venvScriptsactivate
これにより仮想環境がアクティブになり、そのことがシェルのプロンプトの変化により示されます。
手順 3: 必要なものをインストールする
スマートメーターのスキャン・アプリケーションには、多くの依存関係があり、実行するためにはそれらをインストールする必要があります。これらは requirements ファイルに列挙されており、Python パッケージ・インストーラーを使用してインストールできます。
OpenVINO™ ツールキットを含む、必要な Python ライブラリーをインストールするには、次のコマンドを使用します。
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™ ツールキットが提供する利点の 1 つは、ダイナミック・シェイプでデータを直接 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
セグメンテーション後、前処理が完了し、その結果が後処理に渡されます。メーターが検出されてセグメント化されたので、メーターの最終的な読み取り値が処理され、返される必要があります。この処理には、スケールとポインターを 2 値化して、スケールマップのポインターを算出し、最終的なメーターの読み取り値を返すことが含まれます。
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 でデバイスの優先順位を指定するか、または AUTO に設定して、OpenVINO™ ツールキットに、利用可能なハードウェアデバイスから最適な推論デバイスを自動的に選択させます。
アプリケーションを実行するには、次のコマンドを使用します。config/config.json を構成ファイルのパスに、data/test.jpg をテスト画像のパスに置き換えてください。出力結果の画像は、テスト画像と同じフォルダーにエクスポートされます。
python main.py -i data/test.jpg -c config/config.json -t "analog"
アプリケーションを実行する入力パラメーターには、次のものが含まれます。
- -i: 入力画像のパス、ライブカメラでキャプチャーされた産業用メーターの画像
- -c: 構成ファイルのパス。これには、モデル推論、前処理、後処理の手順のパラメーターが含まれています。
- -t: analog と digital から選び、アナログまたはデジタル産業用メーターの自動読み取りを行います。
これで、メーターの読み取り値が得られました。
手順 8: Benchmark_App によるパフォーマンス・ベンチマーク
メーター読み取りパイプラインのモデルのパフォーマンスを評価するには、OpenVINO™ ツールキット Benchmark_App を使用します。この手順では、モデルの実環境のパフォーマンスに関するインサイトが得られ、導入の計画を立てることができます。
Ultralytics フレームワークを使用する、新しくトレーニングされた YOLO* v8l モデルをお勧めします。(PPYOLO v2 は現在、GPU ではサポートされていません。) これは、GitHub* にある同じリポジトリーからダウンロードできます。
YOLO v8l パイプラインでこのアプリケーションを実行するには、次のコマンドを使用して、デフォルトの構成ファイルを ./config/yolov8.json に切り替えます。
python main.py -i data/test.jpg -c config/yolov8.json
-t "analog"
インテル® デベロッパー・クラウドまたはローカルマシンで 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™ ツールキットは、この処理が高性能で低レイテンシーであるようにします。
ご質問や、共有したいことがある場合は、GitHub または Intel Community Support Channel でディスカッションに参加してください。OpenVINO™ ツールキットによる開発の詳細については、こちらのドキュメントを参照してください。
パフォーマンス・ベンチマークの詳細については、GitHub にアクセスしてください。