日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

Udacity机器人软件工程师课程笔记(三)-样本搜索和找回-基于漫游者号模拟器-使用moviepy输出测试视频

發布時間:2023/11/27 生活经验 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Udacity机器人软件工程师课程笔记(三)-样本搜索和找回-基于漫游者号模拟器-使用moviepy输出测试视频 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

6.方法測試

在這個部分我們要整體的測試我們的程序,對前面的知識和內容有一個整體的應用和概括。

這是Udacity提供的相應資料,在code文件夾中有一個Rover_Project_Test_Notebook.ipynb文件,提供了輸出視頻的筆記本文件。

由于個人喜好的原因,我選擇了pycharm2019來運行此程序。

(1)方法測試程序概述

在這個部分我們需要完成的項目如下

  1. 首先運行筆記本中的每個單元格,檢查代碼和每個單元格的結果。
  2. 在“訓練模式”中運行模擬器并記錄一些數據。注意:只需要使用一些示例圖像,幾百張即可。
  3. 將數據目錄路徑(下面的2個單元格)更改為保存數據的目錄
  4. 測試數據上提供的功能
  5. 編寫新功能(或修改現有功能)以報告和繪制障礙物和巖石樣本(黃色巖石)的檢測結果
  6. 使用適當的步驟/函數填充process_image()函數,以從原圖像轉換為worldmap。
  7. 使用moviepy函數運行調用process_image()的單元格以創建視頻輸出
  8. 如果繪制工作可以進行,則繼續修改perception.py和decision.py,讓流浪者號自主導航并以自動模式進行繪制。

首先我們需要獲取ffmpeg工具

import imageioimageio.plugins.ffmpeg.download()

運行此程序以下載ffmpeg工具。

但我在運行這個程序時遇到了一個問題。

報錯

imageio.ffmpeg.download() has been deprecated. Use 'pip install imageio-ffmpeg' instead.'‘

經查閱,該錯誤是由版本更新引起的錯誤,解決辦法(在Windows上)為

pip install imageio==2.4.1

現在再一次運行我們的程序,如果imageio正確安裝且電腦中沒有安裝ffmpeg,程序會自動下載安裝

import imageioimageio.plugins.ffmpeg.download()

python會自動下載ffmpeg,如果下載不成功或者速度太慢可以選擇到相應網站下載,單擊這里進行下載。

ffmpeg應當放到AppData目錄下。

(2)讀入以保存的數據和世界地圖

我們定義一個名為 Databucket() 類來存儲測量數據、圖像路徑和圖像。

當我們實例化這個類時,我們將得到一個名為 data 的全局變量,我們將在之后的 process_image() 函數中來引用其中的數據。

其程序如下:

import pandas as pd
df = pd.read_csv('.../Roversim/Roverdata/robot_log.csv', delimiter=';', decimal='.')
csv_img_list = df["Path"].tolist()
# 讀入世界地圖并使用它創建一個3通道的圖像
ground_truth = mpimg.imread('.../RoboND-Rover-Project-master/calibration_images/map_bw.png')
ground_truth_3d = np.dstack((ground_truth*0, ground_truth*255, ground_truth*0)).astype(np.float)# 創建一個類作為Databucket,讀取csv文件中保存的數據并填充此對象。
# worldmap被實例化為200*200個網格,其對應200m*200m的空間。
class Databucket():def __init__(self):self.images = csv_img_list  self.xpos = df["X_Position"].valuesself.ypos = df["Y_Position"].valuesself.yaw = df["Yaw"].valuesself.count = 0 # 運行索引self.worldmap = np.zeros((200, 200, 3)).astype(np.float)self.ground_truth = ground_truth_3d # Ground truth worldmap# 實例化一個databucket,這將是一個全局變量,
# 我們可以在接下來的process_image()函數中使用
data = Databucket()

(3)圖像處理函數

1)process_image()函數

編寫process_image()函數,以執行圖像分析和映射。我們只需要把對應漫游者號的位置等映射到worldmap上去就可以。

在之前的程序中,我們小車的位置和偏轉角是隨機生成的,但是這里就需要我們來讀取csv文件中的數據,將相應的透視變換之后的圖像映射到世界地圖上去。

換句話說, 我們將各個圖像傳遞到 process_image() 函數并以此來構建一個名為 output_image 的圖像,該圖像將存儲為視頻的一幀。

下面是經過更改后的 process_image() 函數:

