Basic image transformation and common operations

    Here is a brief introduction to the basic transformation operations of some frequently used images

    Rotate:

    img.rotation_corr()
    

    Change the image size:

    img.resize()
    

    For more image transformation, please see image API

    Introduction to image buffer

    MaixPy has designed two buffers for the image,

    • One is the RGB565 buffer, as the name suggests, is a memory that stores the information of this picture in the format of RGB565. Note that the order in the memory is [pixel 1 RGB, pixel 2 RGB...]
    • The other is the RGB888 buffer, as the name implies, a memory that stores the information of this picture in the format of RGB88. Note that the order in the memory is [all pixels R, all pixels G, all pixels B], we also call it AI memory

    The main reason for using two memory blocks here is that all image operations of the underlying code and LCD display are based on RGB565, but KPU needs the input of RGB888.

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

    When only the camera captures pictures, the hardware will automatically put a copy of the data into the RGB888 memory area, and the other will not automatically fill the RGB888 memory block. The software operation will only operate on the RGB565 memory, and will not automatically updateRGB888, (because the update takes time) This is worth noting,
    This means that every time we change the memory block of RGB565, for example, execute img = img.resize((224, 224)), if you want KPU to use the changed image, you need to execute img. pix_to_ai() to manually update the image of RGB565 to the area of ​​RGB888, and then you can call kpu related functions for model inference!

    The same update in the opposite direction also provides API: img.ai_to_pix(), which will update the data in the RGB888 area to the RGB565 area

    resize modify resolution

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

    Get and modify pixel value

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

    The second pixel B set here is 10, and it is actually found to be 8. This is a normal phenomenon. As mentioned earlier, the storage in the memory uses RGB565 for storage, so it will Error

    Copy image

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

    Crop image

    Also use the copy function

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

    Convert to bytes object

    Convert to RGB565 string

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

    The output value here is in the format of RGB565, which means that one pixel is stored in two bytes

    In addition, you can also compress the image to JPEG format first, and then convert it to bytes

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

    Using the compressed function here will not modify the original image, using the compress() function will modify the original image, but if the compressed size is larger than the original image, it will fail

    Convert to grayscale image

    img = img.to_grayscale(copy=False)
    

    Here the copy parameter means whether to re-apply for a piece of memory without modifying the original image

    Convert to RGB565 color image

    Convert to a color image, note that only the format has become a color image, the picture is not a color image, if you need to convert a gray image to a color image, use img.to_rainbow()

    img = img.to_rgb565(copy=True)
    

    Here the copy parameter means whether to re-apply for a piece of memory without modifying the original image
    If the original image is grayscale, it must be True

    Convert to color picture

    img = img.to_rainbow(copy=True)
    

    Here the copy parameter means whether to re-apply for a piece of memory without modifying the original image
    If the original image is grayscale, it must be True

    Save to file system

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

    Rotate

    img.rotation_corr([x_rotation=0.0[, y_rotation=0.0[, z_rotation=0.0[, x_translation=0.0[, y_translation=0.0[, zoom=1.0]]]]]])
    

    The brackets are optional parameters, that is, which axis to rotate along a certain angle. If this function is not available in the firmware of the minimum version, the full version of the firmware can be used