欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

vl_imreadjpeg和cv2的resize结果不同

程序员文章站 2022-06-26 17:14:26
matlab 用 vl_imreadjpeg 读图并 resize 到 [224, 224],与 python 用 cv2 做同样操作,得到的结果不同。在用 vl_imreadjpeg 读图的 matlab 程序想做 zero mean 操作,不能直接白嫖之前 python 用 cv2 处理的 image mean pixel,而要重新处理一个 mean pixel。Data用 nuswide 测试,见 [1],用以下程序将 image 放到同一个目录,方便读取:效果:在 images/ 下,...

matlab 用 vl_imreadjpeg 读图并 resize 到 [224, 224],与 python 用 cv2 做同样操作,得到的结果不同

  • 在用 vl_imreadjpeg 读图的 matlab 程序想做 zero mean 操作,能直接白嫖之前 python 用 cv2 处理的 image mean pixel,而要重新处理一个 mean pixel。

Environment

  • matlab R2018a
  • matconvnet-1.0-beta25
  • opencv-python-headless 4.4.0.42

Data

用 nuswide 测试,见 [1],用以下程序将 image 放到同一个目录,方便读取:

  • 效果:在 images/ 下,image 软链接名形如 n.jpg,n 是 sample id。
import os


P = "/home/dataset/nuswide"
print("current dir:", os.getcwd())

print("--- image ---")
IMAGE_LIST = os.path.join(P, "ImageList/Imagelist.txt")
IMAGE_SRC = os.path.join(P, "Flickr")
IMAGE_DEST = os.path.join(os.getcwd(), "images")
if not os.path.exists(IMAGE_DEST):
    os.makedirs(IMAGE_DEST)

with open(IMAGE_LIST, "r") as f:
    for sid, line in enumerate(f):
        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))
        if sid % 1000 == 0:
            print(sid)

Comparison

对比思路:先 matlab 用 vl_imreadjpeg 读一张图,存成 .mat 文件,然后 python 用 cv2 读同一张图比较。这里以 1.jpg 为例,可以换成其它 image。

without resize

用 resize 操作时,两者读出的结果相同

  • matlab + vl_imreadjpeg
cd matconvnet;
setup;
cd /home/tom/codes/test.matlab;


%1.jpg 为例,可以换成 2.jpg、3.jpg……
a = {char(fullfile("images", "1.jpg"))};
img = vl_imreadjpeg(a);  % 读图,不用 resize
img = uint8(img{1, 1});
disp(size(img));  % (181, 240, 3)
save("image_vl.1.mat", "img");
  • python + cv2
import os
import numpy as np
import scipy.io as sio
import cv2
from PIL import Image


P = "images"


def load_image(idx):
    img_p = os.path.join(P, "{}.jpg".format(idx))
    img = cv2.imread(img_p)#[:, :, ::-1]
    if img is None:  # cv2 读不了,就改用 PIL.Image 读
        img_f = Image.open(img_p)
        img = np.asarray(img_f)
        img_f.close()
        if 2 == img.ndim:  # 缺 channel
            img = np.repeat(img[:, :, np.newaxis], 3, axis=2)
    else:
        img = img[:, :, ::-1]
    # 不用 resize
    # img = cv2.resize(img, (224, 224), interpolation=cv2.INTER_LINEAR)
    return img


img_vl = sio.loadmat("image_vl.mat")["img"].astype(np.int64)  # 读刚才 matlab 存的图
img_py = load_image(1).astype(np.int64)  # 同样是 1.jpg
print(img_vl.shape, img_py.shape)  # (181, 240, 3) (181, 240, 3),相同
print(img_vl.sum(), img_py.sum())  # 19504976 19504976,相同
print("diff:", np.abs(img_vl - img_py).sum())  # diff: 0

with resize

还是刚才的代码,只不过两者都加上 resize 操作:统一 resize 成 224 x 224,结果就同了。

  • matlab + vl_imreadjpeg
cd matconvnet;
setup;
cd /home/tom/codes/test.matlab;


% 还是 1.jpg 为例
a = {char(fullfile("images", "1.jpg"))};
img = vl_imreadjpeg(a, 'Resize', [224, 224]);  % 这次加上 resize
img = uint8(img{1, 1});
disp(size(img));  % (224224, 3)
save("image_vl.1.mat", "img");
  • python + cv2
import os
import numpy as np
import scipy.io as sio
import cv2
from PIL import Image
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt


P = "images"


def load_image(idx):
    img_p = os.path.join(P, "{}.jpg".format(idx))
    img = cv2.imread(img_p)#[:, :, ::-1]
    if img is None:  # cv2 读不了,就改用 PIL.Image 读
        img_f = Image.open(img_p)
        img = np.asarray(img_f)
        img_f.close()
        if 2 == img.ndim:  # 缺 channel
            img = np.repeat(img[:, :, np.newaxis], 3, axis=2)
    else:
        img = img[:, :, ::-1]
    # 用上 resize
    img = cv2.resize(img, (224, 224), interpolation=cv2.INTER_LINEAR)
    return img


img_vl = sio.loadmat("image_vl.mat")["img"].astype(np.int64)  # 读刚才 matlab 存的图
img_py = load_image(1).astype(np.int64)  # 同样是 1.jpg
print(img_vl.shape, img_py.shape)  # (224, 224, 3) (224, 224, 3),相同
print(img_vl.sum(), img_py.sum())  # 22847441 22509472,不同!!!
print("diff:", np.abs(img_vl - img_py).sum())  # diff: 10933205,不同!!!

# 画出来看区别
fig, ax = plt.subplots(1, 2)
ax[0].imshow(img_vl);
ax[0].set_title("vl_imreadjpeg")

ax[1].imshow(img_py)
ax[1].set_title("cv2")
fig.savefig("compare_load.png")
plt.close(fig)
  • 画图结果

vl_imreadjpeg和cv2的resize结果不同
…vl_imreadjpeg 这个难道不是叫「crop」?

Conclusion

所以 vl_imreadjpeg 和 cv2 两种读图方式,在 resize 时结果相同,但用 resize 之后两者结果同!

而令人迷惑的是:vl_imreadjpeg 的官网介绍[3]说它 resize 用的是「bilinear interpolation」;而我在 python 调 cv2 时用的 cv2.INTER_LINEAR 也是「bilinear interpolation」[4]
vl_imreadjpeg和cv2的resize结果不同

References

  1. NUS-WIDE数据集预处理
  2. docker命令行安装matlab R2018a、matconvnet、gpu环境
  3. vl_imreadjpeg
  4. cv2.INTER_LINEAR
  5. opencv: 图像缩放(cv2.resize)

本文地址:https://blog.csdn.net/HackerTom/article/details/110926141