猪百岁 发表于 2021-3-22 10:47:46

【新手基础教程】基本图像变换 和 常用操作

# 基本图像变换 和 常用操作

这里简单介绍一些经常用到的图像的基本变换操作

旋转:

```
img.rotation_corr()
```

改变图像尺寸:

```
img.resize()
```

更多的图像变换请看(https://cn.maixpy.sipeed.com/zh/api_reference/machine_vision/image/image.html)

## 1. 图像缓冲区介绍

MaixPy 为图像设计了两个缓冲区,

+ 一个是RGB565缓冲区,顾名思义, 是以RGB565的格式存放这图片的信息的一块内存。注意在内存中的排序是 [像素1 RGB, 像素2 RGB...]

+ 另一个是RGB888缓冲区,顾名思义, 是以RGB88的格式存放这图片的信息的一块内存。注意在内存中的排序是[所有像素 R, 所有像素 G, 所有像素 B], 我们也称之为AI内存

这里使用两个内存块主要的原因是底层代码所有图片操作以及LCD显示均是基于RGB565, 但是KPU又需要RGB888的输入。

```
                   +---------------+
                   |               |
          +--------+ camera(sensor)+-------+
          |      |               |       |
          |      +---------------+       |
          |                              |
+---------v------+                +--------v---------+
|                | img.pix_to_ai()|                  |
|      RGB565    +--------------->+      RGB888      |
|                |                |                  |
+--------+-------+                +------+-----------+
         ^                               |
         |                               |
         |                               v
+--------+----------+             +------+-----------+
|                   |             |                  |
|   image ops   |             |   KPU            |
|                   |             |                  |
+-------------------+             +------------------+
```

只有摄像头采集图片时,硬件会自动放一份数据到RGB888内存区域, 其它的都不会自动填充RGB888内存块, 软件操作只会对RGB565内存进行操作,不会自动更新RGB888,(因为更新需要消耗时间) 这很值得注意, 这意味着,每次我们用更改了RGB565内存块,比如执行了img = img.resize((224, 224)),如果希望KPU使用更改过后的图片, 需要执行img.pix_to_ai()来将RGB565的图像手动更新到RGB888的区域,然后才可以调用kpu相关的函数进行模型推理!

同样反方向更新也提供 API: img.ai_to_pix(), 这会将RGB888区域的数据更新到RGB565区域

## 2. resize 修改分辨率

```
import image
img = image.Image(size=(100, 100))
img2 = img.resize(50, 50)
print(img)
print(img2)
```

## 3. 获取和修改像素值

```
import image
img = image.Image(size=(10, 10))
print("pixel 0:", img, img.get_pixel(0, 0))
img = (255, 0, 0)
img = img.set_pixel(1, 0, (255, 255, 10))
print("after pixel 0 change:", img, img)
```

这里设置的第二个像素点B为10, 实际发现读出来是8, 这是正常现象,因为前面说了,在内存中储存是用了RGB565进行储存,所以会有误差

## 4. 复制图像

```
import image
img = image.Image(size=(10, 10))
img2 = img.copy()
img2 = (255, 0, 0)
print(img, img2)
```

## 5. 剪裁图像

同样使用copy函数

```
import image
img = image.Image(size=(10, 10))
img2 = img.copy(roi=(0, 0, 5, 5))
img2 = (255, 0, 0)
print(img)
print(img2)
print(img, img2)
```

## 6. 转换成 bytes 对象

转换成 RGB565 字符串

```
import image
img = image.Image(size=(10, 10))
img = (255, 0, 0)
img_bytes = img.to_bytes()
print("bytes length: %d bytes: %x%x" %(len(img_bytes), img_bytes, img_bytes))
```

这里输出的值为RGB565格式,以两个字节表示一个像素点储存

另外, 也可以先将图片压缩为 JPEG 格式,然后再转换成bytes

```
import image
img = image.Image(size=(10, 10))
img = img.compressed(quality=20)
jpeg_bytes = img.to_bytes()
print("bytes length: %d bytes: %x%x" %(len(jpeg_bytes), jpeg_bytes, jpeg_bytes))
```

这里使用compressed函数不会修改原图, 使用compress()函数则会修改原图, 但是压缩后的大小如果比原图占用的空间还大,就会失败

## 7. 转换为灰度图像

```
img = img.to_grayscale(copy=False)
```

这里 copy 参数的意思就是是否要重新申请一片内存, 不修改原图的意思

## 8. 转换为 RGB565 彩图

转换为 彩图, 注意只是格式成为了彩图, 画面并不是彩图, 如果需要将灰度图转换为彩图,使用img.to_rainbow()

```
img = img.to_rgb565(copy=True)
```

这里 copy 参数的意思就是是否要重新申请一片内存, 不修改原图的意思 如果原图是灰度图, 必须是True

## 9. 转换为彩图

```
img = img.to_rainbow(copy=True)
```

这里 copy 参数的意思就是是否要重新申请一片内存, 不修改原图的意思 如果原图是灰度图, 必须是True

## 10. 保存到文件系统

```
img.save("/sd/test.jpg", quality=95)
img.save("/sd/test.bmp")
```

## 11. 旋转

```
img.rotation_corr(]]]]])
```

中括号为可选参数,即沿着哪个轴旋转一定的角度, 如果minimum版本的固件里面没有这个函数, 可以用完全版本的固件
页: [1]
查看完整版本: 【新手基础教程】基本图像变换 和 常用操作