CV笔记:图片数据处理

目录

路径类

1. 获取一个路径最后一个目录或文件的名字

 2. 获得文件名的拓展名

图片处理类

1. 数据增强,图像左右反转

 2. 数据增强,随机缩放

3.  数据增强,随机裁剪

4. 读取图片的shape格式

5. cv2 BGR转RGB

6. 给图片设置边界框、边界填充 

7. pyplot子图标题

8. 排列堆叠图片

9. 获取图片中非零像素的索引

10. pyplot保存图片白边太多

 11. 不同库的坐标

12. cv2画矩形框

13. 框出图片中的某一区域并且取得坐标

读取数据集

1. ShanghaiTech

2. UCF-QNRF

 数据持久化

1. h5py存储数据

2. numpy存储:数组、字典


路径类

1. 获取一个路径最后一个目录或文件的名字

os.path.basename("D:\Project\AI-learning\Pytorch-UNet\data\masks\IMG_100_mask.npy")

# 输出: IMG_100_mask.npy

或者:

head,tail = os.path.split("D:\Project\AI-learning\Pytorch-UNet\data\masks\IMG_100_mask.npy")

# head='D:\\Project\\AI-learning\\Pytorch-UNet\\data\\masks',tail='IMG_100_mask.npy'

 2. 获得文件名的拓展名

import os
file = "Hello.py"

# 获取前缀(文件名称)
assert os.path.splitext(file)[0] == "Hello"

# 获取后缀(文件类型)
assert os.path.splitext(file)[-1] == ".py"
assert os.path.splitext(file)[-1][1:] == "py"

图片处理类

1. 数据增强,图像左右反转

可以对Image对象进行如下操作:

new_img = img.transpose(Image.Transpose.FLIP_LEFT_RIGHT)

也可以对2维度np数组:

kpoint = np.fliplr(kpoint)

 2. 数据增强,随机缩放

模板例子:

if self.args['scale_aug'] == True and random.random() > (1 - self.args['scale_p']):
    self.rate = random.choice([0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.05, 1.1, 1.15, 1.2, 1.25, 1.3])    # 缩放倍数
    width, height = img.size
    width = int(width * self.rate)
    height = int(height * self.rate)
    img = img.resize((width, height), Image.ANTIALIAS)
    

3.  数据增强,随机裁剪

crop_size_x = random.randint(0, img.shape[1] - width)
crop_size_y = random.randint(0, img.shape[2] - height)
sub_img = img[:, crop_size_x: crop_size_x + width, crop_size_y:crop_size_y + height]

4. 读取图片的shape格式

  • cv2.imread: 读取返回一个数组,它的shape含义:(h,w,c) c是BGR格式
  • 先读取为Image对象,再转换为np.ndarray对象,shape含义和上面的一致

5. cv2 BGR转RGB

cv2里面都是默认BGR的,所以在打开或者保存文件之前,都要转换成BGR。 

img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

6. 给图片设置边界框、边界填充 

方法:cv2.copyMakeBorder

作用:给图片设置边界框,可以用于填充。

参数:

  • src: 输入的图片
  • dst: 目标图片
  • top
  • bottom
  • left
  • right: 这四个参数是设置图片四个方向上填充多少个像素
  • borderType: 只介绍常用的
    • cv2.BORDER_CONSTANT:添加的边界框像素值为常数(需要额外再给定一个参数)
    • cv2.BORDER_REFLECT:添加的边框像素将是边界元素的镜面反射
    • cv2.BORDER_REPLICATE:使用最边界的像素值代替
  • value: 如果borderType为cv2.BORDER_CONSTANT时需要填充的常数值。

7. pyplot子图标题

使用pyplot画图时,经常需要画出如下的图:

即:一张大图里面包含几张子图,大图有总的标题,子图也有其子标题。画法如下:

from PIL import Image
import matplotlib.pyplot as plt
import numpy as np

img = Image.open('./example_images/1.png').convert('RGB')
img = np.array(img)

# 根据图片大小来设定画布大小
dpi = 100           
fig_size = [img.shape[0]*4.0/dpi,img.shape[1]*3.0/dpi]
plt.figure(dpi=dpi,figsize=fig_size)

# 主标题
plt.suptitle("main title")

for i in range(1,5):
    ax = plt.subplot(2,2,i) 
    # 子标题
    ax.set_title(F'fig{i}')
    # 不显示坐标轴
    plt.axis('off')
    plt.imshow(img)

plt.show()

8. 排列堆叠图片

看到有一份代码里面出现了np.hstack np.vstack,适合拼接图片。留个坑,以后有空了仔细研究一下。

9. 获取图片中非零像素的索引

np.nonzero: 返回b中的非零元素坐标。以二维数组为例:

a = np.array([[0,0,3],[0,0,0],[0,0,9]])
b = np.nonzero(a)
print(b)

输出:
(array([0, 2], dtype=int64), array([2, 2], dtype=int64))

输出两个数组,分别是非零元素的x坐标和y坐标。是一一对应的。

10. pyplot保存图片白边太多

1. 保存少量白边

可以在savefig时指定参数:

