python numpy的数组切片和其中None的意思

参考:https://blog.csdn.net/qq_36490364/article/details/83594271

数组切片中用None

  1. # 那么a和a[:None]有何作用上的差别呢?
  2. a[:None]可以取到此数组的所有元素

np.newaxis

参考:https://blog.csdn.net/weixin_42866962/article/details/82811082
插入新维度
对于[: , np.newaxis] 和 [np.newaxis,:]
是在np.newaxis这里增加1维。

python中图片的float类型和uint8类型

在python图像处理过程中,遇到的RGB图像的值是处于0-255之间的,为了更好的处理图像,通常会将图像值转变到0-1之间
这个处理的过程就是图像的float类型转变为uint8类型过程。
float类型取值范围 :-1 到1 或者 0到1
uint8类型取值范围:0到255

  • 查看数据类型

    1. print(image.dtype)
  • uint8转float32:先将图片转化为float32类型,再除以255,得到0-1之间的数

    1. import numpy as np
    2. image = image.astype(np.float32) / 255
  • float32转uint8:每个数乘以255,再转化为uint8

    1. import numpy as np
    2. image = (image * 255).astype(np.uint8)
  • 另一种转换方式:

    1. img = np.float32(cv2.resize(img, (448, 448))) / 225

    cv2.imwrite()图像全黑问题

    网上看别人遇到的问题,可以借鉴。

查看图片数组的数据类型 img.dtype ,发现现在的格式是float32,本应该要是0-255的整数才行,使用cv2.imwrite()保存能正常cv.imshow的图像是近乎全黑的。
转换一下图片数组的数据类型就好了,float[0.0 - 1.0]数据格式的图片img*255.0,再转成uint8[0-255]。

python图像读取方式总结

python图像读取
BGR:

  • cv2.imread(img_path):使用opencv读取图像,直接返回numpy.ndarray对象,通道顺序为BGR,注意是BGR,通道值默认范围0-255。
    • 为何是BGR?历史遗留问题。

RGB:

  • skimage.io.imread(img_path):直接返回numpy.ndarray()对象,通道顺序为GRB,通道值默认范围0-255.
  • PIL.Image.open():返回PIL image对象,HWC

    1. # 1.读取显示
    2. from PIL import Image
    3. im = Image.open('lena.png')
    4. im.show()
    5. # 2.PIL Image图片转为numpy数组
    6. im_array = np.array(im)
    7. # 也可以用 np.asarray(im) 区别是 np.array() 是深拷贝,np.asarray() 是浅拷贝
    8. # 3.保存PIL图片
    9. I = Image.open('lena.png')
    10. I.save('new_lena.png')
  • matplotlib.image.imread():numpy.ndarray对象

不管是RGB还是BGR,都是高度×宽度×通道数,H×W×C的表达方式,而在深度学习中,因为要对不同通道应用卷积,所以用的是另一种方式:C×H×W,就是把每个通道都单独表达成一个二维矩阵。

图像转为torch.Tensor对象

