目标:完成水下鱼类分割
使用的网络:
mpnet:Learning Motion Patterns in Videos
paper & code: http://thoth.inrialpes.fr/research/mpnet
DeepLabV2(ResNet-101):code: https://github.com/DrSleep/tensorflow-deeplab-resnet
前言:使用了一款记笔记的软件,幕布,风格极简,但保存代码还是差了一点。
另外这几天的鼓捣,经常上网上查资料,发现将自己遇到的问题和解决方法记录下来,
以后再遇到好解决,还可以帮助别人。
正文:
首先是mpnet的实现
一 torch的安装
网址:百度下torch就出来了,itorch也是,安装之前先看看为下边这两段话。
预训练使用的数据集非常大,论文使用的显卡计算能力非常强大,我这里资源有限,所以使用预训练好的模型就可以了。
整个代码都是用lua语言写的,所以先安装torch,为方便调试使用了itorch;刚开始显卡不给力,出现以下的错误
THCudaCheck FAIL file=/home/nvidia/torch/extra/cunn/lib/THCUNN/generic/SpatialUpSamplingBilinear.cu line=63 error=7 : too many resources requested for launch
/home/nvidia/torch/install/bin/luajit: ...e/nvidia/torch/install/share/lua/5.1/threads/threads.lua:179: [thread 1 endcallback] /home/nvidia/torch/install/share/lua/5.1/nn/Container.lua:67:
好像是显卡的线程数不够了,
参考:https://stackoverflow.com/questions/26201172/cuda-too-many-resources-requested-for-launch
就换了一款自带牛x显卡(TITAN Black,作图像处理,还没听说有人用这个。。。。)的电脑,重新安装了torch,导入模型时发现了一个问题,模型导入过程中,出现out of memory,使用itorch一句一句的排查才发现是模型导入的问题,之前以为是数据的batch太大,后来为把batch设置成1,还是out of memory(其实不需要一句一句的查,看错误位置就可以了,但是不敢相信模型还能大到这种程度),就去网上查了查。
网址:http://blog.csdn.net/ycz28/article/details/52300267
关于luaJIT内存限制的说法很多,很多人说lutJIT不如lua5.2好用,所以就卸载了luaJIT,使用了lua5.2,如何将当前JIT替换为lua网址:https://github.com/torch/distro
注意clean.sh后要重新安装依赖,即install-deps
网慢的话,OpenBLAS装不上
二 修改部分程序
首先是训练集的输入路径,
修改mpnet/from_batch_angle.lua文件下的load_dataset 函数
function load_dataset(frameListFile)--输入应该是'trainList.txt',类似训练集图片索引的文件
local file = io.open("/trainList.txt的上级路径/" .. frameListFile)
local trainList = {}
if file then
for line in file:lines() do
table.insert(trainList, line)
end
else
print('File not found')
end
order = torch.randperm(#trainList)--打乱训练集中数据的顺序
return trainList
end
修改同一文件下的get_batch函数
count = 1;
order = 0;
function get_batch(batch_size)
local batch_ims = torch.Tensor(batch_size, 2, 200, 360)--通道数是2,因为光流计算会输出一个角度图,和一个幅度图
local batch_labels = torch.Tensor(batch_size, 1, 100, 180)
for i = 1, batch_size do
local flowPath, path;
local f = io.open(trainList[count], "r")
repeat--删掉了repeat这段代码,没啥用,浪费时间
path = trainList[order[count]]
flowPath = string.gsub(path, 'motion_labels', 'flow_angles_no_artifacts');
flowPath = string.gsub(flowPath, 'png', 'jpg');
local flowAnglePath = string.gsub(flowPath, 'left/', 'left/angleField_')
flowAnglePath = string.gsub(flowAnglePath, 'right/', 'right/angleField_')
if f then
io.close(f)
end
f = io.open(flowAnglePath, "r")
count = count + 1;
if count > #trainList then
count = 1
order = torch.randperm(#trainList)
end
until f
io.close(f)
--以下代码中的路径只要保证和自己数据集下路径一致就可以了,不了解的地方可以参考test_DAVIS.lua
local labels = image.load(path)
local flowAnglePath = string.gsub(flowPath, 'left/', 'left/angleField_')
flowAnglePath = string.gsub(flowAnglePath, 'right/', 'right/angleField_')
local flowAngle = image.load(flowAnglePath)
local flowMagPath = string.gsub(flowPath, 'left/', 'left/magField_')
flowMagPath = string.gsub(flowMagPath, 'right/', 'right/magField_')
local flowMag = image.load(flowMagPath)
local flow = torch.cat(flowAngle, flowMag, 1)
local minMaxPath = string.gsub(flowPath, '%d+.jpg', 'minmax.txt')
local file = io.open(minMaxPath)
local minmaxes = {}
local ind = 1
if file then
for line in file:lines() do
local min_x, max_x, min_y, max_y = unpack(line:split(" "))
minmaxes[ind] = {min_x, max_x, min_y, max_y}
ind = ind + 1
end
else
print('File not found!!!!!!!!')
end
io.close(file)
local frameIndStart, frameIndEnd = string.find(path, '%d+.png')
local frameInd = tonumber(path:sub(frameIndStart, frameIndEnd - 4)) - 5
local mm = minmaxes[frameInd]
if not mm then
print(path)
end
flow = image.scale(flow, 480, 270, 'simple')
labels = image.scale(labels, 480, 270, 'simple')
flow[{{1}, {}, {}}] = flow[{{1}, {}, {}}] * (mm[2] - mm[1]) + mm[1]
flow[{{2}, {}, {}}] = flow[{{2}, {}, {}}] * (mm[4] - mm[3]) + mm[3]
flow[{{2}, {}, {}}]:div(math.sqrt(math.pow(960, 2) + math.pow(540, 2)) / 6)--图像的维度
local h1 = math.ceil(torch.uniform(1e-2, 270 - 200))
local w1 = math.ceil(torch.uniform(1e-2, 480 - 360))
flow = flow[{{}, {h1, h1 + 200 - 1}, {w1, w1 + 360 - 1}}]
labels = labels[{{}, {h1, h1 + 200 - 1}, {w1, w1 + 360 - 1}}]
if math.random() > 0.5 then
flow = image.flip(flow:contiguous(), 3);
labels = image.flip(labels:contiguous(), 3);
end
labels = image.scale(labels, 180, 100, 'simple')
batch_ims[i] = flow
batch_labels[i] = labels
end
return batch_ims, batch_labels
end
修改segment_FT3D_angle.lua及test_DAVIS.lua函数里的路径
require 'image'
require 'lfs'
require 'cunn'
require 'nngraph'
function segment(model, rgbPath, setting)
local flowPath = string.gsub(rgbPath, 'JPEGImages', 'OpticalFlow');--修改路径
local fileName = string.gsub(flowPath, '%d+.jpg', 'minmax.txt')
local file = io.open(fileName)
local minmaxes = {}
local ind = 1;
if file then
for line in file:lines() do
local min_x, max_x, min_y, max_y = unpack(line:split(" "))
minmaxes[ind] = {min_x, max_x, min_y, max_y}
ind = ind + 1
end
else
print('File not found!!!!!!!!')
end
io.close(file)
local resized_width = 424
local resized_height = 232
local batch = torch.Tensor(1, 2, resized_height, resized_width);
local frameNum = tonumber(flowPath:match('(%d+).jpg')) + 1
local mm = minmaxes[frameNum]
local angleFileName = string.gsub(flowPath, '(%d+).jpg', 'angleField_%1.jpg');
local magFileName = string.gsub(flowPath, '(%d+).jpg', 'magField_%1.jpg');
local f = io.open(angleFileName, "r")
if not f then
return nil
end
io.close(f)
local flowAngle = image.load(angleFileName)
local flowMag = image.load(magFileName)
local flowFrame = torch.cat(flowAngle, flowMag, 1)
flowFrame = image.scale(flowFrame, resized_width, resized_height, 'simple');
flowFrame[{{1}, {}, {}}] = flowFrame[{{1}, {}, {}}] * (mm[2] - mm[1]) + mm[1]
flowFrame[{{2}, {}, {}}] = flowFrame[{{2}, {}, {}}] * (mm[4] - mm[3]) + mm[3]
flowFrame[{{1}, {}, {}}]:cmul(flowFrame[{{2}, {}, {}}]:gt(1):double())
flowFrame[{{2}, {}, {}}]:div(math.sqrt(math.pow(854, 2) + math.pow(480, 2)) / 6)
batch[1] = flowFrame;
batch = batch:float():cuda()
local outputs = model:forward(batch)
local objPath = string.gsub(rgbPath, 'JPEGImages', 'Objectness100');
objPath = string.gsub(objPath, '(%d+).jpg', '%1.png');
local objectness = image.load(objPath)
local preds
preds = torch.Tensor(1, 480, 854)
local pred = outputs[1];
pred = nn.utils.recursiveType(pred, 'torch.DoubleTensor')
pred = image.scale(pred, 854, 480)
local predRaw = pred
objectness:div(objectness:max()):add(0.5)
pred:cmul(objectness)
pred:clamp(0, 1)
preds[1] = pred
local resultPath = string.gsub(rgbPath, 'JPEGImages', 'Results/Segmentations');
local resultPath = string.gsub(resultPath, '480p', '480p/' .. setting);
local resultPath = string.gsub(resultPath, 'jpg', 'png');
local resultDir = string.gsub(resultPath, '%d+.png', '');
if not path.exists(resultDir) then
os.execute("mkdir " .. resultDir)
end
image.save(resultPath, torch.round(preds));
local resultPathRaw = string.gsub(resultPath, '(%d+).png', 'raw_%1.png');
image.save(resultPathRaw, predRaw);
end