文章目录
- 引言
- 简介
- 环境配置
- 1、numpy 安装
- 2、matplotlib 安装
- 3、cv2 安装,即opencv-python安装
- 4、scipy 安装
- 5、theano安装
- 7、flip_filters不再支持
- 数据问题
- 密度图生成
- 注意
引言
SwitchCNN是我看的比较早的一篇多列密集计数网络了,但是其网络实现因各种问题我一直没有复现,现如今因Crowd Counting综述讲解,我不禁又沉下心来继续对其进行复现,特此记录,避免后来者多走弯路。
简介
Article:Switching Convolutional Neural Network for Crowd Counting
Code: crowd-counting-cnn
环境配置
其实,环境配置我尝试比较久,因各种问题都歇菜了,从python 3.10 到3.6我都试了一遍,发现会出现各种问题。具体问题,尝试过的就知道了。最终,我也是在尝试中看到了有些错误,如cPickle等语言版本问题,才选择了python 2.7 环境实现了SwitchCNN的运行(不排除python3运行的可行性,但是修改我个人觉得有点麻烦)。
ok,我们开始代码的运行,首先,我们先把Anaconda 环境和Pycharm Project环境搭建好,Anaconda创建环境语句如下:
conda create -n SwitchCNN-Test python=2.7
Proceed: Y ,创建完毕。
Project-File-Setting-Project:Python Interpreter
搭建完基础环境后我们就开始运行,并为环境进行包的添加以及代码的修改。
开始之前,我们先看下README.TXT
SCNN README
-------------
To test SCNN on trained model:
[1] Create test set by executing 'dataset/create_test_set.m'.
[2] Run 'src/test_scnn.py'.
To train SCNN:
[1] Create dataset by executing 'dataset/create_datasets.m'.
[2] Run differential_train.py to perform differential training.
[3] Run coupled_train.py to perform coupled training.
create_datasets.m代码如下:
create_test_set;
create_train_set;
system('python make_validation_set.py');
意思先进行数据的创建,但有个问题是我们打开dataset/create_train_set()后运行会出现:create_density()函数未定义的现象。m
文件代码如下:
% Creates train set
function create_train_set()
image_fold = './ST_part_A/train_data/images';
gt_fold = './ST_part_A/train_data/ground_truth';
final_image_fold = './train/images';
final_gt_fold = './train/gt';
mkdir(final_image_fold);
mkdir(final_gt_fold);
jpgFiles = dir([image_fold, '/*.jpg']);
numfiles = length(jpgFiles);
parfor i = 1: numfiles
[~, f_1] = fileparts(jpgFiles(i).name);
f = sprintf('%s.jpg',f_1);
I = imread(fullfile(image_fold, f));
file_name = f_1;
mat_filename = sprintf('GT_%s.mat', file_name);
ann = load(fullfile(gt_fold, mat_filename));
gt = ann.image_info{1,1}.location;
count = 1;
% generate density map
d_map_h = floor(floor(double(size(I, 1)) / 2.0) / 2.0);
d_map_w = floor(floor(double(size(I, 2)) / 2.0) / 2.0);
% Density Map with Geometry-Adaptive Kernels (see MCNN code:
% Single-Image Crowd Counting via Multi-Column Convolutional
% Neural Network; CVPR 2017)
d_map = create_density(gt / 4.0, d_map_h, d_map_w);
p_h = floor(double(size(I, 1)) / 3.0);
p_w = floor(double(size(I, 2)) / 3.0);
d_map_ph = floor(floor(p_h / 2.0) / 2.0);
d_map_pw = floor(floor(p_w / 2.0) / 2.0);
% create overlapping patches of images and density maps
py = 1;
py2 = 1;
for j = 1: 3
px = 1;
px2 = 1;
for k = 1: 3
final_image = double(I(py: py + p_h - 1, px: px + p_w - 1, :));
final_gt = d_map(py2: py2 + d_map_ph - 1, px2: px2 + d_map_pw - 1);
px = px + p_w;
px2 = px2 + d_map_pw;
if size(final_image, 3) < 3
final_image = repmat(final_image, [1, 1, 3]);
end
image_name = sprintf('%s_%d.jpg', file_name, count);
gt_name = sprintf('%s_%d.mat', file_name, count);
imwrite(uint8(final_image), fullfile(final_image_fold, image_name));
do_save(fullfile(final_gt_fold, gt_name), final_gt);
count = count + 1;
end
py = py + p_h;
py2 = py2 + d_map_ph;
end
end
end
function do_save(gt_name, final_gt)
save(gt_name, 'final_gt');
end
其实,这个问题作者已经在github代码发布时解释了,解释如下:
也就是说创建密度图的代码需要大家自行添加。有现成的数据谁会再重新生成呢,因为我有自己的数据,因此,我就直接用了私有的数据,而没有用公共数据的数据,我的ground truth数据分辨率同输入图像数据(就是因为这个数据问题,致使我各种修改,这是后话)。
ok,让我们设置好数据的路径,然后开始我们复现的行程。
1、numpy 安装
pip install numpy
2、matplotlib 安装
pip install matplotlib
3、cv2 安装,即opencv-python安装
之前,我们安装opencv-python时碰到一些问题,这在‘cv2’、PIL、torch、torchivision一文中我们已经介绍了如何解决,如下
这里需要注意的是,我们的python=2.7,因此,opencv-python我们在安装时要匹配2.7,chatGPT给出了答案(真是至宝啊!!!):
安装命令如下:
pip install opencv-python==3.4.5.20
4、scipy 安装
pip install scipy
5、theano安装
pip install theano
6、lasagne安装
pip install lasagne
出现错误(来源与lasagne)
根据chatGPT给的建议,我首先采用了第一种方式,但是发现这种方法修改也会比较麻烦,并最终选择2,即降低lasagne的版本为1.0.5。
pip install theano==1.0.5
但运行仍然会出现上述错误,然后再次chatGPT发现答案又变化了~,耍我玩呢
。这次给的建议时安装兼容的Theano和Lasagne。
pip install theano==0.8.2
pip install lasagne==0.1
嗯嗯,错误消除了。
7、flip_filters不再支持
这个问题chatGPT给出的解释是,现在的版本已经不再支持flip_filters这个参数了,因此,我们需要将networks.py文件中的这个参数全部删除掉。
为了方便,我这里直接将networks.py文件代码附上,方便大家直接复制粘贴:
# networks.py
# Defines all the networks of SCNN
import numpy as np
import theano
import theano.tensor as T
import lasagne
from lasagne.layers import InputLayer
from lasagne.layers import DenseLayer
from lasagne.layers import MaxPool2DLayer as PoolLayer
from lasagne.layers import Conv2DLayer as ConvLayer
def std_conv_layer(input, num_filters, filter_shape, pad = 'same'):
return ConvLayer(input, num_filters, filter_shape,
pad = pad,
W = lasagne.init.Normal(std = 0.01, mean = 0.0))
# 9x9 Regressor (R1)
class shallow_net_9x9():
def __init__(self, input = None, name = 'shallow_9x9'):
if input is None:
input = T.tensor4()
self.input = input
self.name = name
net = {}
net['input'] = InputLayer(shape = (None, 1, None, None),
input_var = self.input)
net['conv1_1'] = std_conv_layer(net['input'], 16, 9)
net['pool1'] = PoolLayer(net['conv1_1'], 2)
net['conv1_2'] = std_conv_layer(net['pool1'], 32, 7)
net['pool2'] = PoolLayer(net['conv1_2'], 2)
net['conv1_3'] = std_conv_layer(net['pool2'], 16, 7)
net['conv1_4'] = std_conv_layer(net['conv1_3'], 8, 7)
net['conv'] = std_conv_layer(net['conv1_4'], 1, 1)
self.net = net
self.output_layer = net['conv']
self.train_output = lasagne.layers.get_output(self.output_layer)
self.test_output = lasagne.layers.get_output(self.output_layer,
deterministic = True)
self.parameters = lasagne.layers.get_all_params(self.output_layer,
trainable=True)
# 7x7 Regressor (R2)
class shallow_net_7x7():
def __init__(self, input = None, name = 'shallow_7x7'):
if input is None:
input = T.tensor4()
self.input = input
self.name = name
net = {}
net['input'] = InputLayer(shape = (None, 1, None, None),
input_var = self.input)
net['conv2_1'] = std_conv_layer(net['input'], 20, 7)
net['pool2_1'] = PoolLayer(net['conv2_1'], 2)
net['conv2_2'] = std_conv_layer(net['pool2_1'], 40, 5)
net['pool2_2'] = PoolLayer(net['conv2_2'], 2)
net['conv2_3'] = std_conv_layer(net['pool2_2'], 20, 5)
net['conv2_4'] = std_conv_layer(net['conv2_3'], 10, 5)
net['conv'] = std_conv_layer(net['conv2_4'], 1, 1)
self.net = net
self.output_layer = net['conv']
self.train_output = lasagne.layers.get_output(self.output_layer)
self.test_output = lasagne.layers.get_output(self.output_layer,
deterministic = True)
self.parameters = lasagne.layers.get_all_params(self.output_layer,
trainable=True)
# 5x5 Regressor (R3)
class shallow_net_5x5():
def __init__(self, input = None, name = 'shallow_5x5'):
if input is None:
input = T.tensor4()
self.input = input
self.name = name
net = {}
net['input'] = InputLayer(shape = (None, 1, None, None),
input_var = self.input)
net['conv3_1'] = std_conv_layer(net['input'], 24, 5)
net['pool3_1'] = PoolLayer(net['conv3_1'], 2)
net['conv3_2'] = std_conv_layer(net['pool3_1'], 48, 3)
net['pool3_2'] = PoolLayer(net['conv3_2'], 2)
net['conv3_3'] = std_conv_layer(net['pool3_2'], 24, 3)
net['conv3_4'] = std_conv_layer(net['conv3_3'], 12, 3)
net['conv'] = std_conv_layer(net['conv3_4'], 1, 1)
self.net = net
self.output_layer = net['conv']
self.train_output = lasagne.layers.get_output(self.output_layer)
self.test_output = lasagne.layers.get_output(self.output_layer,
deterministic = True)
self.parameters = lasagne.layers.get_all_params(self.output_layer,
trainable=True)
# Switch classifier
class deep_patch_classifier():
def __init__(self, input = None, name = 'deep_patch_classifier'):
if input is None:
input = T.tensor4()
self.input = input
self.name = name
rgb_means = T.as_tensor_variable(\
np.array([104.008, 116.669, 122.675],
dtype = theano.config.floatX));
mean_sub_input = T.tile(self.input, [1, 3, 1, 1])
mean_sub_input -= rgb_means.dimshuffle('x', 0, 'x', 'x')
net = {}
net['input'] = InputLayer(shape = (None, 3, None, None),
input_var = mean_sub_input)
net['conv1_1'] = ConvLayer(
net['input'], 64, 3, pad=1,
W = lasagne.init.Normal(std=0.01, mean=0.0))
net['conv1_2'] = ConvLayer(
net['conv1_1'], 64, 3, pad=1,
W = lasagne.init.Normal(std=0.01, mean=0.0))
net['pool1'] = PoolLayer(net['conv1_2'], 2)
net['conv2_1'] = ConvLayer(
net['pool1'], 128, 3, pad=1,
W = lasagne.init.Normal(std=0.01, mean=0.0))
net['conv2_2'] = ConvLayer(
net['conv2_1'], 128, 3, pad=1,
W = lasagne.init.Normal(std=0.01, mean=0.0))
net['pool2'] = PoolLayer(net['conv2_2'], 2)
net['conv3_1'] = ConvLayer(
net['pool2'], 256, 3, pad=1,
W = lasagne.init.Normal(std=0.01, mean=0.0))
net['conv3_2'] = ConvLayer(
net['conv3_1'], 256, 3, pad=1,
W = lasagne.init.Normal(std=0.01, mean=0.0))
net['conv3_3'] = ConvLayer(
net['conv3_2'], 256, 3, pad=1,
W = lasagne.init.Normal(std=0.01, mean=0.0))
net['pool3'] = PoolLayer(net['conv3_3'], 2)
net['conv4_1'] = ConvLayer(
net['pool3'], 512, 3, pad=1,
W = lasagne.init.Normal(std=0.01, mean=0.0))
net['conv4_2'] = ConvLayer(
net['conv4_1'], 512, 3, pad=1,
W = lasagne.init.Normal(std=0.01, mean=0.0))
net['conv4_3'] = ConvLayer(
net['conv4_2'], 512, 3, pad=1,
W = lasagne.init.Normal(std=0.01, mean=0.0))
net['pool4'] = PoolLayer(net['conv4_3'], 2)
net['conv5_1'] = ConvLayer(
net['pool4'], 512, 3, pad=1,
W = lasagne.init.Normal(std=0.01, mean=0.0))
net['conv5_2'] = ConvLayer(
net['conv5_1'], 512, 3, pad=1,
W = lasagne.init.Normal(std=0.01, mean=0.0))
net['conv5_3'] = ConvLayer(
net['conv5_2'], 512, 3, pad=1,
W = lasagne.init.Normal(std=0.01, mean=0.0))
net['pool5'] = PoolLayer(net['conv5_3'], 2)
net['gap'] = lasagne.layers.GlobalPoolLayer(net['pool5'])
net['fc'] = DenseLayer(net['gap'], num_units=512)
net['softmax'] = DenseLayer(net['fc'], num_units=3,
nonlinearity=lasagne.nonlinearities.softmax)
self.output_layer = net['softmax']
self.net = net
self.train_output = lasagne.layers.get_output(net['softmax'])
self.test_output = lasagne.layers.get_output(net['softmax'], deterministic=True)
self.parameters = lasagne.layers.get_all_params(net['softmax'],
trainable=True)
# Create and compile theano graph for all the networks
def create_network_functions(networks):
momentum = 0.9
weight_decay = 0.0005
run_funcs = []
test_funcs = []
train_funcs = []
print 'Compiling theano functions...'
for i, net in enumerate(networks):
print ' > ' + net.name + '...'
run_funcs.append(theano.function(inputs = [net.input],
outputs = net.test_output))
if i == 0:
Y = T.lvector()
train_loss = lasagne.objectives.categorical_crossentropy(net.train_output, Y).mean()
test_loss = lasagne.objectives.categorical_crossentropy(net.test_output, Y).mean()
else:
Y = T.tensor4()
train_loss = lasagne.objectives.squared_error(net.train_output, Y).mean()
test_loss = lasagne.objectives.squared_error(net.test_output, Y).mean()
test_funcs.append(theano.function(inputs = [net.input, Y],
outputs = [test_loss, net.test_output]))
learning_rate = T.scalar()
updates = lasagne.updates.momentum(
train_loss, net.parameters, learning_rate = learning_rate, momentum=0.9)
train_funcs.append(theano.function(
inputs = [net.input, Y, learning_rate],
outputs = train_loss,
updates = updates))
print 'Done'
return (train_funcs, test_funcs, run_funcs)
数据问题
上述问题解决后,貌似网络可以运行了,但不幸的是又又出现了以下问题:
啥意思呢?这个问题其实困扰我蛮久的,我用chatGPT进行了咨询,得到了如下解释:
查看网络我们发现执行的是test_fn,这个函数是什么呢?这个函数在networks.py文件中的create_network_function()函数做了如下定义:
Y = T.tensor4()
train_loss = lasagne.objectives.squared_error(net.train_output, Y).mean()
test_loss = lasagne.objectives.squared_error(net.test_output, Y).mean()
test_funcs.append(theano.function(inputs = [net.input, Y],
outputs = [test_loss, net.test_output]))
这里调用的是theano.function用于图计算函数,theano.function(…): 这是 Theano 中的一个函数,用于创建一个可以计算指定输入的输出的函数。你可以把它想象成一个将某些计算逻辑封装起来,以便可以在后续调用时执行的工具。那这个函数的具体功能就是计算test_loss,也就是说输入的两个参量应当是模拟值和真实值,错误表示两个输入的大小是不一致的。
其实这个问题在运行MCNN的时候是不存在的,即使我的ground truth数据没有进行下采样。但在SwitchCNN中需要将ground truth进行下采样,因为网络分类的时候是基于MCNN的,即存在两次池化,每次采用2*2的池化操作,这样我们模拟得到的GT应当是原来的1/4,换句话说,我们在生成密度图时需要将ground truth变为原来的1/4。
此外,我们还需要做的一点是,SwitchCNN也采用了MCNN中patch的操作方法,这一点在test_scnn.py代码中也有体现,如下:
def test_scnn(test_funcs, dataset, do_switching = True):
num_patches = 9
num_subnet = len(test_funcs) - 1
losses = np.zeros(num_subnet + 2)
count_losses = np.zeros_like(losses)
mae_image = np.zeros_like(losses)
switch_stat = np.zeros(num_subnet)
pc_switch_stat = np.zeros(num_subnet)
pc_switch_error = 0.0
patch_count_accumulator_tmp = np.zeros((num_subnet + 2, 2))
loss_tmp = np.zeros(num_subnet)
count_tmp = np.zeros(num_subnet)
patch_tmp = np.zeros((num_subnet, 2))
patch_count = 0
image_count = 0
for i, (X, Y) in enumerate(dataset):
for j, test_fn in enumerate(test_funcs[1: ]):
loss_tmp[j], Y_subnet = test_fn(X, Y)
patch_tmp[j, 0] = np.sum(Y_subnet)
patch_tmp[j, 1] = np.sum(Y)
patch_count_accumulator_tmp[1 + j, 0] += patch_tmp[j, 0]
patch_count_accumulator_tmp[1 + j, 1] += patch_tmp[j, 1]
count_tmp[j] = np.abs(patch_tmp[j, 0] - patch_tmp[j, 1])
Y_pc = np.argmin(count_tmp)
losses[-1] += loss_tmp[Y_pc]
count_losses[-1] += count_tmp[Y_pc]
patch_count_accumulator_tmp[-1, 0] += patch_tmp[Y_pc, 0]
patch_count_accumulator_tmp[-1, 1] += patch_tmp[Y_pc, 1]
# Switching
if do_switching:
switch_stat[Y_pc] += 1
pc_loss, Y_pc_pred = test_funcs[0](X, np.array([Y_pc]))
Y_pc_pred = np.argmax(Y_pc_pred, axis = 1)[0]
pc_switch_stat[Y_pc_pred] += 1
if Y_pc_pred != Y_pc:
pc_switch_error += 1.0
losses[0] += pc_loss
patch_count_accumulator_tmp[0, 0] += patch_tmp[Y_pc_pred, 0]
patch_count_accumulator_tmp[0, 1] += patch_tmp[Y_pc_pred, 1]
losses[1: -1] += loss_tmp
count_losses[1: -1] += count_tmp
patch_count += 1
# Compute MAE
if patch_count >= num_patches:
patch_count = 0
mae_image += np.abs(patch_count_accumulator_tmp[:, 0] - \
patch_count_accumulator_tmp[:, 1])
patch_count_accumulator_tmp[:, :] = 0
image_count += 1
assert(patch_count == 0)
i += 1
print i, image_count
losses /= i
count_losses /= i
switch_stat /= i
pc_switch_stat /= i
pc_switch_error /= i
mae_image /= image_count
# Printing Results
txt = ''
loss_names = ['SCNN', 'R1', 'R2', 'R3', 'SCNN_ideal']
if not do_switching:
loss_names = loss_names[1: ]
count_losses = count_losses[1: ]
losses = losses[1: ]
mae_image = mae_image[1: ]
txt += '\n\tPer_Patch mae [l2 loss]: '
for i, j, k in zip(loss_names, count_losses, losses):
txt += ('%s: %.12f [%.12f], ' % (i, j, k))
txt += '\n\tMAE_Stat: '
for i, j in zip(loss_names, mae_image):
txt += ('%s: %.12f, ' % (i, j))
if do_switching:
txt += '\n\tSwitch_Stat: '
for i, j, k in zip(loss_names[1: -1], pc_switch_stat, switch_stat):
txt += ('%s: %f%% [%f%%], ' % (i, j * 100.0, k * 100.0))
txt += '\n\tSwitch_Error: %f%%' % (pc_switch_error * 100.0)
return mae_image[0], mae_image[-1], txt
return 0.0, mae_image[-1], txt
密度图生成
基于上述原因,我还是采用了在原有代码的基础上,对密度图的生成代码进行了复现,最简单的方式就是chatGPT,你懂的,不用白不用🐶。为了便于复现代码,我直接将数据创建代码粘贴如下:
% Creates train set
function create_train_set()
image_fold = './train/Images';
gt_fold = './train/anno';
final_image_fold = './train/patch_images';
final_gt_fold = './train/patch_gt_mat';
mkdir(final_image_fold);
mkdir(final_gt_fold);
jpgFiles = dir([image_fold, '/*.jpg']);
numfiles = length(jpgFiles);
parfor i = 1: numfiles
[~, f_1] = fileparts(jpgFiles(i).name);
f = sprintf('%s.jpg',f_1);
I = imread(fullfile(image_fold, f));
file_name = f_1;
mat_filename = sprintf('%s.mat', file_name);
ann = load(fullfile(gt_fold, mat_filename));
gt = ann.image_info{1,1}.location;
count = 1;
% generate density map
d_map_h = floor(floor(double(size(I, 1)) / 2.0) / 2.0);
d_map_w = floor(floor(double(size(I, 2)) / 2.0) / 2.0);
% Density Map with Geometry-Adaptive Kernels (see MCNN code:
% Single-Image Crowd Counting via Multi-Column Convolutional
% Neural Network; CVPR 2017)
d_map = create_density(gt / 4.0, d_map_h, d_map_w);
% gt_name = sprintf('GT_%s.mat', file_name);
% do_save(fullfile(final_gt_fold, gt_name), d_map);
p_h = floor(double(size(I, 1)) / 3.0);
p_w = floor(double(size(I, 2)) / 3.0);
d_map_ph = floor(floor(p_h / 2.0) / 2.0);
d_map_pw = floor(floor(p_w / 2.0) / 2.0);
% create overlapping patches of images and density maps
py = 1;
py2 = 1;
for j = 1: 3
px = 1;
px2 = 1;
for k = 1: 3
final_image = double(I(py: py + p_h - 1, px: px + p_w - 1, :));
final_gt = d_map(py2: py2 + d_map_ph - 1, px2: px2 + d_map_pw - 1);
px = px + p_w;
px2 = px2 + d_map_pw;
if size(final_image, 3) < 3
final_image = repmat(final_image, [1, 1, 3]);
end
image_name = sprintf('%s_%d.jpg', file_name, count);
gt_name = sprintf('%s_%d.mat', file_name, count);
imwrite(uint8(final_image), fullfile(final_image_fold, image_name));
do_save(fullfile(final_gt_fold, gt_name), final_gt);
count = count + 1;
end
py = py + p_h;
py2 = py2 + d_map_ph;
end
end
end
function do_save(gt_name, final_gt)
save(gt_name, 'final_gt');
end
function density_map = create_density(gt, d_map_h, d_map_w)
% 初始化密度图为全零矩阵
density_map = zeros(d_map_h, d_map_w);
% 获取注释点的数量
num_gt_points = size(gt, 1);
% 如果没有注释点,直接返回零密度图
if num_gt_points == 0
return;
end
% 如果只有一个注释点,将整个密度分布在该点上
if num_gt_points == 1
x = max(1, min(d_map_w, round(gt(1, 1))));
y = max(1, min(d_map_h, round(gt(1, 2))));
density_map(y, x) = 1;
return;
end
% 根据注释点生成密度图
for i = 1:num_gt_points
% 获取当前注释点的坐标
x = min(d_map_w, max(1, round(gt(i, 1))));
y = min(d_map_h, max(1, round(gt(i, 2))));
% 设置高斯核的大小,根据邻近点的平均距离调整
size_gaussian = 15; % 默认高斯核大小
distances = pdist2(gt, gt(i, :));
distances = sort(distances);
if num_gt_points > 3
size_gaussian = floor(mean(distances(2:4)) / 2);
end
if size_gaussian < 0
size_gaussian = 15;
sigma = size_gaussian/4;
% 生成高斯核
gaussian = fspecial('gaussian', [size_gaussian, size_gaussian], sigma);
% 计算高斯核在密度图中的位置
x1 = max(1, x - floor(size_gaussian / 2));
y1 = max(1, y - floor(size_gaussian / 2));
x2 = min(d_map_w, x + floor(size_gaussian / 2));
y2 = min(d_map_h, y + floor(size_gaussian / 2));
% 调整高斯核的边界以避免越界
g_x1 = max(1, 2 - (x - floor(size_gaussian / 2)));
g_y1 = max(1, 2 - (y - floor(size_gaussian / 2)));
g_x2 = g_x1 + (x2 - x1);
g_y2 = g_y1 + (y2 - y1);
% 确保子矩阵的大小一致并检查是否越界
if g_x2 <= size(gaussian, 2) && g_y2 <= size(gaussian, 1) ...
&& (x2 - x1 + 1) == (g_x2 - g_x1 + 1) && (y2 - y1 + 1) == (g_y2 - g_y1 + 1)
% 将高斯核添加到密度图中
density_map(y1:y2, x1:x2) = density_map(y1:y2, x1:x2) + gaussian(g_y1:g_y2, g_x1:g_x2);
end
end
end
注意
代码运行时还会出现以下错误:
1、 保存文件若未创建文件夹,则需要在save_nets中对代码进行如下修改
# Save network weights
def save_nets(files, networks):
print ('Saving nets...')
for file_name in files:
filepath = os.path.dirname(file_name)
if not os.path.exists(filepath):
os.makedirs(filepath)
for file_name, net in zip(files, networks):
fp = open(file_name, 'wb')
params = lasagne.layers.get_all_param_values(net.output_layer)
cPickle.dump(params, fp, protocol = cPickle.HIGHEST_PROTOCOL)
print (' >', net.name)
fp.close()
print (' > Done.')
2、 matplotlib不支持jpg格式,需要在differential_train.py文件中进行如下代码修改:
p1, = plt.plot(min_mae_history[: epoch + 1])
# plt.savefig(os.path.join(log_path, 'min_mae_history.jpg')) # matplotlib不支持jpg格式
plt.savefig(os.path.join(log_path, 'min_mae_history.png'))
plt.clf()
代码复现成功!!!😊😊😊