# 定義圖片處理函數
def process_image(img):output_image = np.zeros((img.shape[0] + data.worldmap.shape[0],img.shape[1] * 2, 3))# 定義第一張圖為imgoutput_image[0:img.shape[0], 0:img.shape[1]] = img# 定義第二張圖為img經過透視變換后的圖像warped = perspect_transform(img, src, dst)output_image[0:img.shape[0], img.shape[1]:] = warpedgray_warped = cv2.cvtColor(warped, cv2.COLOR_RGB2GRAY)ret, img_thresh = cv2.threshold(gray_warped, 160, 255, cv2.THRESH_BINARY)test_image = np.expand_dims(img_thresh, axis=2)output_image[180:340, img.shape[1]:, 0] = img_threshxpix, ypix = rover_coords(img_thresh)worldmap = data.worldmapx_world, y_world = pix_to_world(xpix, ypix, data.xpos[data.count], data.ypos[data.count], data.yaw[data.count],data.worldmap.shape[0], 20 )worldmap[y_world, x_world] += 1map_add = cv2.addWeighted(ground_truth_3d, 1, worldmap, 0.2, 0)output_image[img.shape[0]:, 0:data.worldmap.shape[1]] = map_addcv2.putText(output_image, "Test!", (20, 20),cv2.FONT_HERSHEY_COMPLEX, 0.4, (255, 255, 255), 1)# 跟蹤Databucket中的索引if data.count < len(data.images) - 1:data.count += 1return output_image

2)cv2.addWeighted

此函數是為了使兩個圖像疊加使用的,用在我們將小車的透視變換后的圖像映射到世界地圖上。

dst = cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) 

參數說明:

  • src1 - 第一個輸入數組。
  • alpha - 第一個數組元素的權重。
  • src2 - 與src1具有相同大小和通道編號的第二個輸入數組。
  • beta - 第二個數組元素的權重。
  • dst - 與輸入數組具有相同大小和通道數的輸出數組。
  • gamma - 標量加到每個總和。
  • dtype - 輸出數組的可選深度; 當兩個輸入數組具有相同的深度時,dtype可以設置為-1,這相當于src1.depth()

此函數可以用一下矩陣表達式來代替:

dst = src1 * alpha + src2 * beta + gamma;

(4)輸出測試視頻

因為我們要對特定的顏色進行圖像顏色閾值處理,比如之后選擇特定的黃色的巖石樣本,所以我圖像二值化選擇使用numpy來完成而不是cv2。其程序如下:

def color_thresh(img, rgb_thresh=(160, 160, 160)):color_select = np.zeros_like(img[:,:,0])above_thresh = (img[:,:,0] > rgb_thresh[0]) \& (img[:,:,1] > rgb_thresh[1]) \& (img[:,:,2] > rgb_thresh[2])color_select[above_thresh] = 1return color_selectthreshed = color_thresh(warped)
plt.imshow(threshed, cmap='gray')

以下是最終程序

