筆者從事于cv視覺深度的相關研究,在cv的單目視覺深度模型中,monodepth2有一個相對較好的深度效果,但是論文作者就提供了關于KITTI的預訓練模型,沒有提供如何就自定義的資料集進行訓練的詳細細節,所以,在閱讀了monodepth2原始碼的基礎上,給大家講講如何用自己的資料集把monodepth2跑起來,
我使用的是超算的linux作業系統,訓練平臺為Tesla_V100,由于我采集1920*1080單目幀序列作為資料集,按照模型默認batchsize=12往超算里面送的時候提示顯存不夠,所以這里我還是建議采集自己的資料集的時候還是用較小的解析度,比如640*480,在確認了解析度之后,先把源代碼中的對應尺寸都改為640+480,其中options.py里的self.height和self.width也要分別改成480和640,而且原模型還要求這倆引數是32的倍數,剛好640+480就符合,

所以我們采用640+480作為單目幀序列的解析度,我大概采集了90秒的視頻,場景為我們學院的走廊,每一秒30幀,所以轉換為圖片序列最終是2580張圖片,視頻轉圖片序列的源代碼如下所示:
import os
import cv2 ##加載OpenCV模塊
def video2frames(pathIn='',
pathOut='',
only_output_video_info=False,
extract_time_points=None,
initial_extract_time=0,
end_extract_time=None,
extract_time_interval=-1,
output_prefix='frame',
jpg_quality=100,
isColor=True):
'''
pathIn:視頻的路徑,比如:F:\python_tutorials\test.mp4
pathOut:設定提取的圖片保存在哪個檔案夾下,比如:F:\python_tutorials\frames1\,如果該檔案夾不存在,函式將自動創建它
only_output_video_info:如果為True,只輸出視頻資訊(長度、幀數和幀率),不提取圖片
extract_time_points:提取的時間點,單位為秒,為元組資料,比如,(2, 3, 5)表示只提取視頻第2秒, 第3秒,第5秒圖片
initial_extract_time:提取的起始時刻,單位為秒,默認為0(即從視頻最開始提取)
end_extract_time:提取的終止時刻,單位為秒,默認為None(即視頻終點)
extract_time_interval:提取的時間間隔,單位為秒,默認為-1(即輸出時間范圍內的所有幀)
output_prefix:圖片的前綴名,默認為frame,圖片的名稱將為frame_000001.jpg、frame_000002.jpg、frame_000003.jpg......
jpg_quality:設定圖片質量,范圍為0到100,默認為100(質量最佳)
isColor:如果為False,輸出的將是黑白圖片
'''
cap = cv2.VideoCapture(pathIn) ##打開視頻檔案
n_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) ##視頻的幀數
fps = cap.get(cv2.CAP_PROP_FPS) ##視頻的幀率
dur = n_frames / fps ##視頻的時間
##如果only_output_video_info=True, 只輸出視頻資訊,不提取圖片
if only_output_video_info:
print('only output the video information (without extract frames)::::::')
print("Duration of the video: {} seconds".format(dur))
print("Number of frames: {}".format(n_frames))
print("Frames per second (FPS): {}".format(fps))
##提取特定時間點圖片
elif extract_time_points is not None:
if max(extract_time_points) > dur: ##判斷時間點是否符合要求
raise NameError('the max time point is larger than the video duration....')
try:
os.mkdir(pathOut)
except OSError:
pass
success = True
count = 0
while success and count < len(extract_time_points):
cap.set(cv2.CAP_PROP_POS_MSEC, (1000 * extract_time_points[count]))
success, image = cap.read()
if success:
if not isColor:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) ##轉化為黑白圖片
print('Write a new frame: {}, {}th'.format(success, count + 1))
cv2.imwrite(os.path.join(pathOut, "{}_{:06d}.jpg".format(output_prefix, count + 1)), image,
[int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality]) # save frame as JPEG file
count = count + 1
else:
##判斷起始時間、終止時間引數是否符合要求
if initial_extract_time > dur:
raise NameError('initial extract time is larger than the video duration....')
if end_extract_time is not None:
if end_extract_time > dur:
raise NameError('end extract time is larger than the video duration....')
if initial_extract_time > end_extract_time:
raise NameError('end extract time is less than the initial extract time....')
##時間范圍內的每幀圖片都輸出
if extract_time_interval == -1:
if initial_extract_time > 0:
cap.set(cv2.CAP_PROP_POS_MSEC, (1000 * initial_extract_time))
try:
os.mkdir(pathOut)
except OSError:
pass
print('Converting a video into frames......')
if end_extract_time is not None:
N = (end_extract_time - initial_extract_time) * fps + 1
success = True
count = 0
while success and count < N:
success, image = cap.read()
if success:
if not isColor:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
print('Write a new frame1: {}, {}/{}'.format(success, count + 1, n_frames))
cv2.imwrite(os.path.join(pathOut, "{:010d}.jpg".format(count + 1)), image,
[int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality]) # save frame as JPEG file
count = count + 1
else:
success = True
count = 0
while success:
success, image = cap.read()
if success:
if not isColor:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
print('Write a new frame: {}, {}/{}'.format(success, count + 1, n_frames))
cv2.imwrite(os.path.join(pathOut, "{:010d}.jpg".format(count + 1)), image,
[int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality]) # save frame as JPEG file
count = count + 1
##判斷提取時間間隔設定是否符合要求
elif extract_time_interval > 0 and extract_time_interval < 1 / fps:
raise NameError('extract_time_interval is less than the frame time interval....')
elif extract_time_interval > (n_frames / fps):
raise NameError('extract_time_interval is larger than the duration of the video....')
##時間范圍內每隔一段時間輸出一張圖片
else:
try:
os.mkdir(pathOut)
except OSError:
pass
print('Converting a video into frames......')
if end_extract_time is not None:
N = (end_extract_time - initial_extract_time) / extract_time_interval + 1
success = True
count = 0
while success and count < N:
cap.set(cv2.CAP_PROP_POS_MSEC, (1000 * initial_extract_time + count * 1000 * extract_time_interval))
success, image = cap.read()
if success:
if not isColor:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
print('Write a new frame2: {}, {}th'.format(success, count + 1))
cv2.imwrite(os.path.join(pathOut, "{}_{:06d}.jpg".format(output_prefix, count + 1)), image,
[int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality]) # save frame as JPEG file
count = count + 1
else:
success = True
count = 0
while success:
cap.set(cv2.CAP_PROP_POS_MSEC, (1000 * initial_extract_time + count * 1000 * extract_time_interval))
success, image = cap.read()
if success:
if not isColor:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
print('Write a new frame3: {}, {}th'.format(success, count + 1))
cv2.imwrite(os.path.join(pathOut, "{}_{:06d}.jpg".format(output_prefix, count + 1)), image,
[int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality]) # save frame as JPEG file
count = count + 1
##### 測驗
# import cv2 as cv
# cap = cv.VideoCapture("H:\pyImage\cs.mp4")
pathIn = r'C:\Users\17864\Desktop\Python\binocularResult\calibration pictures\640Stable.avi'
video2frames(pathIn, only_output_video_info=True)
pathOut = r'C:\Users\17864\Desktop\Python\binocularResult\calibration pictures\data'
video2frames(pathIn, pathOut)
我們先要在train.py的當前路徑下新建檔案夾corridor_datasets,然后再在該檔案夾下創建2021_09_17/image_02/data/,得到的訓練圖片我們將放在上面data路徑下,在這之后我們需要將options.py下面的–data_path的默認引數從kitti修改為corridor_datasets,除此之外,我們還需要創建訓練集和驗證集的文本檔案并放置于splits/eigen_zhou/下面,為什么選擇eigen_zhou是因為原模型GitHub的README.md里說明了單目采用eigen_zhou,而雙目采用eigen_full,文本檔案的創建采用如下代碼:
# -*- coding: utf-8 -*-
"""
Created on Fri Sep 17 23:48:28 2021
@author: 17864
"""
import os
def makefile(path,content):
if os.path.exists(path):
if os.path.isdir(path):
f = open('C:/Users/17864/Desktop/train_files.txt','a+')
f.write(content)
f.write('\n')
f.seek(0)
read = f.readline()
f.close()
print(read)
else:
print('please input the dir name')
else:
print('the path is not exists')
path = r'C:\Users\17864\Desktop'
count = 1
while count < 2581:
content = r"2021_09_17 {} l".format(count)
makefile(path,content)
count = count + 1
創建完train_files.txt之后,我們可以創建一個train_files.txt的副本,并命名為val_files.txt,在這兩個檔案中我們需要把第一行(1)和最后一行(2580)刪掉,空行都不能留,這里的原因主要是單目幀序列訓練的時候我們需要輸入當前幀的前一幀和后一幀,而第一幀是沒有前一幀的,最后一幀是沒有后一幀的,到這里我們的資料集準備作業已經做完了,下面我們需要創建環境,
conda創建monodepth2訓練環境
首先在命令列運行
conda create -n monodepth2
conda activate monodepth2
創建并激活一個新的環境,剛創建完的環境是空的,我們需要在這個慷訓境下安裝各種第三方包,從README.md我們可以知道我們需要按照下面安裝pytorch,opencv等依賴,
conda install pytorch=0.4.1 torchvision=0.2.1 -c pytorch
pip install tensorboardX==1.4
conda install opencv=3.3.1 # just needed for evaluation
除了上面幾個之外,建議還安裝上scikit-image和IPython兩個依賴,這樣我們就可以開始我們的訓練和測驗了,
訓練命令
python train.py --model_name mono_model --num_epochs 50
解釋:這里訓練得到的模型會出現在用戶目錄下的tmp目錄中,如果覺得模型的loss降得差不多了,我們可以把models里面的對應權重(這里是weights_49)復制到train.py目錄下的models檔案夾中,然后如果需要測驗求圖片深度,我們可以按照README.md里的命令,按照對應的圖片名和模型名稱即可完成測驗,而測驗檔案夾里所有的圖片則可以使用下面的測驗命令,
測驗命令
python test_simple.py --image_path /public/home/lcc-dx01/monodepth2-master/corridor_datasets/2021_09_17/image_02/data(640test)/ --image_disp_path /public/home/lcc-dx01/monodepth2-master/corridor_datasets/2021_09_17/image_02/disp(640test)/ --model_name weights_49
解釋:我們把需要預測深度的圖片序列放到–image_path對應的檔案夾中,然后我們按照–image_disp_path創建好需要存放視差圖的檔案夾,運行上面測驗命令即可得到檔案夾下所有圖片的深度圖,這些幀序列還可以按照一定的幀率合成深度視頻,
我得到的效果如下
效果似乎很一般,如果知道是什么原因的歡迎交流!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/302319.html
標籤:其他