在深度学习中,原始图像需要转换为深度学习框架自定义的数据格式,在pytorch中,需要转为torch.Tensor。
torch.Tensor 高维矩阵的表示: (nSample)x C x H x W
numpy.ndarray 高维矩阵的表示: H x W x C
因此在两者转换的时候需要使用 numpy.transpose( ) 方法 。

  1. # ------------np.ndarray转为torch.Tensor------------------------------------
  2. # numpy image: H x W x C
  3. # torch image: C x H x W
  4. # np.transpose( xxx, (2, 0, 1)) # 将 H x W x C 转化为 C x H x W
  5. tensor_skimage = torch.from_numpy(np.transpose(img_skimage, (2, 0, 1)))
  6. tensor_cv = torch.from_numpy(np.transpose(img_cv, (2, 0, 1)))
  7. tensor_pil = torch.from_numpy(np.transpose(img_pil_1, (2, 0, 1)))
  • 如果反过来,torch.Tensor转numpy.ndarray
    1. # np.transpose( xxx, (2, 0, 1)) # 将 C x H x W 转化为 H x W x C
    2. img_skimage_2 = np.transpose(tensor_skimage.numpy(), (1, 2, 0))
    3. img_cv_2 = np.transpose(tensor_cv.numpy(), (1, 2, 0))
    4. img_pil_2 = np.transpose(tensor_pil.numpy(), (1, 2, 0))
    5. plt.figure()
    6. for i, im in enumerate([img_skimage_2, img_cv_2, img_pil_2]):
    7. ax = plt.subplot(1, 3, i + 1)
    8. ax.imshow(im)
    9. plt.pause(0.01)

    np.transpose()

  1. 对于一维数组不起作用
  2. 对于二维数组:

    1. >>> two=np.arange(16).reshape(4,4)
    2. >>> two
    3. array([[ 0, 1, 2, 3],
    4. [ 4, 5, 6, 7],
    5. [ 8, 9, 10, 11],
    6. [12, 13, 14, 15]])
    7. >>> two.transpose()
    8. array([[ 0, 4, 8, 12],
    9. [ 1, 5, 9, 13],
    10. [ 2, 6, 10, 14],
    11. [ 3, 7, 11, 15]])
    12. >>> two.transpose(1,0)
    13. array([[ 0, 4, 8, 12],
    14. [ 1, 5, 9, 13],
    15. [ 2, 6, 10, 14],
    16. [ 3, 7, 11, 15]])

    以上可见,原数组two的数组两个轴为(x,y),对应的下标为(0,1),np.transpose()传入的参数为(1,0),即将原数组的x,y轴互换。综上,对二维数组的transpose操作就是对原数组的转置操作。

  3. 对于三维数组:通常用来交换某两个轴,用于深度学习中,如下,即实现将[H, W, C]的表达方式转为[C, H, W]的表达方式。

    1. np.transpose(image, (2, 0, 1)) # channel first

    注意与torch.transpose()的区别,torch.transpose()只能交换两个维度

np.ascontiniusarray()

返回一个连续的array,其内存是连续的。

cv2图像处理

  1. cv2.resize(img, (224, 224))
  • 输入:

io.imread(img_name)
img = np.float32(cv2.resize(img, (224,224))) /255
inputs = prepare_input(img)

  1. def prepare_input(image):
  2. image = image.copy()
  3. # 归一化
  4. means = np.array([0.485, 0.456, 0.406])
  5. stds = np.array([0.229, 0.224, 0.225])
  6. image -= means
  7. image /= stds
  8. image = np.ascontiguousarray(np.transpose(image, (2, 0, 1))) # channel first
  9. image = image[np.newaxis, ...] # 增加batch维
  10. return torch.tensor(image, requires_grad=True)

扁平化函数 ravel()flatten()

参考:https://www.cnblogs.com/mzct123/p/8659193.html
在Numpy中经常使用到的操作由扁平化操作,Numpy提供了两个函数进行此操作,他们的功能相同,但在内存上有很大的不同.

  1. from numpy import *
  2. a = arange(12).reshape(3,4)
  3. print(a)
  4. # [[ 0 1 2 3]
  5. # [ 4 5 6 7]
  6. # [ 8 9 10 11]]
  7. print(a.ravel())
  8. # [ 0 1 2 3 4 5 6 7 8 9 10 11]
  9. print(a.flatten())
  10. # [ 0 1 2 3 4 5 6 7 8 9 10 11]

可以看到这两个函数实现的功能一样,但我们在平时使用的时候flatten()更为合适.在使用过程中flatten()分配了新的内存,但ravel()返回的是一个数组的视图.视图是数组的引用(说引用不太恰当,因为原数组和ravel()返回后的数组的地址并不一样),(但修改视图会导致原数组也被修改),在使用过程中应该注意避免在修改视图时影响原本的数组。

numpy数组的拷贝和视图(注意和list的拷贝的区别)

参考:https://blog.csdn.net/Arrogant_95/article/details/82291226https://blog.csdn.net/u014465934/article/details/79488819

  • 完全不拷贝:简单的任务是不会对数组或其数据进行拷贝的。

    • 赋值即为引用。

      1. >>> a = np.arange(12)
      2. >>> b = a # 不会创建新的对象
      3. >>> b is a # a和b是同一个ndarray对象的两个名字
      4. True
      5. >>> b.shape = 3,4 # 也会改变a的形状
      6. >>> a.shape
      7. (3, 4)
    • Python传递可变对象的引用,因此函数调用也不会进行拷贝。

  • 视图或浅拷贝
    • 不同的数组对象可以共享相同的数据。view方法会创建一个共享原数组数据的新的数组对象。

