自己制作crowd counting数据集

本文详细介绍了创建Crowdcounting数据集的全过程,包括拍摄图像、图像标注、生成.mat文件和制作densitymap。通过实例代码展示了如何利用Python进行图像处理,以及使用Matlab转换坐标为densitymap,为人工智能算法训练提供数据准备。
摘要由CSDN通过智能技术生成

Crowd counting的数据集包括两部分:图像部分和标签部分

标签部分主要包括每个人头的坐标点:(x, y);

常见的标签格式例如:ShanghaiTech数据集中的格式,用mat文件存储每个人头的坐标点,一张图像对应一个mat文件;

 

当我们自己制作数据集时,需要经历以下几个步骤:


1)拍摄图像或者视频;视频需要切分成帧;

2)在图像上进行标点,标点的同时会记录下坐标点;

3)根据这些坐标点生成每张图像对应的.mat文件;

4)在训练时,将mat文件中的坐标转换为density map;

 

以下是每个步骤中所需要用到的py文件:

1)拍摄图像,如果是视频的话需要切分为视频帧:

将视频切分为视频帧:

import imageio

filename = "E:\video.MP4"
vid = imageio.get_reader(filename, 'ffmpeg')

try:
    for num, im in enumerate(vid):
        if (num / 50) and (num % 50) == 0:    # 控制图像的输出张数;
            imageio.imwrite('E:\save_photo_from_video\{}.jpg'.format(num // 50), im)
        else:
            continue
except imageio.core.format.CannotReadFrameError or RuntimeError:
    pass

2)在图像上进行标注:

有一些现有的工具也可以完成相应的操作,这里我们用一段py代码来实现在图像上打点并将图像上人头的坐标点写入txt文件中,已备下一步使用:

打点代码:

import cv2
import os

"""
This code is used to:
1)对图片进行标注
2)生成对应的包含坐标信息的.txt文件
"""

imgs_path = "E:/images/" # 存放图像的文件夹
txt_path = "E:/txt/" # 存放txt文件的文件夹
files = os.listdir(imgs_path)
img = 0
coordinates = []

def on_EVENT_LBUTTONDOWN(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        cv2.circle(img, (x, y), 4, (0, 255, 0), thickness=-1)
        coordinates.append([x, y])
        print([x,y])
        cv2.imshow("image", img)

for file in files:  # for i in range(80, len(files)):
    coordinates = []
    img = cv2.imread(imgs_path+file)
    cv2.namedWindow("image")
    cv2.setMouseCallback("image", on_EVENT_LBUTTONDOWN)
    cv2.imshow("image", img)
    cv2.waitKey(0)
    with open(txt_path+file.replace("jpg","txt"), "w+") as f:
        for coor in coordinates:
            f.write(str(coor[0])+" "+str(coor[1])+"\n")    # 记录每个人头的坐标点
        f.write(str(len(coordinates)))    # 记录一张图像中的人头总数
    print(file+" is ok !"+"\n")

使用这个打点代码时,点击运行,会出现第一张图像,然后用鼠标在上面打点,标注完一张图像后,点击右上角的×关闭这张图像,开始对第二张图像打点,直到所有图像结束;

如果中途有图像发现点错了,可以记录下错误的图像名称,待全部点完之后再进行处理;如果图像太多,一次性标注不完,建议分批进行处理;

以上就是名为0.jpg的图像打点的过程以及生成对应的0.txt,第三张图可以看到txt中的内容,为人头的坐标,最后一行为人头总数;

3)通过这些txt文件中的坐标点,形成mat文件;(注:使用ShanghaiTech数据集中的同样的格式)

将txt文件转换为mat文件:

import numpy as np
import scipy.io as io
import os

txt_path = "E:/txts/"
save_path = "E:/mats/"
files = os.listdir(txt_path)
for file in files:
    print(file)
    with open(txt_path+file, "r") as f:
        datas = f.readlines()
        list = []
        for i in range(0, len(datas) - 1):
            line = datas[i].strip('\n')
            ele = line.split( )
            list.append(ele)

        data_length = np.array([[datas[len(datas) - 1]]], dtype=np.uint8)

        data = np.array(list, dtype=np.float64)
        dt = np.dtype([('location', np.ndarray), ('number', np.ndarray)])
        data_combine = np.array([(data, data_length)], dtype=dt)

        image_info = np.array([data_combine], dtype=[('location', 'O'),('number', 'O')])   # [[(data, data_length)]]
        image_info = np.array([[image_info]], dtype=object)

        __header__ = b'MATLAB 5.0 MAT-file Platform: nt, Created on: 2021'
        __version__ = '1.0'
        __globals__ = '[]'

        dict = {'__header__': __header__, '__version__': __version__, '__globals__': __globals__, 'image_info':image_info}
        gt = dict["image_info"][0,0][0,0][0]

    io.savemat(save_path+file.replace("txt","mat"), dict)

通过这个步骤,我们就可以得到每张图像对应的mat文件;

4)根据mat文件制作训练时需要的density map

