matlab分批读数据

Updates 2020.12.8

各位,别用「将 image 转成 .mat,然后 load mat」这种愚蠢的读图法,应该用 vl_imreadjpeg,速度差太多啦!不过要注意:需要重新处理一个 image mean pixel,见 [17]。

comparison

  • 注意要将 string 用 char() 转成 char array(这两者居然不是同一种东西)
  • 好像是 image_batch(i, :, :, :) = img; 这句耗时?如果 vl_imreadjpeg 不加 Pack 参数,而是用这句手动拼的话,也会很慢。
cd matconvnet;
setup;
cd /home/tom/codes/test.matlab;


fprintf("--- load mat ---\n");
image_batch = [];
tic;
for i = 1 : 1000
    img = load(fullfile("images.mat", strcat(num2str(i), ".mat")), "image");
    img = img.image;
    % fprintf("img:"), disp(size(img));
    image_batch(i, :, :, :) = img;  % 好像是这句很耗时?
    % break;
end
toc;  % Elapsed time is 158.847031 seconds.
fprintf("images:"), disp(size(image_batch));  % images: 1000 224 224 3


fprintf("--- vl_imreadjpeg ---\n");
tic;
a = {};
for i = 1 : 1000
    a(i) = {char(fullfile("images", sprintf("%d.jpg", i)))};
end
img = vl_imreadjpeg(a, 'NumThreads', 4, 'Resize', [224, 224], 'Pack');
image_batch = img{1, 1};
fprintf("image:"), disp(size(image_batch));  % image: 224 224 3 1000
toc;  % Elapsed time is 0.947701 seconds.
  • 158.847031s 和 0.947701 的区别!

Notes

[1] 直接加载整个数据集,由于条件限制,需要将 image 改为分批读入。

Preprocess

之前做的数据见 [2, 3],当时存成 .npy,要处理成 .mat 给 matlab 读。

  • image 读出来转成 (224, 224, 3) 放在 image.mat/ 目录下,一幅图一个 .mat 文件,key 统一为 image
  • 不处理 image,直接用 vl_imreadjpeg 读原图,见上面 Updates 2020.12.8
  • label、text 亦存成 .mat,不过可以装在一个文件内,key 分别为 labelstexts
  • index 一个 set 一个 .mat,key 统一为 index。有 idx_test.npyidx_labeled.npyidx_unlabeled.npyidx_ret.npy
  • 注意:python 索引是 0-base,而 matlab 是 1-base。此处 idx_*.npy 都是 0-base 的,所以 matlab 读入之后要 +1 转成 1-base 才能作为下标做 indexing。但是!前述 image.mat/ 的文件又是 0-base 的,所以后文 load_images 要用 0-base 索引。
import os
import numpy as np
import scipy.io as sio
import cv2
from PIL import Image


P = "/home/dataset/nuswide"
SPLIT_P = os.path.join(P, "nuswide-tc21.100pc.500pc")
DEST_P = os.path.join(P, "matlab-data")
if not os.path.exists(DEST_P):
    os.makedirs(DEST_P)
IMAGE_LIST = os.path.join(P, "ImageList/Imagelist.txt")
IMAGE_SRC = os.path.join(P, "Flickr")
IMAGE_DEST = os.path.join(DEST_P, "images.mat")
if not os.path.exists(IMAGE_DEST):
    os.makedirs(IMAGE_DEST)


"""label, text"""
# clean_id = np.load(os.path.join(P, "clean_id.tc21.AllTags1k.npy"))
labels = np.load(os.path.join(P, "labels.tc-21.npy")).astype(np.uint8)
texts = np.load(os.path.join(P, "texts.AllTags1k.npy")).astype(np.uint8)

sio.savemat(os.path.join(DEST_P, "labels.tc-21.mat"), {"labels": labels}, do_compression=True)
sio.savemat(os.path.join(DEST_P, "texts.AllTags1k.mat"), {"texts": texts}, do_compression=True)


"""image
with open(IMAGE_LIST, "r") as f:
    for sid, line in enumerate(f):
        # if sid not in clean_id_list:
        #     continue
        line = line.replace('\\/'.replace(os.sep, ''), os.sep).strip()
        img_p = os.path.join(IMAGE_SRC, line)
        # new_img_p = os.path.join(IMAGE_DEST, "{}.jpg".format(sid))
        # os.system("ln -s {} {}".format(img_p, new_img_p))
        img = cv2.imread(img_p)
        if img is None:
            img = np.asarray(Image.open(img_p))
            if 2 == img.ndim:
                img = np.repeat(img[:, :, np.newaxis], 3, axis=2)
        else:
            img = img[:, :, ::-1]
        img = cv2.resize(img, (224, 224), interpolation=cv2.INTER_LINEAR)
        # image_list.append(img)
        # 注意此处标号是 0-base 的
        sio.savemat(os.path.join(IMAGE_DEST, "{}.mat".format(sid)), {"image": img})

        if sid % 1000 == 0:
            print(sid)
"""