import numpy as np
import cv2
import pandas as pd
import matplotlib.image as mpimg
from moviepy.editor import VideoFileClip
from moviepy.editor import ImageSequenceClip##顏色閾值
# 使用Numpy定義二值化圖像函數
def color_thresh(img, rgb_thresh=(160, 160, 160)):img_thresh = np.zeros_like(img[:, :, 0])above_thresh = (img[:, :, 0] > rgb_thresh[0]) \& (img[:, :, 1] > rgb_thresh[1]) \& (img[:, :, 2] > rgb_thresh[2])img_thresh[above_thresh] = 1return img_thresh##透視變換
# 定義圖像映射函數,將攝像頭的圖像映射到平面坐標中去
def perspect_transform(img, src, dst):M = cv2.getPerspectiveTransform(src, dst)  # 定義變換矩陣img_perspect = cv2.warpPerspective(img, M, (img.shape[1], img.shape[0]))return img_perspect##坐標變換
# 定義從圖像坐標轉換函數
def rover_coords(binary_img):ypos, xpos = binary_img.nonzero()x_pixel = -(ypos - binary_img.shape[0]).astype(np.float)y_pixel = -(xpos - binary_img.shape[1]/2 ).astype(np.float)return x_pixel, y_pixel# 定義旋轉操作函數
def rotate_pix(xpix, ypix, yaw):yaw_rad = yaw * np.pi / 180xpix_rotated = (xpix * np.cos(yaw_rad)) - (ypix * np.sin(yaw_rad))ypix_rotated = (xpix * np.sin(yaw_rad)) + (ypix * np.cos(yaw_rad))return xpix_rotated, ypix_rotated# 定義平移操作函數
def translate_pix(xpix_rot, ypix_rot, xpos, ypos, scale):xpix_translated = (xpix_rot / scale) + xposypix_translated = (ypix_rot / scale) + yposreturn xpix_translated, ypix_translated# 定義綜合函數,將旋轉和平移函數進行結合,并限制了圖像范圍
def pix_to_world(xpix, ypix, xpos, ypos, yaw, world_size, scale):xpix_rot, ypix_rot = rotate_pix(xpix, ypix, yaw)xpix_tran, ypix_tran = translate_pix(xpix_rot, ypix_rot, xpos, ypos, scale)x_pix_world = np.clip(np.int_(xpix_tran), 0, world_size - 1)y_pix_world = np.clip(np.int_(ypix_tran), 0, world_size - 1)return x_pix_world, y_pix_world# 定義轉換為極坐標函數
def to_polar_coords(xpix, ypix):dist = np.sqrt(xpix**2 + ypix ** 2)angles = np.arctan2(ypix, xpix)return dist, angles# 參考圖像,用作透視變換
filename = '.../RoboND-Rover-Project-master/calibration_images/example_grid1.jpg'
image = cv2.imread(filename)dst_size = 5
bottom_offset = 0src = np.float32([[14, 140], [301, 140], [200, 96], [118, 96]])
dst = np.float32([[image.shape[1]/2 - dst_size, image.shape[0] - bottom_offset],[image.shape[1]/2 + dst_size, image.shape[0] - bottom_offset],[image.shape[1]/2 + dst_size, image.shape[0] - 2*dst_size - bottom_offset],[image.shape[1]/2 - dst_size, image.shape[0] - 2*dst_size - bottom_offset],])# 透視變換
warped = perspect_transform(image, src, dst)df = pd.read_csv('.../Roverdata/robot_log.csv', delimiter=';', decimal='.')
csv_img_list = df["Path"].tolist() # 創建一個關于圖像的路徑列表
# 讀取worldmap,并創建一個三維圖像
ground_truth = mpimg.imread('.../RoboND-Rover-Project-master/calibration_images/map_bw.png')
ground_truth_3d = np.dstack((ground_truth*0, ground_truth*255, ground_truth*0)).astype(np.float)# 定義一個類來存儲諸如漫游者號位置,方向角等數據
class Databucket():def __init__(self):self.images = csv_img_listself.xpos = df["X_Position"].valuesself.ypos = df["Y_Position"].valuesself.yaw = df["Yaw"].valuesself.count = 0self.worldmap = np.zeros((200, 200, 3)).astype(np.float)self.ground_truth = ground_truth_3d# 實例化Databucket類
data = Databucket()# 定義圖片處理函數
def process_image(img):output_image = np.zeros((img.shape[0] + data.worldmap.shape[0],img.shape[1] * 2, 3))# 定義第一張圖為攝像頭原圖imgoutput_image[0:img.shape[0], 0:img.shape[1]] = img# 定義第二張圖為img經過透視變換后的圖像warped = perspect_transform(img, src, dst)output_image[0:img.shape[0], img.shape[1]:] = warpedgray_warped = cv2.cvtColor(warped, cv2.COLOR_RGB2GRAY)ret, img_thresh = cv2.threshold(gray_warped, 160, 255, cv2.THRESH_BINARY)test_image = np.expand_dims(img_thresh, axis=2)output_image[180:340, img.shape[1]:, 0] = img_thresh# 漫游者號的坐標系,在每一個圖像中都不同xpix, ypix = rover_coords(img_thresh)worldmap = data.worldmapx_world, y_world = pix_to_world(xpix, ypix, data.xpos[data.count], data.ypos[data.count], data.yaw[data.count], data.worldmap.shape[0], 20 )# 相應位置顏色+1worldmap[y_world, x_world] += 1map_add = cv2.addWeighted(ground_truth_3d, 1, worldmap, 0.2, 0)output_image[img.shape[0]:, 0:data.worldmap.shape[1]] = map_addcv2.putText(output_image, "Test_Video", (20, 20),cv2.FONT_HERSHEY_COMPLEX, 0.4, (255, 255, 255), 1)# 跟蹤Databucket中的索引if data.count < len(data.images) - 1:data.count += 1return output_image# 將處理過的圖像制作成視頻,使用moviepy
output = '.../test_mapping.mp4'clip = ImageSequenceClip(data.images, fps=60)
new_clip = clip.fl_image(process_image)# 只接受彩色圖片
new_clip.write_videofile(output, audio=False)

輸出的視頻結果如下:

總結

以上是生活随笔為你收集整理的Udacity机器人软件工程师课程笔记(三)-样本搜索和找回-基于漫游者号模拟器-使用moviepy输出测试视频的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。