此处使用matlab进行实现:

a)preapre_World_10.m

clc; clear all;

fileFolder=fullfile('F:\label');
dirOutput=dir(fullfile(fileFolder,'*'));
fileNames={dirOutput.name}';

standard_size = [384,512]; # 可以修改大小

dataset_name = ['WorldExpo10'];
original_path = ['F:/dataset/'];
output_path = 'F:/data/';
att = 'test';
train_path_img = strcat(output_path, 'train_frame/');
mkdir(train_path_img);

for ii = 3:105
  gt_path = ['F:/train_label/' fileNames{ii} '/'];
  
  train_path_den = strcat(output_path, 'train_lable/', fileNames{ii}, '/');
  mkdir(train_path_den);
  
  matFolder=fullfile(gt_path);
  matdirOutput=dir(fullfile(matFolder,'*'));
  matNames={matdirOutput.name}';
  num_images=length(matdirOutput)-1;
  
  disp(num_images)
  
  for idx = 3:num_images
    i = idx;
    if (mod(idx,10)==0)
        fprintf(1,'Processing %3d/%d files\n', idx, num_images);
    end
    load(strcat(gt_path, matNames{idx}));
    input_img_name = strcat(original_path,'train_frame/',strrep(matNames{idx}, 'mat', 'jpg'));
    disp(input_img_name)
    im = imread(input_img_name);
    [h, w, c] = size(im);
    annPoints =  point_position;

    rate_h = standard_size(1)/h;
    rate_w = standard_size(2)/w;

    im = imresize(im,[standard_size(1),standard_size(2)]);
    annPoints(:,1) = annPoints(:,1)*double(rate_w);
    annPoints(:,2) = annPoints(:,2)*double(rate_h);
    
    im_density = get_density_map_gaussian(im,annPoints); 
    im_density = im_density(:,:,1);
    
    imwrite(im, [output_path 'train_frame/' strrep(matNames{idx}, 'mat', 'jpg')]);
    csvwrite([output_path 'train_lable/' fileNames{ii} '/' strrep(matNames{idx}, 'mat', 'csv')], im_density);
  end
end

b)get_density_map_gaussian()实现:

function im_density = get_density_map_gaussian(im,points)


im_density = zeros(size(im)); 
[h,w] = size(im_density);

if(length(points)==0)
    return;
end

if(length(points(:,1))==1)
    x1 = max(1,min(w,round(points(1,1))));
    y1 = max(1,min(h,round(points(1,2))));
    im_density(y1,x1) = 255;
    return;
end
for j = 1:length(points) 	
    f_sz = 15;
    sigma = 4.0;
    H = fspecial('Gaussian',[f_sz, f_sz],sigma);
    x = min(w,max(1,abs(int32(floor(points(j,1)))))); 
    y = min(h,max(1,abs(int32(floor(points(j,2))))));
    if(x > w || y > h)
        continue;
    end
    x1 = x - int32(floor(f_sz/2)); y1 = y - int32(floor(f_sz/2));
    x2 = x + int32(floor(f_sz/2)); y2 = y + int32(floor(f_sz/2));
    dfx1 = 0; dfy1 = 0; dfx2 = 0; dfy2 = 0;
    change_H = false;
    if(x1 < 1)
        dfx1 = abs(x1)+1;
        x1 = 1;
        change_H = true;
    end
    if(y1 < 1)
        dfy1 = abs(y1)+1;
        y1 = 1;
        change_H = true;
    end
    if(x2 > w)
        dfx2 = x2 - w;
        x2 = w;
        change_H = true;
    end
    if(y2 > h)
        dfy2 = y2 - h;
        y2 = h;
        change_H = true;
    end
    x1h = 1+dfx1; y1h = 1+dfy1; x2h = f_sz - dfx2; y2h = f_sz - dfy2;
    if (change_H == true)
        H =  fspecial('Gaussian',[double(y2h-y1h+1), double(x2h-x1h+1)],sigma);
    end
    im_density(y1:y2,x1:x2) = im_density(y1:y2,x1:x2) +  H;
     
end

end

至此,自己制作crowd counting数据集完毕。

评论 28
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值