如果数组A是数组B的视图(view),则称B为A的base(除非B也是视图)。视图数组中的数据实际 上保存在base数组中。

  • 对数组切片返回的是其视图(引用)。
    • 深拷贝:
  • copy方法会对numpy数组和其数据进行完全拷贝,不仅不是一个对象,也不再共享数据。类似于list列表中的deepcopy()。

    !!!特别注意,对于list列表而言, copy() 方法和 切片 是浅拷贝,如果list中没有引用其他对象,那么浅拷贝和深拷贝才一样(比如一维度list)

  1. # list 列表的浅拷贝或者切片
  2. c = [1,3,[2,3]]
  3. d = c.copy()
  4. c
  5. >> [1, 3, [2, 3]]
  6. d
  7. >> [1, 3, [2, 3]]
  8. d[2][0] = 999
  9. d[1] = 2
  10. d
  11. >> [1, 2, [999, 3]]
  12. c
  13. >> [1, 3, [999, 3]]
  14. # list列表的深拷贝
  15. import copy
  16. c = [1, 2, [3, 4]]
  17. b = copy.deepcopy(c)
  18. d
  19. >> [1, 2, [3, 4]]
  20. d[0] = 0
  21. d[2][1] = 2
  22. d
  23. >> [0, 2, [3, 2]]
  24. c
  25. >> [1, 2, [3, 4]]

索引相关操作

1、批量赋值
比如在将label转为one-hot编码时:

  1. # y是原label的list,每个元素取值为[0,num_classes)
  2. y = np.array(y, dtype='int')
  3. categorical = np.zeros(n, num_classes, dtype='float32')
  4. categorical[np.arange(n), y] = 1

还有一种方式 np.eye(num_classes)[y] ,目前还不理解

2、对于二维数组, a[0, 0]a[0][0] 是一样的。

数组维度

1、一维numpy array的维度为 (n, )

  1. import numpy as np
  2. a = arange(10)
  3. # array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
  4. a.shape
  5. # (10, )

np.genfromtxt

从文本文件加载数据,并按指定处理缺失值。

  1. import numpy as np
  2. data = np.genfromtxt('waveform.txt',delimiter=',',skip_header=18)
  3. 数据以,间隔,忽略前18

np.row_stack()

在numpy库中,对于矩阵的合并操作用两种方法:
行合并:np.row_stack()
列合并:np.column_stack()

  1. >>> import numpy as np
  2. >>> a=np.arange(16).reshape(4,-1)
  3. >>> a
  4. array([[ 0, 1, 2, 3],
  5. [ 4, 5, 6, 7],
  6. [ 8, 9, 10, 11],
  7. [12, 13, 14, 15]])
  8. >>> b=np.arange(16,32).reshape(4,-1)
  9. >>> b
  10. array([[16, 17, 18, 19],
  11. [20, 21, 22, 23],
  12. [24, 25, 26, 27],
  13. [28, 29, 30, 31]])
  14. >>> test=np.row_stack((a,b))#行合并
  15. >>> test
  16. array([[ 0, 1, 2, 3],
  17. [ 4, 5, 6, 7],
  18. [ 8, 9, 10, 11],
  19. [12, 13, 14, 15],
  20. [16, 17, 18, 19],
  21. [20, 21, 22, 23],
  22. [24, 25, 26, 27],
  23. [28, 29, 30, 31]])
  24. >>> test=np.column_stack((a,b))#列合并
  25. >>> test
  26. array([[ 0, 1, 2, 3, 16, 17, 18, 19],
  27. [ 4, 5, 6, 7, 20, 21, 22, 23],
  28. [ 8, 9, 10, 11, 24, 25, 26, 27],
  29. [12, 13, 14, 15, 28, 29, 30, 31]])
  30. >>>