plt.savefig('test.jpg', bbox_inches='tight',dpi=200)

但是可能导致对图片尺寸大小的设置失效。另外需要设定一下dpi,否则图片会很模糊。

2. 完全不要白边 

plt.subplots_adjust(top=1, bottom=0, right=1, left=0, hspace=0, wspace=0)
plt.margins(0, 0)

 11. 不同库的坐标

下图中x表示第一个维度,y表示第二个维度

opencv-python:

PIL:

12. cv2画矩形框

cv2.rectangle,是靠 确定对角线 来画矩形的。
cv2.rectangle(img, (bbox.left, bbox.top), (bbox.right, bbox.bottom), (0,0,255), 2)。后面两个一个是RGB颜色,另一个是线条宽度

13. 框出图片中的某一区域并且取得坐标

 可以使用cv2.selectROI。回自动输出一个坐标。按空格或者回车完成绘制,按C退出。

selectROI(windowName, img, showCrosshair=None, fromCenter=None):
    .   参数windowName:选择的区域被显示在的窗口的名字
    .   参数img:要在什么图片上选择ROI
    .   参数showCrosshair:是否在矩形框里画十字线.
    .   参数fromCenter:是否是从矩形框的中心开始画

返回的是一个元组r = [min_x,min_y,w,h]:

如果要切片出来需要转换一下:[int(r[1]):int(r[1]+r[3]),int(r[0]):int(r[0]+r[2])]

14. numpy的c_和r_

np.c_是np.r_['-1,2,0', index expression]的一种简写,就是沿着矩阵的第二个轴拼接。对于二维矩阵,就是按照列column,要求两个矩阵的行数相等

# -*- coding: utf-8 -*
import numpy as np

x_1 = np.array([1, 2, 3, 4, 5, 6]).reshape(2, 3)
x_2 = np.array([3, 2, 1, 8, 9, 6]).reshape(2, 3)
x_new = np.c_[x_1,x_2]
print("x_1 = \n",x_1)
print("x_2 = \n",x_2)
print("x_new = \n",x_new)

# 输出如下:

x_1 = 
 [[1 2 3]
  [4 5 6]]
x_2 = 
 [[3 2 1]
  [8 9 6]]
x_new = 
 [[1 2 3 3 2 1]
  [4 5 6 8 9 6]]

np.r_是沿着row进行拼接

15. numpy有用的api

1. 返回排序后数组的索引: np.argsort

2. np.argwhere:返回一个二维数组,每一行代表一个满足条件的元素的索引,即使是在一个一维数组中查找,也会返回一个二维数组

3. np.where 有时候会返回一个包含一个元素的元组

        1.np.where(condition,x,y) 当where内有三个参数时,第一个参数表示条件,当条件成立时where方法返回x,当条件不成立时where返回y
        2.np.where(condition) 当where内只有一个参数时,那个参数表示条件,当条件成立时,where返回的是每个符合condition条件元素的坐标,返回的是以元组的形式

读取数据集

1. ShanghaiTech

import scipy.io as sio

# anno_path是标注文件的路径
data = sio.loadmat(anno_path)
# 标注点位置
xy = data['image_info'][0][0][0][0][0]           # (n,2)格式数据
cnt = data['image_info'][0][0][0][0][1][0][0]    # 人数

需要注意的是,这里的坐标格式是(w_idx,h_idx)

附上一个可视化查看标注位置是否对应正确的代码:

for xy in xys:
    w_idx = int(xy[0])
    h_idx = int(xy[1])
    img[h_idx-5:h_idx+5,w_idx-5:w_idx+5,:] = [0,0,255]
plt.imshow(img)
plt.show()

2. UCF-QNRF

这个数据集文件夹下有train test两个文件夹,标注和图片都在同一个文件夹里。标注是.mat文件格式,读取标注文件后,在其'annPoints'键的值中就是标注的数据。是(人头数目,2)格式,其中的2是(w_idx,h_idx)。示例代码如下:

test_img_path = r"./qnrf\img_0001_ann.mat"
test_anno_path = test_img_path.replace('.jpg','_ann.mat')

data = sio.loadmat(test_anno_path)
data = data['annPoints']

x = [i[0] for i in data]
y = [i[1] for i in data]

x = np.array(x).astype(np.int16)
y = np.array(y).astype(np.int16)
for i in range(len(x)):
    img[y[i]-5:y[i]+5,x[i]-5:x[i]+5,...] = [255,0,0]
plt.imshow(img)
plt.axis('off')
plt.show()

 数据持久化

1. h5py存储数据

import h5py

with h5py.File(h5_path,'w') as hf:
    hf['key'] = data

读取数据:

file = h5py.File(h5_path,'r')
data = np.asarray(file['key'])

2. numpy存储:数组、字典

 1. 保存一般的数组文件直接用np.save就可以保存为npy文件了

2. 保存与读取字典格式数据:

import numpy as np
a = {'alpha':1,'beta':'b','gamma':[2,3]}
# 保存
np.save('test',a)
# 读取
b = np.load('test.npy',allow_pickle=True).item()

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值