"""index"""
idx_list = os.listdir(SPLIT_P)
# print(idx_list)
for f in idx_list:
    idx = np.load(os.path.join(SPLIT_P, f)) 
    new_f = f.replace(".npy", ".mat")
    sio.savemat(os.path.join(P, new_f), {"index": idx})

Matlab Example

  • 没有 matlab 高亮,借 lua 的。vs code 也要装 matlab 插件才有高亮。
  • 行首 % 是行注释。
  • 「字符数组」与「字符串」居然是同一个东西,见 [11]。
  • 函数一定要定义在文件尾。
P = "/home/tom/dataset/nuswide/matlab-data";
SPLIT_P = fullfile(P, "nuswide-tc21.100pc.500pc");
IMAGE_P = fullfile(P, "images.mat");
TEXT_P = fullfile(P, "texts.AllTags1k.mat");
LABEL_P = fullfile(P, "labels.tc-21.mat");


% 读数据划分
index_key = ["train", "test", "ret"];
index_set = containers.Map('KeyType', 'char', 'ValueType', 'any');
for k = index_key
    % fprintf("key: %s\n", k);
    if strcmp(k, "train") == 1
        fn = "idx_labeled.mat";
    else
        fn = strcat("idx_", k, ".mat");
    end
    idx_f = fullfile(SPLIT_P, fn);
    % fprintf("idx_f: %s\n", idx_f);
    % index_set(char(k)) = cell2mat(struct2cell(load(idx_f)))';
    index_set(char(k)) = load_mat(idx_f, "index")';
end

for k = index_key
    fprintf("%s:", idx_name), disp(size(index_set(char(k))));
end


labels = load_mat(LABEL_P, "labels");
texts = load_mat(TEXT_P, "texts");
fprintf("labels:"), disp(size(labels));
fprintf("texts:"), disp(size(texts));


% 模拟训练
idx_train = index_set(char("train"));
% disp(size(idx_train));
N_TRAIN = length(idx_train);
% fprintf("#train: %d\n", N_TRAIN);
BATCH_SIZE = 128;

for iter = 1 : ceil(N_TRAIN / BATCH_SIZE)
    fprintf("--- %d ---\n", iter);
    meta_indices = randperm(N_TRAIN);
    meta_index = meta_indices(1: BATCH_SIZE);
    fprintf("batch size:"), disp(size(meta_index));  % (1, 128)

    label_batch = labels(meta_index, :);
    % DEPRECATED IMAGE READING METHOD, TOO SLOW
    image_batch = load_images(idx_train(meta_index));  % 慢成狗,建议用 `vl_imreadjpeg`
    text_batch = texts(meta_index, :);

    fprintf("label size:"), disp(size(label_batch));  % (128, 21)
    fprintf("image size:"), disp(size(image_batch));  % (128, 224, 224, 3)
    fprintf("text size:"), disp(size(text_batch));  % (128, 1000)

	% …此处训练…
    break;
end % for iter


function image_batch = load_images(indices)
	% 读一批 image %
    global IMAGE_P
    image_batch = [];
    for i = 1 : length(indices)
        idx = indices(i);
        img_p = fullfile(IMAGE_P, strcat(num2str(idx), ".mat"));
        % img = cell2mat(struct2cell(load(img_p)));
        % img_ = load(img_p, "image");
        % img = img_.image;
        img = load_mat(img_p, "image");
        image_batch(i, :, :, :) = img;
    end
end % load_images


function data = load_mat(path, key)
    st = load(path, key);
    data = st.(key);
end % load_mat

References

  1. DCMH-CVPR2017/DCMH_matlab/DCMH_matlab/DCMH_demo.m
  2. NUS-WIDE数据集预处理
  3. NUS-WIDE数据集划分
  4. 遍历数组的两种方式
  5. Characters and Strings
  6. strcat
  7. strcmp
  8. if, elseif, else
  9. fullfile
  10. MATLAB查看变量的类型
  11. matlab之str与char:字符串数组与字符数组
  12. function
  13. Matlab equivalent of Python enumerate
  14. load
  15. 190311-3种方法Matlab结构体struct元素的索引
  16. MATLAB文件夹命名里的“+”和“@”是干什么用的#每天学习一点编程
  17. vl_imreadjpeg和cv2的resize结果不同
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值