今天是第二十天我們做實驗發現斑馬魚陰影可能會影響到實驗的準確值,因此我們可以寫一個lstm結合yolo的程式去分析,以下是程式碼
import torch
from yolov5 import YOLOv5
import cv2
# 初始化 YOLOv5 模型
model = YOLOv5("yolov5s.pt") # 使用訓練好的模型
def detect_objects(image):
results = model.predict(image)
detected_objects = {'fish': [], 'shadow': [], 'light': [], 'other': []}
for result in results:
for det in result.boxes:
cls_id = int(det.cls)
x1, y1, x2, y2 = map(int, det.xyxy)
if cls_id == 0: # 假設斑馬魚類別ID為0
detected_objects['fish'].append([x1, y1, x2, y2])
elif cls_id == 1: # 假設陰影類別ID為1
detected_objects['shadow'].append([x1, y1, x2, y2])
elif cls_id == 2: # 假設光源類別ID為2
detected_objects['light'].append([x1, y1, x2, y2])
else: # 其他物體
detected_objects['other'].append([x1, y1, x2, y2])
return detected_objects
這裡我們不僅輸出位置資訊,還會計算距離、速度、面積等作為LSTM的輸入特徵。
import numpy as np
def calculate_distance(box1, box2):
x1_center = (box1[0] + box1[2]) / 2
y1_center = (box1[1] + box1[3]) / 2
x2_center = (box2[0] + box2[2]) / 2
y2_center = (box2[1] + box2[3]) / 2
return np.sqrt((x1_center - x2_center)**2 + (y1_center - y2_center)**2)
def calculate_area(box):
return (box[2] - box[0]) * (box[3] - box[1])
def calculate_velocity(previous_box, current_box, time_interval):
previous_center = [(previous_box[0] + previous_box[2]) / 2, (previous_box[1] + previous_box[3]) / 2]
current_center = [(current_box[0] + current_box[2]) / 2, (current_box[1] + current_box[3]) / 2]
distance = np.sqrt((current_center[0] - previous_center[0])**2 + (current_center[1] - previous_center[1])**2)
return distance / time_interval
def prepare_complex_sequence_data(detected_objects_list, sequence_length=10, time_interval=1.0):
sequence_data = []
for i in range(len(detected_objects_list) - sequence_length):
fish_seq = []
shadow_seq = []
for j in range(sequence_length):
fish_boxes = detected_objects_list[i+j]['fish']
shadow_boxes = detected_objects_list[i+j]['shadow']
# 距離、面積和速度特徵
if fish_boxes and shadow_boxes:
fish_box = fish_boxes[0]
shadow_box = shadow_boxes[0]
distance = calculate_distance(fish_box, shadow_box)
fish_area = calculate_area(fish_box)
shadow_area = calculate_area(shadow_box)
if i > 0: # 速度計算需要前一個時間點的數據
prev_fish_box = detected_objects_list[i+j-1]['fish'][0]
fish_velocity = calculate_velocity(prev_fish_box, fish_box, time_interval)
else:
fish_velocity = 0
# 特徵序列
fish_seq.append([distance, fish_area, fish_velocity])
shadow_seq.append([shadow_area])
else:
fish_seq.append([0, 0, 0])
shadow_seq.append([0])
seq = np.array(fish_seq + shadow_seq).flatten()
sequence_data.append(seq)
return np.array(sequence_data)
這裡我們使用雙向LSTM並增強模型的複雜度,讓其更好地捕捉時間序列的模式。
import torch
import torch.nn as nn
class AdvancedFishBehaviorLSTM(nn.Module):
def __init__(self, input_size, hidden_size, output_size, num_layers=2, bidirectional=True):
super(AdvancedFishBehaviorLSTM, self).__init__()
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True, bidirectional=bidirectional)
self.fc1 = nn.Linear(hidden_size * 2 if bidirectional else hidden_size, hidden_size)
self.fc2 = nn.Linear(hidden_size, output_size)
def forward(self, x):
h_0 = torch.zeros(2 if self.lstm.bidirectional else 1, x.size(0), self.lstm.hidden_size)
c_0 = torch.zeros(2 if self.lstm.bidirectional else 1, x.size(0), self.lstm.hidden_size)
out, _ = self.lstm(x, (h_0, c_0))
out = torch.relu(self.fc1(out[:, -1, :]))
out = self.fc2(out)
return out
# 假設我們的輸入是更加複雜的特徵組合
input_size = 3 * 10 + 1 * 10 # 魚的3個特徵(距離、面積、速度) * 10個時間步長 + 陰影的1個特徵(面積) * 10個時間步長
hidden_size = 256
output_size = 3 # 假設我們有三個行為影響指標(例如焦慮、逃避、活動水平)
model = AdvancedFishBehaviorLSTM(input_size, hidden_size, output_size)
# 假設 sequence_data 是你使用複雜特徵集準備的數據
sequence_data = prepare_complex_sequence_data(detected_objects_list)
sequence_data_tensor = torch.tensor(sequence_data, dtype=torch.float32)
# 進行預測
predictions = model(sequence_data_tensor)
這裡我們會對多個行為指標進行預測並輸出每個指標的評估結果。
# 假設我們對每個行為指標都設定了不同的閾值
anxiety_threshold = 0.6
avoidance_threshold = 0.5
activity_level_threshold = 0.7
impact_anxiety = (predictions[:, 0] > anxiety_threshold).numpy()
impact_avoidance = (predictions[:, 1] > avoidance_threshold).numpy()
impact_activity = (predictions[:, 2] > activity_level_threshold).numpy()
# 輸出結果
print("斑馬魚焦慮是否受到陰影影響:", impact_anxiety)
print("斑馬魚逃避行為是否受到陰影影響:", impact_avoidance)
print("斑馬魚活動水平是否受到陰影影響:", impact_activity)
import torch
from yolov5 import YOLOv5
import cv2
# 初始化 YOLOv5 模型
model = YOLOv5("yolov5s.pt") # 使用訓練好的模型
def detect_objects(image):
results = model.predict(image)
detected_objects = {'fish': [], 'shadow': [], 'light': [], 'other': []}
for result in results:
for det in result.boxes:
cls_id = int(det.cls)
x1, y1, x2, y2 = map(int, det.xyxy)
if cls_id == 0: # 假設斑馬魚類別ID為0
detected_objects['fish'].append([x1, y1, x2, y2])
elif cls_id == 1: # 假設陰影類別ID為1
detected_objects['shadow'].append([x1, y1, x2, y2])
elif cls_id == 2: # 假設光源類別ID為2
detected_objects['light'].append([x1, y1, x2, y2])
else: # 其他物體
detected_objects['other'].append([x1, y1, x2, y2])
return detected_objects
YOLOv5 模型初始化:
yolov5s.pt
作為預訓練模型。這個模型可以用來檢測圖片中的不同物體。detect_objects
函數:
魚
(fish
)、陰影
(shadow
)、光源
(light
)和其他
(other
)。import numpy as np
def calculate_distance(box1, box2):
x1_center = (box1[0] + box1[2]) / 2
y1_center = (box1[1] + box1[3]) / 2
x2_center = (box2[0] + box2[2]) / 2
y2_center = (box2[1] + box2[3]) / 2
return np.sqrt((x1_center - x2_center)**2 + (y1_center - y2_center)**2)
def calculate_area(box):
return (box[2] - box[0]) * (box[3] - box[1])
def calculate_velocity(previous_box, current_box, time_interval):
previous_center = [(previous_box[0] + previous_box[2]) / 2, (previous_box[1] + previous_box[3]) / 2]
current_center = [(current_box[0] + current_box[2]) / 2, (current_box[1] + current_box[3]) / 2]
distance = np.sqrt((current_center[0] - previous_center[0])**2 + (current_center[1] - previous_center[1])**2)
return distance / time_interval
def prepare_complex_sequence_data(detected_objects_list, sequence_length=10, time_interval=1.0):
sequence_data = []
for i in range(len(detected_objects_list) - sequence_length):
fish_seq = []
shadow_seq = []
for j in range(sequence_length):
fish_boxes = detected_objects_list[i+j]['fish']
shadow_boxes = detected_objects_list[i+j]['shadow']
# 距離、面積和速度特徵
if fish_boxes and shadow_boxes:
fish_box = fish_boxes[0]
shadow_box = shadow_boxes[0]
distance = calculate_distance(fish_box, shadow_box)
fish_area = calculate_area(fish_box)
shadow_area = calculate_area(shadow_box)
if i > 0: # 速度計算需要前一個時間點的數據
prev_fish_box = detected_objects_list[i+j-1]['fish'][0]
fish_velocity = calculate_velocity(prev_fish_box, fish_box, time_interval)
else:
fish_velocity = 0
# 特徵序列
fish_seq.append([distance, fish_area, fish_velocity])
shadow_seq.append([shadow_area])
else:
fish_seq.append([0, 0, 0])
shadow_seq.append([0])
seq = np.array(fish_seq + shadow_seq).flatten()
sequence_data.append(seq)
return np.array(sequence_data)
calculate_distance
函數:
box1
和 box2
)的中心點之間的歐幾里得距離。calculate_area
函數:
calculate_velocity
函數:
time_interval
內的移動速度。這是通過計算前後兩個邊界框中心點之間的距離來實現的。prepare_complex_sequence_data
函數:
import torch
import torch.nn as nn
class AdvancedFishBehaviorLSTM(nn.Module):
def __init__(self, input_size, hidden_size, output_size, num_layers=2, bidirectional=True):
super(AdvancedFishBehaviorLSTM, self).__init__()
self.lstm = nn.LSTM(input_size, hidden_size, num_layers, batch_first=True, bidirectional=bidirectional)
self.fc1 = nn.Linear(hidden_size * 2 if bidirectional else hidden_size, hidden_size)
self.fc2 = nn.Linear(hidden_size, output_size)
def forward(self, x):
h_0 = torch.zeros(2 if self.lstm.bidirectional else 1, x.size(0), self.lstm.hidden_size)
c_0 = torch.zeros(2 if self.lstm.bidirectional else 1, x.size(0), self.lstm.hidden_size)
out, _ = self.lstm(x, (h_0, c_0))
out = torch.relu(self.fc1(out[:, -1, :]))
out = self.fc2(out)
return out
# 假設我們的輸入是更加複雜的特徵組合
input_size = 3 * 10 + 1 * 10 # 魚的3個特徵(距離、面積、速度) * 10個時間步長 + 陰影的1個特徵(面積) * 10個時間步長
hidden_size = 256
output_size = 3 # 假設我們有三個行為影響指標(例如焦慮、逃避、活動水平)
model = AdvancedFishBehaviorLSTM(input_size, hidden_size, output_size)
# 假設 sequence_data 是你使用複雜特徵集準備的數據
sequence_data = prepare_complex_sequence_data(detected_objects_list)
sequence_data_tensor = torch.tensor(sequence_data, dtype=torch.float32)
# 進行預測
predictions = model(sequence_data_tensor)
LSTM 模型設計:
AdvancedFishBehaviorLSTM
是一個包含雙向 LSTM 的深度學習模型,用於分析時間序列數據。input_size
是每個時間步的輸入特徵數量,這裡是魚和陰影的特徵組合。hidden_size
是 LSTM 層中隱藏單元的數量。output_size
是最終輸出的數量,代表不同行為的影響指標。模型的前向傳播:
forward
函數中,LSTM 層將輸入數據處理成隱藏狀態。活函數來引入非線性。
這段程式碼的整體流程如下: