如何使用TensorFlow和Cleanvision檢測大堡礁的海星威脅?
譯文澳大利亞的大堡礁美不勝收,是全球最大的珊瑚礁,也是多種多樣的海洋生物棲息的家園。不幸的是,珊瑚礁面臨蠶食珊瑚的棘冠海星(COTS)的威脅。為了控制COTS爆發(fā),珊瑚礁管理人員使用一種名為Manta Tow勘查的方法,將潛水員拖在船后,目測評估珊瑚礁的各個部分。然而,這種方法在效率、數(shù)據(jù)質(zhì)量和可擴展性方面存在局限性。
為了改善對COTS的監(jiān)測和控制,大堡礁基金會啟動了一項創(chuàng)新計劃。一個關鍵部分就是使用水下攝像機采集珊瑚礁圖像,并運用AI自動檢測COTS。
為了針對這種基于視頻的大規(guī)??辈殚_發(fā)機器學習技術,澳大利亞國家科學機構CSIRO與谷歌進行合作。他們的目標是創(chuàng)建系統(tǒng),以便能夠準確高效地分析大量圖像,從而近乎實時地查明大堡礁的COTS爆發(fā)情況。這將大大有助于環(huán)保工作,并有助于確保珊瑚礁生態(tài)系統(tǒng)受到長期保護。
總而言之,基于AI的圖像分析正被應用于從大堡礁拍攝畫面中自動檢測棘冠海星,從而以大幅提高的效率和規(guī)模更好地監(jiān)測和控制,以保護珊瑚礁。這里旨在建立一個使用水下珊瑚礁視頻訓練的對象檢測模型,實時準確地識別海星。我們在這篇博文中將構建一個機器學習管道,以分析珊瑚礁的圖像,并預測棘冠海星的存在和位置。
我們將使用Cleanvision(這個開源軟件包使用以數(shù)據(jù)為中心的AI來清理圖像數(shù)據(jù)中的問題)、Tensorflow、KerasCV以及YOLOv8,后者用于計算機視覺任務,比如對象檢測和圖像分類。
!pip install -q cleanvision keras-cv kaggle
由于數(shù)據(jù)量巨大,我們直接使用Kaggle下載并運行教程。為此,我們需要配置您的Kaggle憑據(jù),并授予適當?shù)臋嘞?/span>,點擊這里閱讀更多(https://www.kaggle.com/discussions/general/74235?ref=hackernoon.com)。
! cp kaggle.json ~/.kaggle/
! chmod 600 ~/.kaggle/kaggle.json
下載和提取Kaggle數(shù)據(jù)集
!kaggle competitions download -c tensorflow-great-barrier-reef
!unzip /content/tensorflow-great-barrier-reef.zip
使用Cleanvision清理數(shù)據(jù)
CleanVision是一個以數(shù)據(jù)為中心的開源AI軟件包,可以自動識別可能對計算機視覺系統(tǒng)產(chǎn)生負面影響的有問題的圖像。它掃描圖像數(shù)據(jù)集并檢測常見的數(shù)據(jù)問題,比如模糊、光照不足和重復圖像等。
在開發(fā)機器學習模型以確??煽啃灾?,解決訓練數(shù)據(jù)中的這些問題是必不可少的第一步。
CleanVision提供了一個簡單的統(tǒng)一界面,僅運行相同的幾行Python代碼就可以審查任何圖像集合,無論大小或來源如何。這使得清理臟的圖像數(shù)據(jù)異常容易。
通過預先主動標記低質(zhì)量、重復及其他不需要的圖像,CleanVision在構建計算機視覺應用程序時有助于節(jié)省大量時間,并改善結(jié)果。
這是在運用機器學習處理基于圖像的任務之前做好數(shù)據(jù)干凈這項先決條件的快速方法。
from cleanvision import Imagelab
# Specify path to folder containing the image files in your dataset
imagelab = Imagelab(data_path="train_images/")
# Automatically check for a predefined list of issues within your dataset
imagelab.find_issues()
# Produce a neat report of the issues found in your dataset
imagelab.report()
import os
for st in imagelab.info['exact_duplicates']['sets']:
os.remove(st[0])
導入相關庫
import pandas as pd
# show images inline
%matplotlib inline
import keras
import tensorflow
# import miscellaneous modules
import matplotlib.pyplot as plt
import cv2
import os
import numpy as np
import time
import tensorflow as tf
準備數(shù)據(jù)集進行預處理
我們將讀取數(shù)據(jù)集,然后對其進行預處理,以便能夠?qū)⑵溆糜谀P陀柧?。我們先加載train CSV文件,并將注釋由原始JSON格式轉(zhuǎn)換為整數(shù)格式。
df_train = pd.read_csv("train.csv")
df_train=df_train.loc[df_train["annotations"].astype(str) != "[]"]
df_train['annotations'] = df_train['annotations'].apply(eval)
df_train['image_path'] = "train_images/video_" +
df_train['video_id'].astype(str) + "/" +
df_train['video_frame'].astype(str) + ".jpg"
df_extrain=df_train.explode('annotations') # Single annotation per row
df_extrain.reset_index(inplace=True)
df_extrain.head()
df_extrain_main=pd.DataFrame(pd.json_normalize(df_extrain['annotations']),
columns=['x', 'y', 'width', 'height']).join(df_extrain)
df_extrain_main['class']=0
df_extrain_main=df_extrain_main[['image_path','x','y','width','height','cl
ass','video_id','video_frame']]
df_extrain_main.head(10)
在CSV處理之后,我們嘗試將CSV拆分成一個數(shù)據(jù)集,并使用適當?shù)倪吔缈蚋袷?、類和圖像路徑,以創(chuàng)建準備進一步處理的初步數(shù)據(jù)集。
def create_tf_example(rowss,data_df):
xmins = []
xmaxs = []
ymins = []
ymaxs = []
# Convert ---> [xmin,ymin,width,height] to [xmins,xmaxs,ymins,ymaxs]
xmin = rowss['x']
xmax = rowss['x']+rowss['width']
ymin = rowss['y']
ymax = rowss['y']+rowss['height']
#main_data.append((rowss['image_path'],xmins,xmaxs,ymins,ymaxs))
return rowss['image_path'],xmin,ymin,xmax,ymax
from PIL import Image, ImageDraw
paths = []
bboxes = []
classes = []
for index, row in df_extrain_main.iterrows():
if index % 1000 == 0:
print('Processed {0} images.'.format(index))
image_path,xmins,ymins,xmaxs,ymaxs=create_tf_example(row,df_extrain_main)
paths.append(image_path)
bboxes.append([[float(xmins),float(ymins),float(xmaxs),float(ymaxs)]])
classes.append([0])
這里,我們使用tf.rag.constant由bbox和classes列表創(chuàng)建不規(guī)則張量。不規(guī)則張量是一類張量,可以沿一個或多個維度處理不同長度的數(shù)據(jù)。這在處理具有可變長度序列的數(shù)據(jù)(如文本或時間序列數(shù)據(jù))時非常有用。
在這種情況下,bbox和classes列表對于每個圖像有不同的長度,這取決于圖像中對象的數(shù)量以及相應的邊界框和類。為了應對這種變化,我們使用不規(guī)則張量而不是規(guī)則張量。
稍后,這些不規(guī)則張量使用from_tensor_slices方法用于創(chuàng)建tf.data.Dataset。該方法通過沿第一個維度對輸入張量進行切片來創(chuàng)建一個數(shù)據(jù)集。
通過使用不規(guī)則張量,數(shù)據(jù)集可以為每個圖像處理不同長度的數(shù)據(jù),并為進一步處理提供靈活的輸入管道。
bbox = tf.ragged.constant(bboxes)
classes = tf.ragged.constant(classes)
image_paths = tf.ragged.constant(paths)
data = tf.data.Dataset.from_tensor_slices((image_paths, classes, bbox))
num_val = int(bbox.shape[0] * 0.2)
# Split the dataset into train and validation sets
val_data = data.take(num_val)
train_data = data.skip(num_val)
KerasCV包括流行的計算機視覺數(shù)據(jù)集(比如ImageNet、COCO和Pascal VOC)的預訓練模型,可用于遷移學習。KerasCV還提供了一系列可視化工具,用于檢查模型所學到的中間表示,以及直觀顯示對象檢測和分割任務的結(jié)果。
在這個特定的筆記本中,我們使用YOLOV8,因此我們必須根據(jù)YOLOV8模型以兼容的格式格式化數(shù)據(jù)集。邊界框輸入格式應該如下所示:
bounding_boxes = {
# num_boxes may be a Ragged dimension
'boxes': Tensor(shape=[batch, num_boxes, 4]),
'classes': Tensor(shape=[batch, num_boxes]) }
字典有兩個鍵box和classes,每個鍵都映射到TensorFlow RaggedTensor或Tensor對象。boxes張量的形狀為[batch, num_boxes, 4],其中batch是批處理中的圖像數(shù)量,num_boxes是任何圖像中邊界框的最大數(shù)量。4表示定義邊界框所需的四個值:xmin、ymin、xmax和ymax。
classes張量的形狀為[batch, num_boxes],其中每個元素代表boxes張量中相應邊界框的類標簽。num_boxes維度可能是不規(guī)則的,這意味著邊界框的數(shù)量在批處理中的圖像當中可能不同。
最終的模型輸入看起來像這樣:
{"images": images, "bounding_boxes": bounding_boxes}
def load_image(image_path):
image = tf.io.read_file(image_path)
image = tf.image.decode_jpeg(image, channels=3)
return image
def load_dataset(image_path, classes, bbox):
# Read Image
image = load_image(image_path)
bounding_boxes = {
"classes": tf.cast(classes, dtype=tf.float32),
"boxes": tf.cast(bbox, dtype=tf.float32),
}
return {"images": tf.cast(image, tf.float32), "bounding_boxes":
bounding_boxes}
數(shù)據(jù)增強
在構建對象檢測模型時,運用有效的數(shù)據(jù)增強至關重要,但又具有挑戰(zhàn)性。像裁切和翻轉(zhuǎn)等轉(zhuǎn)換必須正確地更新邊界框坐標。手動執(zhí)行此操作既復雜又容易出錯。
KerasCV提供了專門的層來處理感知邊界框的增強。它提供了廣泛的轉(zhuǎn)換,可以自動調(diào)整bboxes以匹配增強的圖像。
借助KerasCV,這種集成的邊界框處理可以輕松地將強大的增強功能整合到對象檢測管道中。利用tf.data管道,增強可以在訓練期間實時完成。
借助KerasCV強大的bbox感知增強功能,開發(fā)人員可以在對象檢測模型中實現(xiàn)更多樣化更有用的訓練數(shù)據(jù)和改進的泛化,同時避免繁瑣的坐標手動處理。這些層在幕后處理這種復雜性。
augmenter = keras.Sequential(
layers=[
keras_cv.layers.RandomFlip(mode="horizontal",
bounding_box_format="xyxy"),
keras_cv.layers.RandomShear(
x_factor=0.2, y_factor=0.2, bounding_box_format="xyxy"
),
keras_cv.layers.JitteredResize(
target_size=(640, 640), scale_factor=(0.75, 1.3),
bounding_box_format="xyxy"
),
]
)
resizing = keras_cv.layers.JitteredResize(
target_size=(640, 640),
scale_factor=(0.75, 1.3),
bounding_box_format="xyxy",
)
借助增強訓練數(shù)據(jù)集
我們正在借助增強為對象檢測模型準備訓練數(shù)據(jù)集。我們先將batch_size設置為4,然后使用load_dataset函數(shù)來加載數(shù)據(jù)。
接下來,我們對數(shù)據(jù)進行大清洗,以確保我們的模型不會在特定類型的數(shù)據(jù)上過擬合。然后,我們使用ragged_batch函數(shù)以固定大小4對數(shù)據(jù)進行批處理,并刪除任何剩余的數(shù)據(jù)。
最后,我們對數(shù)據(jù)集運用augmenter函數(shù)進行數(shù)據(jù)增強,這有助于增加數(shù)據(jù)集的多樣性,并提高模型的精度。
num_parallel_calls參數(shù)被設置為tf.data.AUTOTUNE,允許TensorFlow動態(tài)調(diào)整并行調(diào)用的數(shù)量,以提高性能。
BATCH_SIZE =4
train_ds = train_data.map(load_dataset, num_parallel_calls=tf.data.AUTOTUNE)
train_ds = train_ds.shuffle(BATCH_SIZE * 4)
train_ds = train_ds.ragged_batch(BATCH_SIZE, drop_remainder=True)
train_ds = train_ds.map(augmenter, num_parallel_calls=tf.data.AUTOTUNE)
驗證數(shù)據(jù)集
在這個代碼塊中,我們通過將'load_dataset'函數(shù)映射到'val_data'集來創(chuàng)建一個驗證數(shù)據(jù)集。該函數(shù)有助于從數(shù)據(jù)集加載數(shù)據(jù),并為模型對其進行預處理。
我們還將'num_parallel_calls'設置為'tf.data.AUTOTUNE’,以啟用并行機制,從而加快處理速度。
接下來,我們將驗證數(shù)據(jù)集按“BATCH_SIZE * 4”的因子進行大清洗,以增強隨機性并防止過擬合。最后,我們用'drop_remainder=True'創(chuàng)建一個'BATCH_SIZE'的'ragged_batch',以確保所有批次大小相同。
這有助于使模型在訓練期間更高效更一致。
val_ds = val_data.map(load_dataset, num_parallel_calls=tf.data.AUTOTUNE)
val_ds = val_ds.shuffle(BATCH_SIZE * 4)
val_ds = val_ds.ragged_batch(BATCH_SIZE, drop_remainder=True)
邊界框可視化
我們使用keras_cv庫來實現(xiàn)邊界框可視化。它導入必要的軟件包,并為數(shù)據(jù)集定義類映射。visualize_dataset()函數(shù)接受數(shù)據(jù)集輸入,并使用plot_bounding_box_gallery()函數(shù)來顯示邊界框被覆蓋的圖像。您可以通過train_ds和val_ds數(shù)據(jù)集看到這一點。
import keras_cv
from keras_cv import bounding_box
from keras_cv import visualization
class_mapping = {0:'fish'}
def visualize_dataset(inputs, value_range, rows, cols,
bounding_box_format):
inputs = next(iter(inputs.take(1)))
images, bounding_boxes = inputs["images"], inputs["bounding_boxes"]
visualization.plot_bounding_box_gallery(
images,
value_range=value_range,
rows=rows,
cols=cols,
y_true=bounding_boxes,
scale=5,
font_scale=0.7,
bounding_box_format=bounding_box_format,
class_mapping=class_mapping,
)
visualize_dataset(
train_ds, bounding_box_format="xyxy", value_range=(0, 255), rows=2,
cols=2
)
visualize_dataset(
val_ds, bounding_box_format="xyxy", value_range=(0, 255), rows=2,
cols=2
)
接下來,我們解壓縮數(shù)據(jù)集,以便能夠?qū)⑵漯佀偷終eras API的模型訓練函數(shù)。
def dict_to_tuple(inputs):
return inputs["images"], inputs["bounding_boxes"]
train_ds = train_ds.map(dict_to_tuple,
num_parallel_calls=tf.data.AUTOTUNE)
train_ds = train_ds.prefetch(tf.data.AUTOTUNE)
val_ds = val_ds.map(dict_to_tuple, num_parallel_calls=tf.data.AUTOTUNE)
val_ds = val_ds.prefetch(tf.data.AUTOTUNE)
模型構建
YOLOv8是流行的YOLO(你只看一次)系列模型的最新版本,用于對象檢測和圖像分類之類的計算機視覺任務。它是由Ultralytics在之前的YOLOv5模型的基礎上創(chuàng)建的。
與以前的版本相比,YOLOv8集成了架構方面的眾多升級,以提高精度和性能。創(chuàng)建者還旨在提升開發(fā)人員的整體體驗。
作為業(yè)界領先的YOLO系列的最新版本,YOLOv8代表了對象檢測等領域當前的最高水平。它結(jié)合了算法方面的進步,為從業(yè)人員不斷提升CV能力和可用性方面的改進。
Keras-CV提供多種YOLOV8模型:YOLOv8n、YOLOv8s、YOLOv8m、YOLOv8l和YOLOv8x。就本例而言,我們選擇YOLOV8s主力模型,并使用coco預訓練權重來加載它。
接下來,我們使用YOLOV8 detector構建一個YOLOV8模型,接受特征提取器作為主干參數(shù),num_classes參數(shù)根據(jù)class_mapping列表的大小指定要檢測的對象類的數(shù)量,bounding_box_format參數(shù)告知模型數(shù)據(jù)集中bbox的格式。最后,特征金字塔網(wǎng)絡(FPN)深度由fpn_depth參數(shù)指定。
backbone = keras_cv.models.YOLOV8Backbone.from_preset(
"yolo_v8_s_backbone_coco" # We will use yolov8 small backbone with
coco weights
)
yolo = keras_cv.models.YOLOV8Detector(
num_classes=1,
bounding_box_format="xyxy",
backbone=backbone,
fpn_depth=1,
)
編譯模型
YOLOv8模型的訓練過程涉及使用兩種類型的損失:分類損失和邊界框損失。
分類損失度量每個檢測對象的預測類概率與真實類概率之間的差異。在這種情況下使用二元交叉熵損失,因為每個檢測到的項目要么屬于特定的類,要么不屬于特定的類。該損失函數(shù)有助于優(yōu)化模型以實現(xiàn)準確的對象分類。
另一方面,邊界框損失計算預測的邊界框與實際邊界框之間的差異度。YOLOv8使用全面的IoU(CIoU)而不是基本的IoU來計算邊界框損失。CIoU還考慮額外的因素,比如邊界框的長寬比、中心距離和比例。如果查看更多的邊界框?qū)傩裕ú粌H限于重疊),這有助于更好地表示邊界框的相似度。
通過在訓練過程中針對對象分類和精確定位進行共同優(yōu)化,分類損失和邊界框損失幫助YOLOv8通過最小化跨類和邊界框坐標的輸出和標簽數(shù)據(jù)之間的差異,生成高度準確的對象檢測。
optimizer = tf.keras.optimizers.Adam(
learning_rate=10e-3,
)
yolo.compile(
optimizer=optimizer, classification_loss="binary_crossentropy",
box_loss="ciou"
)
訓練模型
在每個輪次(epoch)期間,模型迭代式調(diào)整其參數(shù),以實現(xiàn)預測輸出與實際輸出之間的差異最小化。這個過程幫助模型學習如何在珊瑚礁的水下視頻中準確地檢測到棘冠海星。
輪次的數(shù)量可以根據(jù)訓練數(shù)據(jù)集的大小、模型的復雜性以及所需的精度加以調(diào)整。經(jīng)過訓練,模型可用于實時預測海星的存在和位置,幫助研究人員和環(huán)保主義者更有效地監(jiān)測和控制COTS爆發(fā)。
yolo.fit(
train_ds,
epochs=3,
)
結(jié)論
在這個項目中,集成Cleanvision、TensorFlow、KerasCV和YOLOv8體現(xiàn)了AI在環(huán)保方面的強大功能和多功能性,特別是對大堡礁而言。
利用這些先進工具具有的優(yōu)勢,我們開發(fā)了一個強大的模型,能夠在復雜的水下環(huán)境中準確識別棘冠海星。
這不僅標志著在保護世界自然奇觀方面向前邁出了重要一步,還展示了AI在應對生態(tài)挑戰(zhàn)方面具有的巨大潛力。
原文標題:How to Use TensorFlow and Cleanvision to Detect Starfish Threats in the Great Barrier Reef,作者:Aravind Putrevu
鏈接:
https://hackernoon.com/how-to-use-tensorflow-and-cleanvision-to-detect-starfish-threats-in-the-great-barrier-reef。