- 像素
像素是指由图像的小方格组成的,这些小方块都有一个明确的位置和被分配的色彩数值,小方格颜色和位置就决定该图像所呈现出来的样子。
- 分辨率
图像分辨率指图像中存储的信息量,是每英寸图像内有多少个像素点,分辨率的单位为PPI(Pixels Per Inch),通常叫做像素每英寸。图像分辨率一般被用于ps中,用来改变图像的清晰度。
- 图片的尺寸x图片的分辨率=图片的像素
- 这里的尺寸指的就是照相馆中说的几寸照片
- 而AI图像高与宽则是存储图像的矩阵有几行几列
### 通俗理解
- 图像有形状(尺寸)和颜色
- 颜色是指RGB(红,绿,蓝),red,green,blue三色
-
- 每个颜色的取值范围为[0,255]
- AI的图像处理通常都是黑白色的
- 也就是说,AI更关注图像的形状,而不是色彩
-
- 图像由像素组成
- 一个像素就是一个值为[0,255]的一个数
|
这里指计算机中的图像,从视觉上看,它与现实相近, 比如电脑中看到大山,马路,楼房,车子等,与现实中看到的相近, 但我们知道,这些事物并没有真的进入电脑, 这时要从两个角度理解: 1. 由于电脑中全是数字/字节/二进制01,所图像在电脑的存储方式只能是数字,我们处理图像就是要去处理图像对应的数字 2. 看不见的数字是如何转换成视觉成像的问题,是显示器或者相机处理的,这个不是我们要关注的问题 处理图像就是要处理与图像对应的 数字矩阵
|
## 数据
1
是一个数,也叫标量,或者张量
[1]
是一个列表,确切讲是1维列表,也可以叫做向量
向量就是n个数值形成的列表
[[1],[2]]
2维列表,它的每1维都是一个1维列表,或者说每1维都是一个向量
也可以说是矩阵
## 数据shape
数据shape,指数据的形状,或者数据的维度
单个数字没有维度
```python
print("shape----------------------")
import numpy as np
from numpy.core.fromnumeric import shape
print(1,shape(3)) # (),没有
print(2,shape([3])) # (1,),表示第一维的个数为1,第二维没有
print(3,shape([[1],[2]])) # (2, 1) 第一维个数为2,第二维个数为1
print(4,shape([[1,1],[2,2]])) # (2, 2) 第一维个数为2,第二维个数为2
```
神经网络模型常用的数据shape,通常 不超过四维
|
### reshape
- 将原数组中的所有元素串起来,按新的维度进行组合
```python
import numpy as np
a = np.array( [
[
[[1],[255]],
[[0],[100] ],
]
])
print("1",a)
print("2",a.shape)
b = a.reshape(2,2)
print("3",b)
```
```
1 [[[[ 1]
[255]]
[[ 0]
[100]]]]
2 (1, 2, 2, 1)
3 [[ 1 255]
[ 0 100]]
```
reshape不改变数组元素具体的值,也不改变元素的个数,改变了数组的形状,
数据进入模型后,会经过很多方法的处理,
不同的方法需要的数组的shape不一样,
所以有时需要改变数据的shape
|
|
新增1个维度-在最高维增加 - 元素个数不变的情况下,再加1维(维度数为1) ```python import numpy as np w = np.array([1,2,3]) print(w.shape) """ (3,) 行向量第2个维度为空 下面增加一个维度,新的维度为(3,1),表示3行1列 """ w = w.reshape(3,1) ``` 新增1个维度-矩阵
由于数据的元素不变化,reshape新的维度后,数据会重排列,
可以利用这一点,为数据增加一个维度,
新的维度要能刚好放下原来所有的数据才行,还需要考虑整除的问题,
如果这加上的一维的维度数不是1,比如是3,就直接报错了
- 下面矩阵最后一个维度是一个行向量
```python
import numpy as np
a = np.array( [
[
[1, 2, 55],
[0, 3, 10],
[1, 2, 55],
]
])
print("1",a)
print("2",a.shape)
b = a.reshape(1,3,3,1)
print("3",b)
print("4",b.shape)
```
```
1 [[[ 1 2 55]
[ 0 3 10]
[ 1 2 55]]]
2 (1, 3, 3)
3 [[[[ 1]
[ 2]
[55]]
[[ 0]
[ 3]
[10]]
[[ 1]
[ 2]
[55]]]]
4 (1, 3, 3, 1)
```
|
### 单个图像shape
- 一张图像的矩阵表示
- 下面是一张图片,185是高,宽是358
- 以jpg格式存储,然后使用numpy读取
```python
from PIL import Image
import numpy as np
im = np.array(Image.open('/tmp/31.jpg'))
print(im.dtype)
# uint8
print(im.shape)
(185, 358, 3)
```
- RGB图像的shape为(高,宽,RGB颜色)
- 第3维,表示的是[红,黄,蓝]三色,
- 也叫:通道
-
- 高宽决定图片的尺寸
- png图片还有一个透明度的维度,它的通道数为4
- 所以通道表示的是高与宽形成的矩阵数量
-
- 每个通道的矩阵表示了相似的图片形状,不同的颜色
下面是png图片,每张图片有4组数据
```python
from PIL import Image
import numpy as np
im = np.array(Image.open('/tmp/1.png'))
print(im.shape)
# (61, 97, 4)
```
### 图像通道
- 下面是一张5行2列3通道的白色图片
- 白色对应的RGB是三个255,图像数据最后一维是一个行向量[255,255,255]
```python
from PIL import Image
import numpy as np
im = np.array(Image.open('/tmp/12.jpg'))
print(im.shape) # (5, 2, 3)
print(im)
"""
[[[255 255 255]
[255 255 255]]
[[255 255 255]
[255 255 255]]
[[255 255 255]
[255 255 255]]
[[255 255 255]
[255 255 255]]
[[255 255 255]
[255 255 255]]]
"""
```
图像处理之从PIL读取到模型输入
from PIL import Image
from torchvision.transforms import Compose
from torchvision.transforms import Grayscale
from torchvision.transforms import Resize
from torchvision.transforms import ToTensor
from torchvision.transforms import Normalize
img = Image.open(fp="/opt/tpf/aiwks/datasets/images/001/dianzi1.jpg")
# 图像数据预处理
transforms1 = Compose(transforms=[Resize(size=(224, 224)),
ToTensor()])
# Compose的参数要求是JpegImageFile
x = transforms1(img)
print(x.shape) # torch.Size([3, 224, 224]),注意这里shape已经进行了转换
print(x[0,0][:5]) # tensor([0.0863, 0.0863, 0.0863, 0.0863, 0.0863]),还完成了归一化,将0-255的数值转换到0-1
# Normalize标准化处理,图像有3通道,所以需要3个维度进行归一化
transforms2 = Compose(transforms=
[Resize(size=(224, 224)),
ToTensor(),
Normalize(mean=[0.5, 0.5, 0.5],
std=[0.5, 0.5, 0.5])])
x = transforms2(img)
print(x.shape) # torch.Size([3, 224, 224])
# 灰度处理,图像有1通道,所以需要1个维度进行归一化
transforms3 = Compose([
Grayscale(),
Resize(size=(32,32)),
ToTensor(),
Normalize(mean=[0.5],
std=[0.5])
])
x = transforms3(img)
print("灰度处理:",x.shape) # 灰度处理: torch.Size([1, 32, 32])
是否灰度处理看业务需求: 如果业务更关注形状,就灰度处理减少计算量 如果不同的颜色对业务分类有帮助,就不进行灰度处理 Normalize(mean=[0.5], std=[0.5]) 将数据拉到0与1的中间,并且转为正态分布
按比例 随机 批量 生成 以x为中心的值
import numpy as np
def shake(x):
float_num = [0.1, 0.1, 0.3, 0.5, 0.95, 0.95, 0.99, 0.99, 0.99, 0.99]
seed = float_num[np.random.randint(0, len(float_num))]
x = 100
x = x + np.random.randint(int(-x * seed), int(x * seed))
return x
for i in range(5):
x = shake(100)
print(x)
输出:
107
105
126
85
34
按比例 随机 批量 生成 以图像为中心的其他图像
参考上面的思路,进行以下设计: 要生成的图像通常是正方形,所以求图像的高h,宽w 中的最大值 msize = max(h,w) 以此值为中心,按上面的方法抖动一下,生成一批边 求出图像的中心坐标(cx,cy)按上面的方法抖动一下,得到一系列中心坐标 新的中心+新的边长 对应 新的正方形 存在的问题: 比如x=100,原图像最大边长110,但随机生成的值却有126这样的数据, 所以并不是所有生成的图像都要,要除大于某个值的数据 既然图像变大可能出问题,那么可以将原初的坐标框收缩一下, 这样再随机扩大后,可以减少要去除的框的个数
图像偏移率
(原坐标 - 新坐标)/ 新的最大边长 = 偏移率 所有点的 偏移率之和 就是 损失函数 损失函数的目标是 让程序框到的图像 离 真实标签框的图像 的偏移率 越来越小 如此,程序框 就逐渐逼近 标签框 了