Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
d3002b1
commit 261daad
Showing
24 changed files
with
2,376 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
dofile('opts.lua') | ||
dofile('util.lua') | ||
dofile('dataset.lua') | ||
|
||
opts.SCORES_FILES = #arg >= 1 and arg or {opts.PATHS.SCORES_PATTERN:format('trainval')} | ||
|
||
loaded = hdf5_load(opts.SCORES_FILES[1], {'subset', 'rois', 'labels', 'output'}) | ||
outputs = {} | ||
|
||
for i = 1, #opts.SCORES_FILES do | ||
outputs_i = hdf5_load(opts.SCORES_FILES[i], 'outputs') | ||
for output_field, scores in pairs(outputs_i) do | ||
outputs[output_field] = {} | ||
for exampleIdx = 1, #scores do | ||
outputs[output_field][exampleIdx] = (outputs[output_field][exampleIdx] or scores[exampleIdx]:clone():zero()):add(scores[exampleIdx]:div(#opts.SCORES_FILES)) | ||
end | ||
end | ||
end | ||
|
||
res = {training_MAP = dataset_tools.meanAP(loaded.output, loaded.labels)} | ||
for output_field, scores in pairs(outputs) do | ||
res[output_field] = {by_class = {}, _mean = corloc(dataset[loaded.subset], {scores, loaded.rois})} | ||
for classLabelInd, classLabel in ipairs(classLabels) do | ||
res[output_field].by_class[classLabels[classLabelInd]] = corloc(dataset[loaded.subset], {scores, loaded.rois}, classLabelInd) | ||
end | ||
end | ||
|
||
json_save(opts.PATHS.CORLOC, res) | ||
print('result in ' .. opts.PATHS.CORLOC) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
if opts.DATASET == 'VOC2007' or opts.DATASET == 'VOC2012' then | ||
dataset_tools = dofile('pascal_voc.lua') | ||
classLabels = dataset_tools.classLabels | ||
numClasses = dataset_tools.numClasses | ||
end | ||
|
||
dataset = torch.load(opts.PATHS.DATASET_CACHED) | ||
|
||
dofile('parallel_batch_loader.lua') | ||
dofile('example_loader.lua') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
dofile('opts.lua') | ||
dofile('util.lua') | ||
dofile('dataset.lua') | ||
threads = require 'threads' | ||
|
||
overlap_threshold = 0.4 | ||
score_threshold = 1e-3 / (2 * 5) | ||
output_field = 'output_prod' | ||
local subset = 'test' | ||
|
||
opts.SCORES_FILES = #arg >= 1 and arg or {opts.PATHS.SCORES_PATTERN:format(subset)} | ||
rois = hdf5_load(opts.SCORES_FILES[1], 'rois') | ||
|
||
scores = {} | ||
for i = 1, #opts.SCORES_FILES do | ||
scores_i = hdf5_load(opts.SCORES_FILES[i], 'outputs/' .. output_field) | ||
for exampleIdx = 1, #scores_i do | ||
scores[exampleIdx] = (scores[exampleIdx] or scores_i[exampleIdx]:clone():zero()):add(scores_i[exampleIdx]:div(#opts.SCORES_FILES)) | ||
end | ||
end | ||
|
||
local detrespath = dataset_tools.package_submission(opts.PATHS.DATA, dataset, opts.DATASET, subset, 'comp4_det', rois, scores, nms_mask(rois, scores, overlap_threshold, score_threshold)) | ||
local opts = opts | ||
|
||
if dataset['test'].objectBoxes == nil then | ||
print('detection mAP cannot be computed for ' .. opts.DATASET .. '. Quitting.') | ||
print('VOC submission saved in ' .. detrespath) | ||
os.exit(0) | ||
end | ||
|
||
res = {[output_field] = {_mean = nil, by_class = {}}} | ||
APs = torch.FloatTensor(numClasses):zero() | ||
|
||
jobQueue = threads.Threads(numClasses) | ||
for classLabelInd, classLabel in ipairs(classLabels) do | ||
jobQueue:addjob(function() | ||
os.execute(('matlab -nodisplay -nojvm -nosplash -r "classLabel = \'%s\'; cd(\'%s\'); addpath(\'VOCcode\'); VOCinit; VOCopts.testset = \'%s\'; VOCopts.detrespath = \'%s\'; [rec, prec, ap] = VOCevaldet_fast(VOCopts, \'comp4\', classLabel, false); dlmwrite(sprintf(VOCopts.detrespath, \'resu4\', classLabel), ap); quit;"'):format(classLabel, paths.dirname(opts.PATHS.VOC_DEVKIT_VOCYEAR), subset, detrespath)) | ||
return tonumber(io.open(detrespath:format('resu4', classLabel)):read('*all')) | ||
end, function(ap) res[output_field].by_class[classLabel] = ap; APs[classLabelInd] = ap; end) | ||
end | ||
jobQueue:synchronize() | ||
os.execute('[ -t 1 ] && reset') | ||
|
||
res[output_field]._mean = APs:mean() | ||
|
||
json_save(opts.PATHS.DETECTION_MAP, res) | ||
print('result in ' .. opts.PATHS.DETECTION_MAP) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
local ExampleLoader, parent = torch.class('ExampleLoader') | ||
|
||
function ExampleLoader:__init(dataset, example_loader_opts, channel_order, rgb_pixel_means) | ||
self.scales = {{608, 800}, {496, 656}, {400, 544}, {720, 960}, {864, 1152}} | ||
--self.scales = {{608, 800}, {368, 480}, {432, 576}, {528, 688}, {656, 864}, {912, 1200}} | ||
|
||
self.channel_order = {3, 2, 1} -- BGR because we use Caffe-derived models | ||
self.rgb_pixel_means = {122.7717, 115.9465, 102.9801} | ||
self.example_loader_opts = example_loader_opts | ||
self.dataset = dataset | ||
end | ||
|
||
local function table2d(I, J, elem_generator) | ||
local res = {} | ||
for i = 1, I do | ||
res[i] = {} | ||
for j = 1, J do | ||
res[i][j] = elem_generator(i, j) | ||
end | ||
end | ||
return res | ||
end | ||
|
||
local function subtract_mean(dst, src, channel_order, rgb_pixel_means) | ||
for c = 1, 3 do | ||
dst[c]:copy(src[channel_order[c]]):add(-rgb_pixel_means[channel_order[c]]) | ||
end | ||
end | ||
|
||
local function rescale(img, max_height, max_width) | ||
--local height_width = math.max(dhw_rgb:size(3), dhw_rgb:size(2)) | ||
--local im_scale = target_height_width / height_width | ||
local scale_factor = max_height / img:size(2) | ||
if torch.round(img:size(3) * scale_factor) > max_width then | ||
scale_factor = math.min(scale_factor, max_width / img:size(3)) | ||
end | ||
|
||
return image.scale(img, math.min(max_width, img:size(3) * scale_factor), math.min(max_height, img:size(2) * scale_factor)) | ||
end | ||
|
||
local function flip(images_j, rois_j) | ||
image.hflip(images_j, images_j) | ||
rois_j:select(2, 1):mul(-1):add(images_j:size(3)) | ||
rois_j:select(2, 3):mul(-1):add(images_j:size(3)) | ||
|
||
local tmp = rois_j:select(2, 1):clone() | ||
rois_j:select(2, 1):copy(rois_j:select(2, 3)) | ||
rois_j:select(2, 3):copy(tmp) | ||
end | ||
|
||
local function insert_dummy_dim1(...) | ||
for _, tensor in ipairs({...}) do | ||
tensor:resize(1, unpack(tensor:size():totable())) | ||
end | ||
end | ||
|
||
function ExampleLoader:makeBatchTable(batchSize, isTrainingPhase) | ||
local o = self:getPhaseOpts(isTrainingPhase) | ||
local num_jittered_copies = isTrainingPhase and 2 or (1 + (o.hflips and 2 or 1) * o.numScales) | ||
|
||
return table2d(batchSize, num_jittered_copies, function() return {torch.FloatTensor(), torch.FloatTensor(), torch.FloatTensor()} end) | ||
end | ||
|
||
function ExampleLoader:loadExample(exampleIdx, isTrainingPhase) | ||
local o = self:getPhaseOpts(isTrainingPhase) | ||
|
||
local labels_loaded = self.dataset[o.subset]:getLabels(exampleIdx) | ||
local rois_loaded = self.dataset[o.subset]:getProposals(exampleIdx) | ||
local jpeg_loaded = self.dataset[o.subset]:getJpegBytes(exampleIdx) | ||
local scales = o.scales or self.scales | ||
local channel_order, rgb_pixel_means = self.channel_order, self.rgb_pixel_means | ||
|
||
local scale_inds = isTrainingPhase and {0, torch.random(1, o.numScales)} or torch.range(0, o.numScales):totable() | ||
local hflips = isTrainingPhase and (o.hflips and torch.random(0, 1) or 0) or (o.hflips and 2 or 0) -- 0 is no_flip, 1 is do_flip, 2 is both | ||
local rois_perm = isTrainingPhase and torch.randperm(rois_loaded:size(1)) or torch.range(1, rois_loaded:size(1)) | ||
|
||
return function(indexInBatch, batchTable) | ||
image = image or require 'image' | ||
local img_original = image.decompressJPG(jpeg_loaded, 3, 'byte') | ||
local height_original, width_original = img_original:size(2), img_original:size(3) | ||
|
||
local rois_scale0 = rois_loaded:index(1, rois_perm:sub(1, math.min(rois_loaded:size(1), o.numRoisPerImage)):long()) | ||
rois_scale0[1]:copy(torch.FloatTensor{0, 0, width_original - 1, height_original - 1, 0.0}:sub(1, rois_scale0:size(2))) | ||
|
||
for j, scale_ind in ipairs(scale_inds) do | ||
local images, rois, labels = unpack(batchTable[indexInBatch][j]) | ||
|
||
local img_scaled = scale_ind == 0 and img_original:clone() or rescale(img_original, scales[scale_ind][1], scales[scale_ind][2]) | ||
local width_scaled, height_scaled = img_scaled:size(3), img_scaled:size(2) | ||
|
||
subtract_mean(images:resize(img_scaled:size()), img_scaled, channel_order, rgb_pixel_means) | ||
rois:cmul(rois_scale0, torch.FloatTensor{{width_scaled / width_original, height_scaled / height_original, width_scaled / width_original, height_scaled / height_original, 1.0}}:narrow(2, 1, rois_scale0:size(2)):contiguous():expandAs(rois_scale0)) | ||
labels:resize(labels_loaded:size()):copy(labels_loaded) | ||
|
||
if hflips == 1 then | ||
flip(images, rois) | ||
elseif scale_ind ~= 0 and hflips == 2 then | ||
local jj = #batchTable[indexInBatch] - j + 2 | ||
local images_flipped, rois_flipped, labels_flipped = unpack(batchTable[indexInBatch][jj]) | ||
images_flipped:resizeAs(images):copy(images) | ||
rois_flipped:resizeAs(rois):copy(rois) | ||
labels_flipped:resizeAs(labels):copy(labels) | ||
flip(images_flipped, rois_flipped) | ||
insert_dummy_dim1(images_flipped, rois_flipped, labels_flipped) | ||
end | ||
|
||
insert_dummy_dim1(images, rois, labels) | ||
end | ||
|
||
collectgarbage() | ||
end | ||
end | ||
|
||
function ExampleLoader:getNumExamples(isTrainingPhase) | ||
return self.dataset[self:getSubset(isTrainingPhase)]:getNumExamples() | ||
end | ||
|
||
function ExampleLoader:getPhaseOpts(isTrainingPhase) | ||
return isTrainingPhase and self.example_loader_opts['training'] or self.example_loader_opts['evaluate'] | ||
end | ||
|
||
function ExampleLoader:getSubset(isTrainingPhase) | ||
return self:getPhaseOpts(isTrainingPhase).subset | ||
end |
Oops, something went wrong.