5.8. sail.Bmcv

Bmcv封装了常用的图像处理接口, 支持硬件加速。

实现接口硬件说明

本文档中, 在BM1684/BM1684X上实现的接口, 负责其实现的硬件单元可能有不同情况(i.e. crop_and_resize在BM1684上由VPP+智能视觉深度学习处理器实现)。影响实现的硬件单元的因素如下:

  1. 输入图片/输出图片数量不大于16

  2. 图片无需按照原图比例进行缩放

  3. 输入图片/输出图片不为以下数据格式: DATA_TYPE_EXT_1N_BYTE_SIGNED DATA_TYPE_EXT_4N_BYTE DATA_TYPE_EXT_FLOAT32

  4. 输入的图片device memory不在DDR0上

  5. 输入图片格式不为FORMAT_YUV422P, 输出图片格式不为FORMAT_NV12或FORMAT_COMPRESSED, 并且输入图片格式-输出图片格式不为以下组合:

input_format

output_format

FORMAT_RGBP_SEPARATE

FORMAT_ARGB_PACKED FORMAT_ABGR_PACKED

FORMAT_BGRP_SEPARATE

FORMAT_ARGB_PACKED FORMAT_ABGR_PACKED

FORMAT_GRAY

FORMAT_YUV420P FORMAT_YUV422P FORMAT_YUV444P

FORMAT_YUV420P

FORMAT_GRAY FORMAT_YUV422P FORMAT_YUV444P

FORMAT_YUV444P

FORMAT_GRAY

FORMAT_COMPRESSED

FORMAT_GRAY FORMAT_YUV422P FORMAT_YUV444P

当且仅当满足上述5个条件时, 接口实现硬件为"VPP+智能视觉深度学习处理器"的Bmcv接口会使用VPP; 否则, 将会使用智能视觉深度学习处理器, 智能视觉深度学习处理器仅支持最邻近插值(Nearest Interpolitan),如不满足上述使用VPP的条件且缩放算法为其它插值策略,将会报错。

5.8.1. __init__

初始化Bmcv

接口形式:
def __init__(self, handle: sail.Handle)

参数说明:

  • handle: sail.Handle

指定Bmcv使用的设备句柄。

5.8.2. bm_image_to_tensor

将BMImage/BMImageArray转换为Tensor。

接口形式1:
def bm_image_to_tensor(self, image: sail.BMImage) -> sail.Tensor

参数说明1:

  • image: sail.BMImage

需要转换的图像数据。

返回值说明1:

  • tensor: sail.Tensor

返回转换后的Tensor。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    tensor = bmcv.bm_image_to_tensor(BMimg)# here is a sail.Tensor
接口形式2:
def bm_image_to_tensor(self,
        image: sail.BMImageArray,
        tensor) -> None

参数说明2:

  • image: sail.BMImageArray

输入参数。需要转换的图像数据。

  • tensor: sail.Tensor

输出参数。转换后的Tensor。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    tensor = sail.Tensor(handle,(1920,1080),sail.Dtype.BM_FLOAT32,True,True)
    bmcv.bm_image_to_tensor(BMimg,tensor)

5.8.3. tensor_to_bm_image

将Tensor转换为BMImage/BMImageArray。

接口形式1:
def tensor_to_bm_image(self,
        tensor: sail.Tensor,
        bgr2rgb: bool=False,
        layout: str = 'nchw') -> sail.BMImage

参数说明1:

  • tensor: sail.Tensor

输入参数。待转换的Tensor。

  • bgr2rgb: bool, default: False

输入参数。是否进行图像的通道变换。

  • layout: str, default: 'nchw'

输入参数。输入Tensor的布局。

返回值说明1:

  • image : sail.BMImage

返回转换后的图像。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    tensor = bmcv.bm_image_to_tensor(BMimg)# here is a sail.Tensor
    BMimg2 = bmcv.tensor_to_bm_image(tensor)
接口形式2:
def tensor_to_bm_image(self,
        tensor: sail.Tensor,
        format: sail.Format) -> sail.BMImage

参数说明2:

  • tensor: sail.Tensor

输入参数。待转换的Tensor。

  • format: sail.Format

输入参数。BMImage的像素格式。

返回值说明2:

  • image : sail.BMImage

返回转换后的图像。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    tensor = bmcv.bm_image_to_tensor(BMimg)# here is a sail.Tensor
    BMimg2 = bmcv.tensor_to_bm_image(tensor, sail.Format.FORMAT_BGR_PLANAR)
接口形式3:
def tensor_to_bm_image(self,
        tensor: sail.Tensor,
        img: sail.BMImage | sail.BMImageArray,
        bgr2rgb: bool=False,
        layout: str = 'nchw') -> None

参数说明3:

  • tensor: sail.Tensor

输入参数。待转换的Tensor。

  • img : sail.BMImage | sail.BMImageArray

输出参数。返回转换后的图像。

  • bgr2rgb: bool, default: False

输入参数。是否进行图像的通道变换。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    tensor = bmcv.bm_image_to_tensor(BMimg)# here is a sail.Tensor
    BMimg2 = sail.BMImage()
    bmcv.tensor_to_bm_image(tensor,BMimg2)
接口形式4:
def tensor_to_bm_image(self,
        tensor: sail.Tensor,
        img: sail.BMImage | sail.BMImageArray,
        format: sail.Format) -> None

参数说明4:

  • tensor: sail.Tensor

输入参数。待转换的Tensor。

  • img: sail.BMImage | sail.BMImageArray

输出参数。返回转换后的图像。

  • format: sail.Format

输入参数。BMImage的像素格式。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    tensor = bmcv.bm_image_to_tensor(BMimg)# here is a sail.Tensor
    BMimg2 = sail.BMImage()
    bmcv.tensor_to_bm_image(tensor,BMimg2, sail.Format.FORMAT_BGR_PLANAR)

5.8.4. crop_and_resize

对图片进行裁剪并resize。

实现硬件 * BM1684: VPP+智能视觉深度学习处理器 * BM1684X: VPP

接口形式:
def crop_and_resize(self,
        input: sail.BMImage | sail.BMImageArray,
        crop_x0: int,
        crop_y0: int,
        crop_w: int,
        crop_h: int,
        resize_w: int,
        resize_h: int,
        resize_alg: sail.bmcv_resize_algorithm=sail.bmcv_resize_algorithm.BMCV_INTER_NEAREST)
            -> sail.BMImage

参数说明:

  • input : sail.BMImage | sail.BMImageArray

待处理的图像或图像数组。

  • crop_x0 : int

裁剪窗口在x轴上的起始点。

  • crop_y0 : int

裁剪窗口在y轴上的起始点。

  • crop_w : int

裁剪窗口的宽。

  • crop_h : int

裁剪窗口的高。

  • resize_w : int

图像resize的目标宽度。

  • resize_h : int

图像resize的目标高度。

  • resize_alg : sail.bmcv_resize_algorithm

图像resize的插值算法,默认为sail.bmcv_resize_algorithm.BMCV_INTER_NEAREST

返回值说明:

  • output : sail.BMImage | sail.BMImageArray

返回处理后的图像或图像数组。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    BMimg3 = bmcv.crop_and_resize(BMimg,0,0,BMimg.width(),BMimg.height(),640,640,sail.bmcv_resize_algorithm.BMCV_INTER_NEAREST)

5.8.5. crop

对图像进行裁剪。

接口形式1:
def crop(self,
        input: sail.BMImage | sail.BMImageArray,
        crop_x0: int,
        crop_y0: int,
        crop_w: int,
        crop_h: int) -> sail.BMImage | sail.BMImageArray

参数说明:

  • input : sail.BMImage | sail.BMImageArray

待处理的图像或图像数组。

  • crop_x0 : int

裁剪窗口在x轴上的起始点。

  • crop_y0 : int

裁剪窗口在y轴上的起始点。

  • crop_w : int

裁剪窗口的宽。

  • crop_h : int

裁剪窗口的高。

返回值说明:

  • output : sail.BMImage | sail.BMImageArray

返回处理后的图像或图像数组。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    crop_x0, crop_y0, crop_w, crop_h = 100, 100, 200, 200
    cropped_BMimg = bmcv.crop(BMimg, crop_x0, crop_y0, crop_w, crop_h)

对图像进行裁剪,可从一张图上裁剪出多个小图

接口形式2:
def crop(self,
        input: sail.BMImage
        rects: list[list[]] ) -> list[sail.BMImage]

参数说明:

  • input : sail.BMImage

待处理的图像。

  • rects: list[list[]]

[[crop_x0,crop_y0,crop_w0,crop_h0],[crop_x1,crop_y1,crop_w1,crop_h1]]

  • crop_xi : int

第i个裁剪窗口在x轴上的起始点。

  • crop_yi : int

第i个裁剪窗口在y轴上的起始点。

  • crop_wi : int

第i个裁剪窗口的宽。

  • crop_hi : int

第i个裁剪窗口的高。

返回值说明1:

  • output : list[sail.BMImage]

返回处理后的图像列表。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    rects = [
        [0, 0, 40, 40],
        [40, 40, 80, 80],
        #...more
    ]
    cropped_images_list = bmcv.crop(BMimg, rects)

5.8.6. resize

对图像进行resize。

接口形式:
def resize(self,
        input: sail.BMImage | sail.BMImageArray,
        resize_w: int,
        resize_h: int,
        resize_alg: bmcv_resize_algorithm = BMCV_INTER_NEAREST)
    -> sail.BMImage | sail.BMImageArray

参数说明:

  • input : sail.BMImage | sail.BMImageArray

待处理的图像或图像数组。

  • resize_w : int

图像resize的目标宽度。

  • resize_h : int

图像resize的目标高度。

  • resize_alg : sail.bmcv_resize_algorithm

图像resize的插值算法,默认为sail.bmcv_resize_algorithm.BMCV_INTER_NEAREST

返回值说明:

  • output : sail.BMImage | sail.BMImageArray

返回处理后的图像或图像数组。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    BMimg_resize = bmcv.resize(BMimg,640,640,resize_alg=sail.bmcv_resize_algorithm.BMCV_INTER_NEAREST)

5.8.7. vpp_crop_and_resize

利用VPP硬件加速图片的裁剪与resize。

实现硬件 * BM1684: VPP * BM1684X: VPP

接口形式:
def vpp_crop_and_resize(self,
                input: sail.BMImage | sail.BMImageArray,
                crop_x0: int,
                crop_y0: int,
                crop_w: int,
                crop_h: int,
                resize_w: int,
                resize_h: int,
                resize_alg: bmcv_resize_algorithm = BMCV_INTER_NEAREST)
                -> sail.BMImage | sail.BMImageArray

参数说明:

  • input : sail.BMImage | sail.BMImageArray

待处理的图像或图像数组。

  • crop_x0 : int

裁剪窗口在x轴上的起始点。

  • crop_y0 : int

裁剪窗口在y轴上的起始点。

  • crop_w : int

裁剪窗口的宽。

  • crop_h : int

裁剪窗口的高。

  • resize_w : int

图像resize的目标宽度。

  • resize_h : int

图像resize的目标高度。

  • resize_alg : sail.bmcv_resize_algorithm

图像resize的插值算法,默认为sail.bmcv_resize_algorithm.BMCV_INTER_NEAREST

返回值说明:

  • output : sail.BMImage | sail.BMImageArray

返回处理后的图像或图像数组。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    crop_x0 = 100
    crop_y0 = 100
    crop_w = 200
    crop_h = 200
    resize_w = 300
    resize_h = 300

    resized_BMimg = bmcv.vpp_crop_and_resize(
        BMimg,
        crop_x0,
        crop_y0,
        crop_w,
        crop_h,
        resize_w,
        resize_h,
        sail.bmcv_resize_algorithm.BMCV_INTER_NEAREST
    )

5.8.8. vpp_crop_and_resize_padding

利用VPP硬件加速图片的裁剪与resize,并padding到指定大小。

实现硬件 * BM1684: VPP * BM1684X: VPP

接口形式:
def vpp_crop_and_resize_padding(self,
                    input: sail.BMImage | sail.BMImageArray,
                    crop_x0: int,
                    crop_y0: int,
                    crop_w: int,
                    crop_h: int,
                    resize_w: int,
                    resize_h: int,
                    padding: sail.PaddingAtrr,
                    resize_alg: bmcv_resize_algorithm = BMCV_INTER_NEAREST)
                     -> sail.BMImage | sail.BMImageArray

参数说明:

  • input : sail.BMImage | sail.BMImageArray

待处理的图像或图像数组。

  • crop_x0 : int

裁剪窗口在x轴上的起始点。

  • crop_y0 : int

裁剪窗口在y轴上的起始点。

  • crop_w : int

裁剪窗口的宽。

  • crop_h : int

裁剪窗口的高。

  • resize_w : int

图像resize的目标宽度。

  • resize_h : int

图像resize的目标高度。

  • padding : sail.PaddingAtrr

padding的配置信息。

  • resize_alg : sail.bmcv_resize_algorithm

图像resize的插值算法,默认为sail.bmcv_resize_algorithm.BMCV_INTER_NEAREST

返回值说明:

  • output : sail.BMImage | sail.BMImageArray

返回处理后的图像或图像数组。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    paddingatt = sail.PaddingAtrr()
    paddingatt.set_stx(0)
    paddingatt.set_sty(0)
    paddingatt.set_w(640)
    paddingatt.set_h(640)
    paddingatt.set_r(114)
    paddingatt.set_g(114)
    paddingatt.set_b(114)
    BMimg4 = bmcv.vpp_crop_and_resize_padding(BMimg,0,0,BMimg.width(),BMimg.height(),640,640,paddingatt)

5.8.9. vpp_crop

利用VPP硬件加速图片的裁剪。

接口形式:
def vpp_crop(self,
    input: sail.BMImage | sail.BMImageArray,
    crop_x0: int,
    crop_y0: int,
    crop_w: int,
    crop_h: int)->sail.BMImage | sail.BMImageArray

参数说明:

  • input : sail.BMImage | sail.BMImageArray

待处理的图像或图像数组。

  • crop_x0 : int

裁剪窗口在x轴上的起始点。

  • crop_y0 : int

裁剪窗口在y轴上的起始点。

  • crop_w : int

裁剪窗口的宽。

  • crop_h : int

裁剪窗口的高。

返回值说明:

  • output : sail.BMImage | sail.BMImageArray

返回处理后的图像或图像数组。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    crop_x0 = 100
    crop_y0 = 100
    crop_w = 200
    crop_h = 200
    BMimg4 = bmcv.vpp_crop(BMimg,crop_x0,crop_y0,crop_w,crop_h)

5.8.10. vpp_resize

利用VPP硬件加速图片的resize,采用最近邻插值算法。

接口形式1:
def vpp_resize(self,
        input: sail.BMImage | sail.BMImageArray,
        resize_w: int,
        resize_h: int,
        resize_alg: bmcv_resize_algorithm = BMCV_INTER_NEAREST)->sail.BMImage | sail.BMImageArray

参数说明1:

  • input : sail.BMImage | sail.BMImageArray

待处理的图像或图像数组。

  • resize_w : int

图像resize的目标宽度。

  • resize_h : int

图像resize的目标高度。

  • resize_alg : sail.bmcv_resize_algorithm

图像resize的插值算法,默认为sail.bmcv_resize_algorithm.BMCV_INTER_NEAREST

返回值说明1:

  • output : sail.BMImage | sail.BMImageArray

返回处理后的图像或图像数组。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    BMimg_resize = bmcv.vpp_resize(BMimg,640,640,resize_alg=sail.bmcv_resize_algorithm.BMCV_INTER_NEAREST)
接口形式2:
def vpp_resize(self,
       input: sail.BMImage | sail.BMImageArray,
       output: sail.BMImage | sail.BMImageArray,
       resize_w: int,
       resize_h: int,
       resize_alg: bmcv_resize_algorithm = BMCV_INTER_NEAREST)->None

参数说明2:

  • input : sail.BMImage | sail.BMImageArray

输入参数。待处理的图像或图像数组。

  • output : sail.BMImage | sail.BMImageArray

输出参数。处理后的图像或图像数组。

  • resize_w : int

输入参数。图像resize的目标宽度。

  • resize_h : int

输入参数。图像resize的目标高度。

  • resize_alg : sail.bmcv_resize_algorithm

图像resize的插值算法,默认为sail.bmcv_resize_algorithm.BMCV_INTER_NEAREST

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    BMimg_resize = sail.BMImage()
    bmcv.vpp_resize(BMimg,BMimg_resize,640,640,resize_alg=sail.bmcv_resize_algorithm.BMCV_INTER_NEAREST)

5.8.11. vpp_resize_padding

利用VPP硬件加速图片的resize,并padding。

接口形式:
def vpp_resize_padding(self,
        input: sail.BMImage | sail.BMImageArray,
        resize_w: int,
        resize_h: int,
        padding: PaddingAtrr,
        resize_alg: bmcv_resize_algorithm = BMCV_INTER_NEAREST)->sail.BMImage | sail.BMImageArray

参数说明:

  • input : sail.BMImage | sail.BMImageArray

待处理的图像或图像数组。

  • resize_w : int

图像resize的目标宽度。

  • resize_h : int

图像resize的目标高度。

  • padding : sail.PaddingAtrr

padding的配置信息。

  • resize_alg : sail.bmcv_resize_algorithm

图像resize的插值算法,默认为sail.bmcv_resize_algorithm.BMCV_INTER_NEAREST

返回值说明:

  • output : sail.BMImage | sail.BMImageArray

返回处理后的图像或图像数组。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name, True, tpu_id)
    BMimg = decoder.read(handle)  # here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    paddingatt = sail.PaddingAtrr()
    paddingatt.set_stx(0)
    paddingatt.set_sty(0)
    paddingatt.set_w(640)
    paddingatt.set_h(640)
    paddingatt.set_r(114)
    paddingatt.set_g(114)
    paddingatt.set_b(114)
    BMimg4 = bmcv.vpp_resize_padding(BMimg,640,640,paddingatt)

5.8.12. warp

对图像进行仿射变换。

实现硬件 * BM1684: 智能视觉深度学习处理器 * BM1684X: 智能视觉深度学习处理器

接口形式1:
def warp(self,
    input: sail.BMImage | sail.BMImageArray,
    matrix: list,
    use_bilinear: int = 0,
    similar_to_opencv: bool = False)->sail.BMImage | sail.BMImageArray

参数说明1:

  • input : sail.BMImage | sail.BMImageArray

待处理的图像或图像数组。

  • matrix: 2d list

2x3的仿射变换矩阵。

  • use_bilinear: int

是否使用双线性插值,默认为0使用最近邻插值,1为双线性插值

  • similar_to_opencv: bool

是否使用与opencv仿射变换对齐的接口

返回值说明1:

  • output : sail.BMImage | sail.BMImageArray

返回处理后的图像或图像数组。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    rotated_matrix = [[0.9996914396,-0.02484,0],[0.02484,0.9996914396,0]]
    BMimg6 = bmcv.warp(BMimg, rotated_matrix)
接口形式2:
def warp(self,
    input: sail.BMImage | sail.BMImageArray,
    output: sail.BMImage | sail.BMImageArray,
    matrix: list,
    use_bilinear: int = 0,
    similar_to_opencv: bool = False)->int

参数说明2:

  • input : sail.BMImage | sail.BMImageArray

待处理的图像或图像数组。

  • output : sail.BMImage | sail.BMImageArray

待返回的输出图像或图像数组。

  • matrix: 2d list

2x3的仿射变换矩阵。

  • use_bilinear: int

是否使用双线性插值,默认为0使用最近邻插值,1为双线性插值

  • similar_to_opencv: bool

是否使用与opencv仿射变换对齐的接口

返回值说明2:

如果成功返回0,否则返回非0值。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    rotated_matrix = [[0.9996914396,-0.02484,0],[0.02484,0.9996914396,0]]
    output = sail.BMImage()
    ret = bmcv.warp(BMimg, output,rotated_matrix)

5.8.13. convert_to

对图像进行线性变换。

实现硬件 * BM1684: 智能视觉深度学习处理器 * BM1684X: VPP+智能视觉深度学习处理器

接口形式1:
def convert_to(self,
    input: sail.BMImage | sail.BMImageArray,
    alpha_beta: tuple)->sail.BMImage | sail.BMImageArray

参数说明1:

  • input : sail.BMImage | sail.BMImageArray

待处理的图像或图像数组。

  • alpha_beta: tuple

分别为三个通道线性变换的系数((a0, b0), (a1, b1), (a2, b2))。

返回值说明1:

  • output : sail.BMImage | sail.BMImageArray

返回处理后的图像或图像数组。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    alpha_beta = (1.0/255,0),(1.0/255,0),(1.0/255,0)
    BMimg5 = bmcv.convert_to(BMimg, alpha_beta)
接口形式2:
def convert_to(self,
        input: sail.BMImage | sail.BMImageArray,
        output: sail.BMImage | sail.BMImageArray,
        alpha_beta: tuple)->None

参数说明2:

  • input : sail.BMImage | sail.BMImageArray

输入参数。待处理的图像或图像数组。

  • output : sail.BMImage | sail.BMImageArray

输出参数。返回处理后的图像或图像数组。

  • alpha_beta: tuple

分别为三个通道线性变换的系数((a0, b0), (a1, b1), (a2, b2))。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    alpha_beta = (1.0/255,0),(1.0/255,0),(1.0/255,0)
    BMimg5 = sail.BMImage()
    bmcv.convert_to(BMimg, BMimg5,alpha_beta)

5.8.14. yuv2bgr

将图像的格式从YUV转换为BGR。

实现硬件 * BM1684: 智能视觉深度学习处理器+VPP * BM1684X: VPP

接口形式:
def yuv2bgr(input: sail.BMImage | sail.BMImageArray)
        -> sail.BMImage | sail.BMImageArray

参数说明:

  • input : sail.BMImage | sail.BMImageArray

待转换的图像。

返回值说明:

  • output : sail.BMImage | sail.BMImageArray

返回转换后的图像。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    BMimg5 = bmcv.yuv2bgr(BMimg)

5.8.15. rectangle

在图像上画一个矩形框。

实现硬件 * BM1684: 智能视觉深度学习处理器 * BM1684X: VPP

接口形式:
def rectangle(self,
        image: sail.BMImage,
        x0: int,
        y0: int,
        w: int,
        h: int,
        color: tuple,
        thickness: int=1)->int

def rectangle(self,
        image: sail.bm_image,
        x0: int,
        y0: int,
        w: int,
        h: int,
        color: tuple,
        thickness: int=1)->int

参数说明:

  • image : sail.BMImage 或 sail.bm_image

待画框的图像。

  • x0 : int

矩形框在x轴上的起点。

  • y0 : int

矩形框在y轴上的起点。

  • w : int

矩形框的宽度。

  • h : int

矩形框的高度。

  • color : tuple

矩形框的颜色。

  • thickness : int

矩形框线条的粗细。

返回值说明:

如果画框成功返回0,否则返回非0值。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    ret = bmcv.rectangle(BMimg, 20, 20, 600, 600,(0,0,255),2)
    # ret = bmcv.rectangle(BMimg.data(), 20, 20, 600, 600,(0,0,255),2)

5.8.16. fillRectangle

在图像上填充一个矩形框。

实现硬件 * BM1684: 智能视觉深度学习处理器 * BM1684X: VPP

接口形式:
def fillRectangle(self,
        image: sail.BMImage,
        x0: int,
        y0: int,
        w: int,
        h: int,
        color: tuple)->int

def fillRectangle(self,
        image: sail.bm_image,
        x0: int,
        y0: int,
        w: int,
        h: int,
        color: tuple)->int

参数说明:

  • image : sail.BMImage 或 sail.bm_image

待画框的图像。

  • x0 : int

矩形框在x轴上的起点。

  • y0 : int

矩形框在y轴上的起点。

  • w : int

矩形框的宽度。

  • h : int

矩形框的高度。

  • color : tuple

矩形框的颜色。

返回值说明:

如果画框成功返回0,否则返回非0值。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    ret = bmcv.fillRectangle(BMimg, 20, 20, 600, 600,(0,0,255))
    # ret = bmcv.fillRectangle(BMimg.data(), 20, 20, 600, 600,(0,0,255))

5.8.17. imwrite

将图像保存在特定文件。

实现硬件

  • BM1684: JPU+VPP+智能视觉深度学习处理器

  • BM1684X: JPU+VPP

接口形式:
def imwrite(self, file_name: str, image: sail.BMImage) -> int

def imwrite(self, file_name: str, image: sail.bm_image) -> int

参数说明:

  • file_name : str

文件的名称。

  • output : sail.BMImage 或 sail.bm_image

需要保存的图像。

返回值说明:

  • process_status : int

如果保存成功返回0,否则返回非0值。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    bmcv.imwrite("{}_{}.jpg".format(BMimg.width(),BMimg.height()),BMimg)
    # bmcv.imwrite("{}_{}.jpg".format(BMimg.width(),BMimg.height()),BMimg.data())

5.8.18. imread

读取和解码图片文件,仅支持 JPEG baseline 格式的硬解码。对于其他格式,如 PNG 和 BMP,则采用软解码。 对于 JPEG baseline 图片,返回的 BMImage 将保持 YUV 色彩空间,像素格式依据图片文件本身的采样方式,例如 YUV420; 而对于其他格式,返回的 BMImage 将保持其输入的对应色彩空间。

实现硬件

  • BM1684: JPU(JPEG baseline), CPU(其他格式)

  • BM1684X: JPU(JPEG baseline), CPU(其他格式)

接口形式:
def imread(self, filename: str) -> BMImage

参数说明:

  • filename : str

需要读取的图片文件路径。

返回值说明:

  • output : sail.BMImage

返回解码得到的BMImage。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    bmcv = sail.Bmcv(handle)
    filename = "your_image_path"
    BMimg = bmcv.imread(filename)

5.8.19. get_handle

获取Bmcv中的设备句柄Handle。

接口形式:
def get_handle(self)->sail.Handle

返回值说明:

  • handle: sail.Handle

Bmcv中的设备句柄Handle。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    handle1 = bmcv.get_handle()

5.8.20. crop_and_resize_padding

对图像进行裁剪并resize,然后padding。

实现硬件 * BM1684: VPP+智能视觉深度学习处理器 * BM1684X: VPP+智能视觉深度学习处理器

接口形式:
def crop_and_resize_padding(self,
                input: sail.BMImage,
                crop_x0: int,
                crop_y0: int,
                crop_w: int,
                crop_h: int,
                resize_w: int,
                resize_h: int,
                padding: PaddingAtrr,
                resize_alg=sail.bmcv_resize_algorithm.BMCV_INTER_NEAREST)
            ->sail.BMImage

参数说明:

  • input : sail.BMImage

待处理的图像。

  • crop_x0 : int

裁剪窗口在x轴上的起始点。

  • crop_y0 : int

裁剪窗口在y轴上的起始点。

  • crop_w : int

裁剪窗口的宽。

  • crop_h : int

裁剪窗口的高。

  • resize_w : int

图像resize的目标宽度。

  • resize_h : int

图像resize的目标高度。

  • padding : sail.PaddingAtrr

padding的配置信息。

  • resize_alg : bmcv_resize_algorithm

resize采用的插值算法。

返回值说明:

  • output : sail.BMImage

返回处理后的图像。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    crop_x0 = 100
    crop_y0 = 100
    crop_w = 200
    crop_h = 200
    resize_w = 300
    resize_h = 300

    paddingatt = sail.PaddingAtrr()
    paddingatt.set_stx(0)
    paddingatt.set_sty(0)
    paddingatt.set_w(300)
    paddingatt.set_h(300)
    paddingatt.set_r(114)
    paddingatt.set_g(114)
    paddingatt.set_b(114)
    padded_BMimg = bmcv.crop_and_resize_padding(
        BMimg,
        crop_x0,
        crop_y0,
        crop_w,
        crop_h,
        resize_w,
        resize_h,
        paddingatt,
        sail.bmcv_resize_algorithm.BMCV_INTER_NEAREST
    )

5.8.21. convert_format

将图像的格式转换为output中的格式,并拷贝到output。

实现硬件 * BM1684: VPP+智能视觉深度学习处理器 * BM1684X: VPP

接口形式1:
def convert_format(self, input: sail.BMImage, output: sail.BMImage)->None

参数说明1:

  • input : sail.BMImage

输入参数。待转换的图像。

  • output : sail.BMImage

输出参数。将input中的图像转化为output的图像格式并拷贝到output。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    output = sail.BMImage()
    bmcv.convert_format(BMimg,output)

接口形式2:

将一张图像转换成目标格式。

def convert_format(self, input: sail.BMImage, image_format:sail.bm_image_format_ext)->sail.BMImage

参数说明2:

  • input : sail.BMImage

待转换的图像。

  • image_format : sail.bm_image_format_ext

转换的目标格式。

返回值说明2:

  • output : sail.BMImage

返回转换后的图像。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    output = bmcv.convert_format(BMimg,sail.FORMAT_BGR_PLANAR)

5.8.22. vpp_convert_format

利用VPP硬件加速图片的格式转换。

实现硬件 * BM1684: VPP * BM1684X: VPP

接口形式1:
def vpp_convert_format(self, input: sail.BMImage, output: sail.BMImage)->None

参数说明1:

  • input : sail.BMImage

输入参数。待转换的图像。

  • output : sail.BMImage

输出参数。将input中的图像转化为output的图像格式并拷贝到output。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    output = sail.BMImage()
    bmcv.vpp_convert_format(BMimg,output)

接口形式2:

将一张图像转换成目标格式。

def vpp_convert_format(self, input: sail.BMImage, image_format:sail.bm_image_format_ext)->sail.BMImage

参数说明2:

  • input : sail.BMImage

待转换的图像。

  • image_format : sail.bm_image_format_ext

转换的目标格式。

返回值说明2:

  • output : sail.BMImage

返回转换后的图像。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    output = bmcv.vpp_convert_format(BMimg,sail.FORMAT_BGR_PLANAR)

5.8.23. putText

在图像上添加text。只支持英文文字。

输入的BMImage支持的像素格式为: FORMAT_GRAY、FORMAT_YUV420P、FORMAT_YUV422P、FORMAT_YUV444P、FORMAT_NV12、 FORMAT_NV21、FORMAT_NV16、FORMAT_NV61。

实现硬件 * BM1684: 处理器 * BM1684X: 处理器

接口形式:
def putText(self,
        input: sail.BMImage,
        text: str,
        x: int,
        y: int,
        color: tuple,
        fontScale: int,
        thickness: int)->int

def putText(self,
        input: sail.bm_image,
        text: str,
        x: int,
        y: int,
        color: tuple,
        fontScale: int,
        thickness: int)->int

参数说明:

  • input : sail.BMImage 或 sail.bm_image

待处理的图像。

  • text: str

需要添加的文本。

  • x: int

添加的起始点位置。

  • y: int

添加的起始点位置。

  • color : tuple

字体的颜色。

  • fontScale: int

字号的大小。

  • thickness : int

字体的粗细。建议设置为偶数。

返回值说明:

  • process_status : int

如果处理成功返回0,否则返回非0值。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    bgr_img = decoder.read(handle)
    bmcv = sail.Bmcv(handle)
    yuv_img = bmcv.convert_format(bgr_img, sail.FORMAT_YUV420P)
    ret = bmcv.putText(yuv_img, "some text" , 20, 20, [0,0,255], 1.4, 2)
    assert ret == 0

5.8.24. image_add_weighted

将两张图像按不同的权重相加。

实现硬件 * BM1684: 智能视觉深度学习处理器 * BM1684X: 智能视觉深度学习处理器

接口形式1:
def image_add_weighted(self,
            input0: sail.BMImage,
            alpha: float,
            input1: sail.BMImage,
            beta: float,
            gamma: float,
            output: sail.BMImage)->None

参数说明1:

  • input0 : sail.BMImage

输入参数。待处理的图像0。

  • alpha : float

输入参数。两张图像相加的权重alpha

  • input1 : sail.BMImage

输入参数。待处理的图像1。

  • beta : float

输入参数。两张图像相加的权重beta

  • gamma : float

输入参数。两张图像相加的权重gamma

  • output: BMImage

输出参数。相加后的图像output = input1 * alpha + input2 * beta + gamma

示例代码1:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name1 = "your_image_path1"
    image_name2 = "your_image_path2"
    decoder1 = sail.Decoder(image_name1,True,tpu_id)
    decoder2 = sail.Decoder(image_name2,True,tpu_id)
    BMimg1 = decoder1.read(handle)# here is a sail.BMImage
    BMimg2 = decoder2.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    bmg = sail.BMImage()
    bmcv.image_add_weighted(BMimg1,0.5,BMimg2,0.5,0.5,bmg)
接口形式2:
def image_add_weighted(self,
            input0: sail.BMImage,
            alpha: float,
            input1: sail.BMImage,
            beta: float,
            gamma: float)->sail.BMImage

参数说明2:

  • input0 : sail.BMImage

输入参数。待处理的图像0。

  • alpha : float

输入参数。两张图像相加的权重alpha

  • input1 : sail.BMImage

输入参数。待处理的图像1。

  • beta : float

输入参数。两张图像相加的权重beta

  • gamma : float

输入参数。两张图像相加的权重gamma

返回值说明2:

  • output: sail.BMImage

返回相加后的图像output = input1 * alpha + input2 * beta + gamma

示例代码2:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name1 = "your_image_path1"
    image_name2 = "your_image_path2"
    decoder1 = sail.Decoder(image_name1,True,tpu_id)
    decoder2 = sail.Decoder(image_name2,True,tpu_id)
    BMimg1 = decoder1.read(handle)# here is a sail.BMImage
    BMimg2 = decoder2.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    bmg = bmcv.image_add_weighted(BMimg1,0.5,BMimg2,0.5,0.5)

5.8.25. image_copy_to

进行图像间的数据拷贝

实现硬件 * BM1684: 智能视觉深度学习处理器 * BM1684X: VPP+智能视觉深度学习处理器

接口形式:
def image_copy_to(self,
            input: BMImage|BMImageArray,
            output: BMImage|BMImageArray,
            start_x: int,
            start_y: int)->None

参数说明:

  • input: BMImage|BMImageArray

输入参数。待拷贝的BMImage或BMImageArray。

  • output: BMImage|BMImageArray

输出参数。拷贝后的BMImage或BMImageArray

  • start_x: int

输入参数。拷贝到目标图像的起始点。

  • start_y: int

输入参数。拷贝到目标图像的起始点。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name1 = "your_image_path1"
    image_name2 = "your_image_path2"
    decoder1 = sail.Decoder(image_name1,True,tpu_id)
    decoder2 = sail.Decoder(image_name2,True,tpu_id)
    BMimg1 = decoder1.read(handle)# here is a sail.BMImage
    BMimg2 = decoder2.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    bmcv.image_copy_to(BMimg1,BMimg2,0,0)

5.8.26. image_copy_to_padding

进行input和output间的图像数据拷贝并padding。

实现硬件 * BM1684: 智能视觉深度学习处理器 * BM1684X: VPP+智能视觉深度学习处理器

接口形式:
def image_copy_to_padding(self,
            input: BMImage|BMImageArray,
            output: BMImage|BMImageArray,
            padding_r: int,
            padding_g: int,
            padding_b: int,
            start_x: int,
            start_y: int)->None

参数说明:

  • input: BMImage|BMImageArray

输入参数。待拷贝的BMImage或BMImageArray。

  • output: BMImage|BMImageArray

输出参数。拷贝后的BMImage或BMImageArray

  • padding_r: int

输入参数。R通道的padding值。

  • padding_g: int

输入参数。G通道的padding值。

  • padding_b: int

输入参数。B通道的padding值。

  • start_x: int

输入参数。拷贝到目标图像的起始点。

  • start_y: int

输入参数。拷贝到目标图像的起始点。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name1 = "your_image_path1"
    image_name2 = "your_image_path2"
    decoder1 = sail.Decoder(image_name1,True,tpu_id)
    decoder2 = sail.Decoder(image_name2,True,tpu_id)
    BMimg1 = decoder1.read(handle)# here is a sail.BMImage
    BMimg2 = decoder2.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    bmcv.image_copy_to_padding(BMimg1,BMimg2,128,128,128,0,0)

5.8.27. nms

利用智能视觉深度学习处理器进行NMS

注意:请查询《BMCV开发参考手册/BMCV API》确认当前算子是否适配BM1688。

实现硬件 * BM1684: 智能视觉深度学习处理器 * BM1684X: 智能视觉深度学习处理器

接口形式:
def nms(self, input: numpy.ndarray, threshold: float)->numpy.ndarray

参数说明:

  • input: numpy.ndarray

待处理的检测框的数组,shape必须是(n,5) n<56000 [left,top,right,bottom,score]。

  • threshold: float

nms的阈值。

返回值说明:

  • result: numpy.ndarray

返回NMS后的检测框数组。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    bmcv = sail.Bmcv(handle)
    input_boxes = np.array([
    [50, 50, 100, 100, 0.9],
    [60, 60, 110, 110, 0.85],
    [200, 200, 250, 250, 0.7],
    [130, 50, 180, 100, 0.8],
    [205, 205, 255, 255, 0.75]
    ])
    nms_threshold = 0.5
    selected_boxes  = bmcv.nms(input_boxes, nms_threshold)
    print(selected_boxes)

5.8.28. drawPoint

在图像上画点。

实现硬件 * BM1684: 处理器 * BM1684X: VPP

接口形式:
def drawPoint(self,
        image: BMImage,
        center: Tuple[int, int],
        color: Tuple[int, int, int],
        radius: int) -> int:

def drawPoint(self,
        image: bm_image,
        center: Tuple[int, int],
        color: Tuple[int, int, int],
        radius: int) -> int:

参数说明:

  • image: BMImage 或 bm_image

输入图像,在该BMImage上直接画点作为输出。

  • center: Tuple[int, int]

点的中心坐标。

  • color: Tuple[int, int, int]

点的颜色。

  • radius: int

点的半径。

返回值说明

如果画点成功返回0,否则返回非0值。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    ret = bmcv.drawPoint(BMimg, (320, 320), (0,255,255),2)
    # ret = bmcv.drawPoint(BMimg.data(), (320, 320), (0,255,255),2)

5.8.29. warp_perspective

对图像进行透视变换。

接口形式:
def warp_perspective(self,
            input: BMImage,
            coordinate: tuple,
            output_width: int,
            output_height: int,
            format: bm_image_format_ext = FORMAT_BGR_PLANAR,
            dtype: bm_image_data_format_ext = DATA_TYPE_EXT_1N_BYTE,
            use_bilinear: int = 0 ) -> BMImage:

参数说明:

  • input: BMImage

待处理的图像。

  • coordinate: tuple

变换区域的四顶点原始坐标。tuple(tuple(int,int))

例如((left_top.x, left_top.y), (right_top.x, right_top.y), (left_bottom.x, left_bottom.y), (right_bottom.x, right_bottom.y))

  • output_width: Output width

输出图像的宽。

  • output_height: Output height

输出图像的高。

  • bm_image_format_ext: sail.Format

输出图像的格式。

  • dtype: sail.ImgDtype

输出图像的数据类型。

  • use_bilinear: bool

是否使用双线性插值。

返回值说明:

  • output: image

输出变换后的图像。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    img = bmcv.warp_perspective(BMimg, ((100, 100), (540, 100), (100, 380), (540, 380)),640,640)

5.8.30. get_bm_data_type

将ImgDtype转换为Dtype

接口形式:
def get_bm_data_type((self, format: sail.ImgDtype) -> sail.Dtype

参数说明:

  • format: sail.ImgDtype

需要转换的类型。

返回值说明:

  • ret: sail.Dtype

转换后的类型。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    type = bmcv.get_bm_data_type(sail.DATA_TYPE_EXT_FLOAT32)

5.8.31. get_bm_image_data_format

将Dtype转换为ImgDtype。

接口形式:
def get_bm_image_data_format(self, dtype: sail.Dtype) -> sail.ImgDtype

参数说明:

  • dtype: sail.Dtype

需要转换的sail.Dtype

返回值说明:

  • ret: sail.ImgDtype

返回转换后的类型。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    type = bmcv.get_bm_image_data_format(sail.BM_FLOAT32)

5.8.32. imdecode

从内存中载入图像到BMImage中。

接口形式:
def imdecode(self, data_bytes: bytes) -> sail.BMImage:

参数说明:

  • data_bytes: bytes

系统内存中图像的bytes

返回值说明:

  • ret: sail.BMImage

返回解码后的图像。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    with open(image_name, 'rb') as image_file:
        image_data_bytes = image_file.read()
    bmcv = sail.Bmcv(handle)
    src_img = bmcv.imdecode(image_data_bytes)

5.8.33. imencode

编码一张图片,并返回编码后的数据。

接口形式:
def imencode(self, ext: str, img: BMImage) -> numpy.ndarray:

参数说明:

  • ext: str

输入参数。图片编码格式。 ".jpg" , ".png" 等。

  • img: BMImage

输入参数。输入图片,只支持FORMAT_BGR_PACKED,DATA_TYPE_EXT_1N_BYTE的图片。

返回值说明:

  • ret: numpy.array

编码后放在系统内存中的数据。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    ret = bmcv.imencode(".jpg",BMimg)

5.8.34. fft

实现对Tensor的快速傅里叶变换。

注意:请查询《BMCV开发参考手册/BMCV API》确认当前算子是否适配BM1688。

接口形式:
fft(self, forward: bool, input_real: Tensor) -> list[Tensor]

fft(self, forward: bool, input_real: Tensor, input_imag: Tensor) -> list[Tensor]

参数说明:

  • forward: bool

是否进行正向迁移。

  • input_real: Tensor

输入的实数部分。

  • input_imag: Tensor

输入的虚数部分。

返回值说明:

  • ret: list[Tensor]

返回输出的实数部分和虚数部分。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    random_array1 = np.random.rand(1, 1, 512, 512).astype('float32'),
    random_array2 = np.random.rand(1, 1, 512, 512).astype('float32'),
    bmcv = sail.Bmcv(handle)
    input_real  = sail.Tensor(handle,random_array1,True)
    input_imag  = sail.Tensor(handle,random_array2,True)
    forward = True
    result_complex = bmcv.fft(forward,input_real,input_imag)

5.8.35. convert_yuv420p_to_gray

将YUV420P格式的图片转为灰度图。

接口形式1:
def convert_yuv420p_to_gray(self, input: sail.BMImage, output: sail.BMImage)->None

参数说明1:

  • input : sail.BMImage

输入参数。待转换的图像。

  • output : sail.BMImage

输出参数。转换后的图像。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg1 = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    BMimg2 = sail.BMImage()
    bmcv.convert_yuv420p_to_gray(BMimg1,BMimg2)

接口形式2:

将YUV420P格式的图片转为灰度图。

def convert_yuv420p_to_gray_(self, input: sail.bm_image, output: sail.bm_image)->None

参数说明2:

  • input : sail.bm_image

待转换的图像。

  • output : sail.bm_image

转换后的图像。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg1 = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    bmg = sail.BMImage()
    bmcv.convert_yuv420p_to_gray_(BMimg1.data(),bmg.data())

5.8.36. mat_to_bm_image

将opencv的mat转为sail的BMImage。

接口形式1:
def mat_to_bm_image(self, mat: numpy.ndarray[numpy.uint8]) -> BMImage:

参数说明1:

  • mat : numpy

输入参数。待转换的opencv mat。

返回值说明:

  • ret: sail.BMImage

返回转换后的sail.BMImage。

示例代码:
import sophon.sail as sail
import cv2

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    bmcv = sail.Bmcv(handle)
    opencv_mat = cv2.imread(image_name)
    sail_bm_image = bmcv.mat_to_bm_image(opencv_mat)
接口形式2:
def mat_to_bm_image(self, mat: numpy.ndarray[numpy.uint8], img: BMImage) -> int:

参数说明2:

  • mat : numpy

待转换的opencv mat。

  • img : sail.BMImage

转换后的BMImage。

返回值说明:

  • ret: int

成功后返回0

示例代码:
import sophon.sail as sail
import cv2

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    bmcv = sail.Bmcv(handle)
    opencv_mat = cv2.imread(image_name)
    BMimg2 = sail.BMImage()
    ret = bmcv.mat_to_bm_image(opencv_mat,BMimg2)

5.8.37. watermark_superpose

实现对图片添加多个水印。

接口形式:
def watermark_superpose(self,
image: sail.BMImage,
water_name:string,
bitmap_type: int,
pitch: int,
rects: list[list[int]],
color: tuple
        )->int

参数说明:

  • image: sail.BMImage

输入图片

  • water_name:string

水印文件路径

  • bitmap_type: int

输入参数。水印类型, 值0表示水印为8bit数据类型(有透明度信息), 值1表示水印为1bit数据类型(无透明度信息)。

  • pitch: int

输入参数。水印文件每行的byte数, 可理解为水印的宽。

  • rects: list[list[int]]

输入参数。水印位置,包含每个水印起始点和宽高。

  • color: tuple

输入参数。水印的颜色。

返回值说明:

  • ret: int

返回是否成功

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path1"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg1 = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    water_name = 'your_watermark_path'
    ret = bmcv.watermark_superpose(BMimg1,water_name,0,117,[[0,0,117,79],[0,90,117,79]],[128,128,128])

5.8.38. polylines

可以实现在一张图像上画一条或多条线段,从而可以实现画多边形的功能,并支持指定线的颜色和线的宽度。

接口形式:
def polylines(self, image: BMImage, pts: list[list[tuple(int, int)]], isClosed: bool, color: tuple(int, int, int), thickness: int = 1, shift: int = 0) -> int:

参数说明:

  • img : sail.BMImage

输入图片。

  • pts : list[list[tuple(int, int)]]

线段的起始点和终点坐标,可输入多个坐标点。图像左上角为原点,向右延伸为x方向,向下延伸为y方向。

  • isClosed : bool

图形是否闭合。

  • color : tuple(int, int, int)

画线的颜色,分别为RGB三个通道的值。

  • thickness : int

画线的宽度,对于YUV格式的图像建议设置为偶数。

  • shift : int

多边形缩放倍数,默认不缩放。缩放倍数为(1/2)^shift。

返回值说明:

  • ret: int

成功后返回0

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg1 = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    bm = bmcv.vpp_convert_format(BMimg1,sail.FORMAT_YUV444P)
    ret = bmcv.polylines(bm,[[(10,20),(40,80)]],True,[128,128,128])

5.8.39. mosaic

该接口用于在图像上打一个或多个马赛克。

接口形式:
def mosaic(self, mosaic_num: int, img: sail.BMImage, rects: list[list[int,int,int,int]], is_expand:int) -> int

参数说明:

  • mosaic_num : int

马赛克数量,指rects中列表长度。

  • img : sail.BMImage

待转换的图像。

  • rects : list[list[int,int,int,int]]

多个马赛克位置,列表中每个元素中参数为[马赛克在x轴起始点,马赛克在y轴起始点,马赛克宽,马赛克高]

  • is_expand : int

是否扩列。值为0时表示不扩列, 值为1时表示在原马赛克周围扩列一个宏块(8个像素)。

返回值说明:

  • ret: int

成功后返回0

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg1 = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    ret = bmcv.mosaic(2, BMimg1, [[10,10,100,2000],[500,500,1000,100]], 1)

5.8.40. gaussian_blur

该接口用于对图像进行高斯滤波。 注意:旧版本SDK并不支持BM1684X,当前SDK是否支持请查询《BMCV开发参考手册》, BMCV API页面查看。

接口形式:
def gaussian_blur(self, input: BMImage, kw: int, kh : int, sigmaX : float, sigmaY : float = 0.0) -> BMImage:

参数说明:

  • input : sail.BMImage

待转换的图像。

  • kw : int

kernel 在width方向上的大小。

  • kh : int

kernel 在height方向上的大小。

  • sigmaX : float

X方向上的高斯核标准差。

  • sigmaY : float

Y方向上的高斯核标准差。如果为0则表示与X方向上的高斯核标准差相同。默认为0。

返回值说明:

  • output : sail.BMImage

返回经过高斯滤波的图像。

示例代码:
import sophon.sail as sail
if __name__ == '__main__':
    handle = sail.Handle(0)
    bmcv = sail.Bmcv(handle)


    bmimg = sail.BMImage()
    decoder = sail.Decoder("your_img.jpg",True,0)
    bmimg = decoder.read(handle)

    print(bmimg.format())
    output = bmcv.gaussian_blur(bmimg, 3, 3, 0.1)

    bmcv.imwrite("out.jpg",output)

5.8.41. transpose

该接口可以实现图片宽和高的转置。

接口形式1:
def transpose(self, src: sail.BMImage) -> sail.BMImage:

参数说明1:

  • src : sail.BMImage

待转换的图像。

返回值说明1:

  • output: sail.BMImage:

返回转换后的图像。

接口形式2:
def transpose(self, src: sail.BMImage, dst: sail.BMImage) -> int:

参数说明2:

  • src : sail.BMImage

待转换的图像。

  • dst : sail.BMImage

输出图像的 sail.BMImage 结构体。

返回值说明2:

  • ret : int

成功返回0,否则返回非0值。

示例代码:
import sophon.sail as sail
if __name__ == '__main__':

    handle = sail.Handle(0)
    bmcv = sail.Bmcv(handle)
    bmimg = sail.BMImage()
    decoder = sail.Decoder("your_img.jpg",True,0)
    bmimg = decoder.read(handle)
    img = bmcv.convert_format(bmimg,sail.Format.FORMAT_GRAY)
    print("readed")
    print(img.format())
    output = bmcv.transpose(img)

    bmcv.imwrite("out.jpg",output)

5.8.42. Sobel

边缘检测Sobel算子。

注意:请查询《BMCV开发参考手册/BMCV API》确认当前算子是否适配BM1684X、BM1688。

接口形式1:
def Sobel(self, input: BMImage, output: BMImage, dx: int, dy: int, ksize: int = 3, scale: float = 1, delta: float = 0) -> int:

参数说明1:

  • input : sail.BMImage

待转换的图像。

  • output : sail.BMImage

转换后的图像。

  • dx : int

x方向上的差分阶数。

  • dy : int

y方向上的差分阶数。

  • ksize : int

Sobel核的大小,必须是-1,1,3,5或7。其中特殊的,如果是-1则使用3×3 Scharr滤波器,如果是1则使用3×1或者1×3的核。默认值为3。

  • scale : float

对求出的差分结果乘以该系数,默认值为1。

  • delta : float

在输出最终结果之前加上该偏移量,默认值为0。

返回值说明1:

  • ret: int

成功后返回0

接口形式2:
def Sobel(self, input: BMImage, dx: int, dy: int, ksize: int = 3, scale: float = 1, delta: float = 0) -> BMImage:

参数说明2:

  • input : sail.BMImage

待转换的图像。

  • dx : int

x方向上的差分阶数。

  • dy : int

y方向上的差分阶数。

  • ksize : int

Sobel核的大小,必须是-1,1,3,5或7。其中特殊的,如果是-1则使用3×3 Scharr滤波器,如果是1则使用3×1或者1×3的核。默认值为3。

  • scale : float

对求出的差分结果乘以该系数,默认值为1。

  • delta : float

在输出最终结果之前加上该偏移量,默认值为0。

返回值说明2:

  • output: sail.BMImage

返回转换后的图像。

示例代码:
import sophon.sail as sail
if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    bmcv = sail.Bmcv(handle)
    bmimg = sail.BMImage()
    decoder = sail.Decoder("your_img.jpg",True,tpu_id)
    bmimg = decoder.read(handle)

    print(bmimg.format())
    output = bmcv.Sobel(bmimg, 1, 1)
    bmcv.imwrite("out.jpg",output)

5.8.43. drawLines

在给定的图像上绘制多条线段。

注意:请查询《BMCV开发参考手册/BMCV API》确认当前算子是否适配BM1684X。

接口形式:
def drawLines(self, image: BMImage, start_points: list[tuple[int, int]], end_points: list[tuple[int, int]], line_num: int, color: tuple[int, int, int], thickness: int) -> int:

参数说明:

  • img : sail.BMImage

输入图片。

  • start_points : list[tuple[int, int]]

线段的起始点坐标列表,图像左上角为原点,向右为x方向,向下为y方向。

  • end_points : list[tuple[int, int]]

线段的结束点坐标列表,必须与起始点列表长度相同。

  • line_num : int

线段的数量,必须和线段起、终点列表长度值相同

  • color : tuple[int, int, int]

线段的颜色,RGB格式。

  • thickness : int

线段的宽度。

返回值说明:

  • ret: int

成功后返回0。

示例代码:
import sophon.sail as sail

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    image_name = "your_image_path"
    decoder = sail.Decoder(image_name,True,tpu_id)
    BMimg1 = decoder.read(handle)# here is a sail.BMImage
    bmcv = sail.Bmcv(handle)
    start_points = [(10, 10), (30, 30)]
    end_points = [(20, 20), (40, 40)]
    line_num = 2
    color = (255, 0, 0)
    thickness = 2
    bm = bmcv.vpp_convert_format(BMimg1,sail.FORMAT_YUV444P)
    ret = bmcv.drawLines(bm, start_points, end_points, line_num,color, thickness)

5.8.44. stft

实现对信号的短时傅里叶变换(STFT)。

注意:请查询《BMCV开发参考手册/BMCV API》确认当前算子是否适配BM1684X。

接口形式:
stft(self, input_real: numpy.ndarray, input_imag: numpy.ndarray, real_input: bool, normalize: bool, n_fft: int, hop_len: int,
        pad_mode: int, win_mode: int) -> tuple[numpy.ndarray, numpy.ndarray]

stft(self, input_real: Tensor, input_imag: Tensor, real_input: bool, normalize: bool, n_fft: int, hop_len: int,
        pad_mode: int, win_mode: int) -> tuple[Tensor, Tensor]

参数说明:

  • input_real: numpy.ndarray 或者 Tensor

    输入信号的实数部分。

  • input_imag: numpy.ndarray 或者 Tensor

    输入信号的虚数部分。

  • real_input: bool

    是否仅使用实数输入的标志。

  • normalize: bool

    是否对输出进行归一化的标志。

  • n_fft: int

    STFT计算中使用的FFT点数。

  • hop_len: int

    窗口滑动的步长。

  • pad_mode: int

    输入信号的填充模式,0表示CONSTANT填充,1表示REFLECT填充。

  • win_mode: int

    窗口函数的类型,0表示HANN窗,1表示HAMM窗。

返回值说明:

  • result: tuple[numpy.ndarray, numpy.ndarray] 或者 tuple[Tensor, Tensor]

    返回输出的实数部分和虚数部分。

示例代码:
import sophon.sail as sail
import numpy as np

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    random_array1 = np.random.rand(2, 4096).astype('float32')
    random_array2 = np.random.rand(2, 4096).astype('float32')
    bmcv = sail.Bmcv(handle)
    input_real = sail.Tensor(handle, random_array1, True)
    input_imag = sail.Tensor(handle, random_array2, True)
    real_input = False
    normalize = True
    n_fft = 1024
    hop_len = 256
    pad_mode = 0  # 填充模式示例
    win_mode = 1  # 窗口类型示例
    stft_R, stft_I = bmcv.stft(input_real, input_imag, real_input, normalize, n_fft, hop_len, pad_mode, win_mode)

5.8.45. istft

实现对信号的逆短时傅里叶变换(ISTFT)。

注意:请查询《BMCV开发参考手册/BMCV API》确认当前算子是否适配BM1684X。

接口形式:
istft(self, input_real: numpy.ndarray, input_imag: numpy.ndarray, real_input: bool, normalize: bool, L: int, hop_len: int,
    pad_mode: int, win_mode: int) -> tuple[numpy.ndarray, numpy.ndarray]:

istft(self, input_real: Tensor, input_imag: Tensor, real_input: bool, normalize: bool, L: int, hop_len: int,
    pad_mode: int, win_mode: int) -> tuple[Tensor, Tensor]:

参数说明:

  • input_real: numpy.ndarray 或者 Tensor

    输入信号的实数部分。

  • input_imag: numpy.ndarray 或者 Tensor

    输入信号的虚数部分。

  • real_input: bool

    输出的信号是否为实数, false 为复数, true 为实数。

  • normalize: bool

    是否对输出进行归一化。

  • L: int

    原始时域信号的长度。

  • hop_len: int

    窗口滑动的步长,必须与STFT计算时使用的值相同。

  • pad_mode: int

    输入信号的填充模式,必须与STFT计算时使用的值相同。

  • win_mode: int

    窗口函数的类型,必须与STFT计算时使用的值相同。

返回值说明:

  • result: tuple[numpy.ndarray, numpy.ndarray] 或者 tuple[Tensor, Tensor]

    返回输出的实数部分和虚数部分。

示例代码:
import sophon.sail as sail
import numpy as np

if __name__ == '__main__':
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    random_array1 = np.random.rand(2, 513, 17).astype('float32')
    random_array2 = np.random.rand(2, 513, 17).astype('float32')
    bmcv = sail.Bmcv(handle)
    input_real = sail.Tensor(handle, random_array1, True)
    input_imag = sail.Tensor(handle, random_array2, True)
    real_input = False
    normalize = True
    L = 4096
    hop_len = 256
    pad_mode = 0  # 填充模式示例
    win_mode = 1  # 窗口类型示例
    istft_R, istft_I = bmcv.istft(input_real, input_imag, real_input, normalize, 4096, hop_len, pad_mode, win_mode)

5.8.46. bmcv_overlay

图片上添加带透明通道的水印图。仅支持BM1688和CV186AH。

接口形式:
def bmcv_overlay(self, image: BMImage, overlay_info: list[list[int]], overlay_image: list[BMImage]) -> int:

参数说明:

  • image : sail.BMImage

输入/输出图片。

  • overlay_info: list[list[int]]

一组水印图的位置大小信息,格式是[x,y,w,h]

  • overlay_image: list[BMImage]

一组水印图,目前仅支持sail.Format.FORMAT_ARGB_PACKED格式

返回值说明:

  • ret: int

成功后返回0。

注:

需要自行确保overlay_info中的所有矩形位置不重叠

示例代码1:

直接读入RGBA图片作为水印

import sophon.sail as sail
import cv2

if __name__ == '__main__':

    handle = sail.Handle(0)

    decoder = sail.Decoder("pics/1.jpg")
    image_org = decoder.read(handle)

    bmcv = sail.Bmcv(handle)

    buffer = cv2.imread("pics/icon.png", cv2.IMREAD_UNCHANGED)
    buffer_x = 100
    buffer_y = 50
    buffer_w = 100
    buffer_h = 30

    buffer_x1 = 500
    buffer_y1 = 200
    buffer_w1 = 60
    buffer_h1 = 70

    buffer = cv2.resize(buffer, (buffer_w, buffer_h))
    buffer1 = cv2.resize(buffer, (buffer_w1, buffer_h1))

    overlay_images = []
    overlay_info = []
    overlay_images.append(sail.BMImage(handle, buffer, buffer_h, buffer_w, sail.Format.FORMAT_ARGB_PACKED, sail.ImgDtype.DATA_TYPE_EXT_1N_BYTE))
    overlay_info.append([buffer_x,buffer_y,buffer_w, buffer_h])
    overlay_images.append(sail.BMImage(handle, buffer1, buffer_h1, buffer_w1, sail.Format.FORMAT_ARGB_PACKED, sail.ImgDtype.DATA_TYPE_EXT_1N_BYTE))
    overlay_info.append([buffer_x1,buffer_y1,buffer_w1, buffer_h1])

    ret = bmcv.bmcv_overlay(image_org, overlay_info, overlay_images)

    ret = bmcv.imwrite("overlayed.jpg", image_org)

示例代码2:

用其他库生成中文字的水印图,用overlay画在指定位置,间接实现puttext功能

import sophon.sail as sail
from PIL import Image, ImageDraw, ImageFont

if __name__ == '__main__':
    # 获取原图
    handle = sail.Handle(0)
    bmcv = sail.Bmcv(handle)
    decoder = sail.Decoder("pics/1.jpg")
    org_image = decoder.read(handle)

    # 字体基本信息
    watermark_w, watermark_h = 60, 30
    text = ["人", "车", "狗"]
    text_color = (255, 0, 0, 255)
    font = ImageFont.truetype("fonts/simhei.ttf", watermark_h, encoding="utf-8")

    # 生成标签水印图
    overlay_images = []
    for i in range(len(text)):
        blank_image = Image.new('RGBA', (watermark_w, watermark_h), (255,255,255,0))
        draw = ImageDraw.Draw(blank_image)
        draw.text((0,0), text[i], fill=text_color, font=font)
        # blank_image.save("watermark.png")
        buffer = blank_image.tobytes()
        overlay_images.append(sail.BMImage(handle, buffer, watermark_h, watermark_w, sail.Format.FORMAT_ARGB_PACKED, sail.ImgDtype.DATA_TYPE_EXT_1N_BYTE))

    # 经过推理等其他过程
    # 模拟获得的水印图位置
    overlay_info = []
    for i in range(len(text)):
        x = int(i*org_image.width()/len(text))
        y = int(org_image.height()/2)
        overlay_info.append([x, y, watermark_w, watermark_h])

    ret = bmcv.bmcv_overlay(org_image, overlay_info, overlay_images)
    ret = bmcv.imwrite("overlayed.jpg", org_image)

5.8.47. faiss_indexflatL2

计算查询向量与数据库向量 L2 距离的平方, 输出前 topK 个最匹配的 L2 距离的平方值及其对应的索引。

接口形式:
faiss_indexflatL2(self, query_vecs: numpy.ndarray, query_vecs_L2norm: numpy.ndarray, database_vecs: numpy.ndarray, database_vecs_L2norm: numpy.ndarray,
                vec_dims: int, query_vecs_nums: int, database_vecs_nums: int, topK: int) -> tuple[numpy.ndarray, numpy.ndarray]:

faiss_indexflatL2(self, query_vecs: numpy.ndarray, query_vecs_L2norm: numpy.ndarray, database_vecs: Tensor, database_vecs_L2norm: Tensor,
                vec_dims: int, query_vecs_nums: int, database_vecs_nums: int, topK: int) -> tuple[numpy.ndarray, numpy.ndarray]:

参数说明:

  • query_vecs: numpy.ndarray

    查询向量, 数据类型仅支持numpy.float32。

  • query_vecs_L2norm: numpy.ndarray

    计算查询向量每行各元素平方值的和, numpy.float32。

  • database_vecs: numpy.ndarray 或者 Tensor

    数据库向量, 数据类型仅支持numpy.float32或者sail.Dtype.BM_FLOAT32。

  • database_vecs_L2norm: numpy.ndarray 或者 Tensor

    计算数据库向量每行各元素平方值的和, numpy.float32 或者sail.Dtype.BM_FLOAT32。

  • vec_dims: int

    查询向量和数据库向量的维度。

  • query_vecs_nums: int

    查询向量的个数。

  • database_vecs_nums: int

    数据库向量的个数。

  • topK: int

    输出前 topK 个最匹配的 L2 距离的平方值及其对应的索引。

返回值说明:

  • result: tuple[numpy.ndarray, numpy.ndarray]

    返回前 topK 个最匹配的 L2 距离的平方值及其对应的索引。

示例代码1:
import numpy as np
import sophon.sail as sail
import time

if __name__ == '__main__':
    # 1. database_vecs
    db_vecs = np.array([
        [-2.0, 0.0, 4.0],
        [-5.0, 3.0, -1.0],
        [1.0, 2.0, 4.0],
        [0.0, 5.0, -3.0],
        [2.0, 1.0, -4.0],
    ], dtype=np.float32)

    # 2. query_vecs
    query_vecs = np.array([
        [1.0, 2.0, 3.0]
    ], dtype=np.float16)

    # 3. test bmcv.faiss_indexflatL2
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    bmcv = sail.Bmcv(handle)

    db_vecs_square = np.square(db_vecs)
    db_vecs_l2norm = np.sum(db_vecs_square, axis=1)
    print("db_vecs_l2norm:", db_vecs_l2norm)

    query_vecs_square = np.square(query_vecs)
    query_vecs_l2norm = np.sum(query_vecs_square, axis=1)
    print("query_vecs_l2norm:", query_vecs_l2norm)

    start = time.time()
    similarity_L2, index_L2 = bmcv.faiss_indexflatL2(query_vecs, query_vecs_l2norm, db_vecs, db_vecs_l2norm, 3, 1, 5, 3)
    end = time.time()
    execution_time_milliseconds_L2 = (end - start) * 1000
    print(f"Execution time: {execution_time_milliseconds_L2:.6f} milliseconds")
    print("similarity_L2:", similarity_L2)
    print("index_L2:", index_L2)
示例代码2:
import numpy as np
import sophon.sail as sail
import time

if __name__ == '__main__':
    # 1. database_vecs
    db_vecs = np.array([
        [-2.0, 0.0, 4.0],
        [-5.0, 3.0, -1.0],
        [1.0, 2.0, 4.0],
        [0.0, 5.0, -3.0],
        [2.0, 1.0, -4.0],
    ], dtype=np.float32)

    # 2. query_vecs
    query_vecs = np.array([
        [1.0, 2.0, 3.0]
    ], dtype=np.float16)

    # 3. test bmcv.faiss_indexflatL2
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    bmcv = sail.Bmcv(handle)

    db_vecs_square = np.square(db_vecs)
    db_vecs_l2norm = np.sum(db_vecs_square, axis=1)
    print("db_vecs_l2norm:", db_vecs_l2norm)

    query_vecs_square = np.square(query_vecs)
    query_vecs_l2norm = np.sum(query_vecs_square, axis=1)
    print("query_vecs_l2norm:", query_vecs_l2norm)

    # 4. database_vecs and db_vecs_l2norm to sail::Tensor
    db_tensor = sail.Tensor(handle, db_vecs, False)
    db_tensor_l2norm = sail.Tensor(handle, db_vecs_l2norm, False)

    start = time.time()
    similarity_L2, index_L2 = bmcv.faiss_indexflatL2(query_vecs, query_vecs_l2norm, db_tensor, db_tensor_l2norm, 3, 1, 5, 3)
    end = time.time()
    execution_time_milliseconds_L2 = (end - start) * 1000
    print(f"Execution time: {execution_time_milliseconds_L2:.6f} milliseconds")
    print("similarity_L2:", similarity_L2)
    print("index_L2:", index_L2)

5.8.48. faiss_indexflatIP

计算查询向量与数据库向量的内积距离, 输出前 topK 个最匹配的内积距离值及其对应的索引。

接口形式:
faiss_indexflatIP(self, query_vecs: numpy.ndarray, database_vecs: numpy.ndarray,
                vec_dims: int, query_vecs_nums: int, database_vecs_nums: int, topK: int) -> tuple[numpy.ndarray, numpy.ndarray]:

faiss_indexflatIP(self, query_vecs: numpy.ndarray, database_vecs: Tensor,
                vec_dims: int, query_vecs_nums: int, database_vecs_nums: int, topK: int) -> tuple[numpy.ndarray, numpy.ndarray]:

参数说明:

  • query_vecs: numpy.ndarray

    查询向量, 数据类型仅支持numpy.float32。

  • database_vecs: numpy.ndarray 或者 Tensor

    数据库向量, 数据类型仅支持numpy.float32或者sail.Dtype.BM_FLOAT32。

  • vec_dims: int

    查询向量和数据库向量的维度。

  • query_vecs_nums: int

    查询向量的个数。

  • database_vecs_nums: int

    数据库向量的个数。

  • topK: int

    输出前 topK 个最匹配的内积距离值及其对应的索引。

返回值说明:

  • result: tuple[numpy.ndarray, numpy.ndarray]

    输出前 topK 个最匹配的内积距离值及其对应的索引。

示例代码:
import numpy as np
import sophon.sail as sail
import time

if __name__ == '__main__':
    # 1. database_vecs
    db_vecs = np.array([
        [-2.0, 0.0, 4.0],
        [-5.0, 3.0, -1.0],
        [1.0, 2.0, 4.0],
        [0.0, 5.0, -3.0],
        [2.0, 1.0, -4.0],
    ], dtype=np.float32)

    # 2. query_vecs
    query_vecs = np.array([
        [1.0, 2.0, 3.0]
    ], dtype=np.float16)

    # 3. test bmcv.faiss_indexflatIP
    tpu_id = 0
    handle = sail.Handle(tpu_id)
    bmcv = sail.Bmcv(handle)

    db_tensor = sail.Tensor(handle, db_vecs, False)
    start = time.time()
    similarity_IP, index_IP = bmcv.faiss_indexflatIP(query_vecs, db_tensor, 3, 1, 5, 3)
    # similarity_IP, index_IP = bmcv.faiss_indexflatIP(query_vecs, db_vecs, 3, 1, 5, 3)
    end = time.time()
    execution_time_milliseconds_L2 = (end - start) * 1000
    print(f"Execution time: {execution_time_milliseconds_L2:.6f} milliseconds")
    print("similarity_IP:", similarity_IP)
    print("index_IP:", index_IP)

5.8.49. faiss_indexPQ_encode

对输入向量进行PQ量化编码, 输出编码之后的向量。

接口形式:
faiss_indexPQ_encode(self, input_vecs: Tensor, centroids_vecs: Tensor,
                encode_vecs_num: int, vec_dims: int, slice_num: int, centroids_num: int, IP_metric: int) -> Tensor:

faiss_indexPQ_encode(self, input_vecs: numpy.ndarray, centroids_vecs: numpy.ndarray,
                encode_vecs_num: int, vec_dims: int, slice_num: int, centroids_num: int, IP_metric: int) -> numpy.ndarray:

faiss_indexPQ_encode(self, input_vecs: numpy.ndarray, centroids_vecs: Tensor, encoded_vecs: Tensor
                encode_vecs_num: int, vec_dims: int, slice_num: int, centroids_num: int, IP_metric: int) -> int:

参数说明:

  • input_vecs: numpy.ndarray or Tensor

    输入的待编码向量, 数据类型仅支持numpy.float32或者sail.Dtype.BM_FLOAT32, 大小为encode_vecs_num * vec_dims。

  • centroids_vecs: numpy.ndarray 或者 Tensor

    聚类中心 (质心) 向量, 数据类型仅支持numpy.float32或者sail.Dtype.BM_FLOAT32, 大小为slice_num * centroids_num * (vec_dims / slice_num)。

  • encode_vecs_num: int

    待编码向量的个数。

  • vec_dims: int

    待编码向量的维度。

  • slice_num: int

    原始向量维度的切分数量, 例如原始向量维度为512, slice_num = 8, 每个子向量维度为64。

  • centroids_num: int

    聚类中心的数量。

  • IP_metric: int

    0 表示使用L2计算距离, 1 表示使用IP计算距离。

返回值说明:

  • result: numpy.ndarray 或者 Tensor

    输出编码之后的向量, numpy.ndarray (uint8) 或者 Tensor (BM_UINT8)。

示例代码:
import faiss
import numpy as np
import sophon.sail as sail

encode_vecs_num = 3
vec_dims = 64
db_vecs_num = 10000
slice_num = 8
centroids_num = 256
nbits = 8

np.random.seed(666)
data = np.random.rand(db_vecs_num, vec_dims).astype('float32')
pq = faiss.ProductQuantizer(vec_dims, slice_num, nbits)
pq.train(data)

# get centroids
centroids = faiss.vector_float_to_array(pq.centroids)
print('centroids.shape: ', centroids.shape)
np.save('pq_centroids_random.npy', centroids)

# faiss PQ encode
input_vector = np.random.rand(encode_vecs_num, vec_dims).astype('float32')
faiss_PQ_encode = pq.compute_codes(input_vector)
print('faiss_PQ_encode:\n', faiss_PQ_encode)
print('faiss_PQ_encode shape:', faiss_PQ_encode.shape)

# test sail bmcv.faiss_indexPQ_encode
handle = sail.Handle(0)
bmcv = sail.Bmcv(handle)

centroids_vecs = np.load("pq_centroids_random.npy").astype(np.float32)
print("centroids_vecs shape:", centroids_vecs.shape)
print("centroids_vecs dtype:", type(centroids_vecs))

input_tensor = sail.Tensor(handle, input_vector, False)
centroids_tensor = sail.Tensor(handle, centroids_vecs, False)

encode_tensor = bmcv.faiss_indexPQ_encode(input_tensor, centroids_tensor, encode_vecs_num, vec_dims, slice_num, centroids_num, 0)
print('bmcv_faiss_indexPQ_encode:\n', encode_tensor.asnumpy())

encode = bmcv.faiss_indexPQ_encode(input_vector, centroids_vecs, encode_vecs_num, vec_dims, slice_num, centroids_num, 0)
print('bmcv_faiss_indexPQ_encode:\n', encode)

5.8.50. faiss_indexPQ_ADC

通过查询向量和聚类中心 (质心) 向量计算出距离表, 编码的数据库向量查表计算距离并排序, 输出前 topK 个最匹配的距离值及其对应的索引。

接口形式:
faiss_indexPQ_ADC(self, nxquery_vecs: numpy.ndarray, centroids_vecs: numpy.ndarray, nycodes_vecs: numpy.ndarray,
                vec_dims: int, slice_num: int, centroids_num: int, database_vecs_num: int, query_vecs_num: int, topK: int, IP_metric: int) -> tuple[numpy.ndarray, numpy.ndarray]:

faiss_indexPQ_ADC(self, nxquery_vecs: numpy.ndarray, centroids_vecs: Tensor, nycodes_vecs: Tensor,
                vec_dims: int, slice_num: int, centroids_num: int, database_vecs_num: int, query_vecs_num: int, topK: int, IP_metric: int) -> tuple[numpy.ndarray, numpy.ndarray]:

参数说明:

  • nxquery_vecs: numpy.ndarray

    查询向量, 数据类型仅支持numpy.float32, 大小为query_vecs_nums * vec_dims。

  • centroids_vecs: numpy.ndarray 或者 Tensor

    聚类中心 (质心) 向量, 数据类型仅支持numpy.float32 或者sail.Dtype.BM_FLOAT32, 大小为slice_num * centroids_num * (vec_dims / slice_num)。

  • nycodes_vecs: numpy.ndarray 或者 Tensor

    编码的数据库向量, 数据类型仅支持numpy.uint8 或者sail.Dtype.BM_UINT8, 大小为database_vecs_nums * slice_num。

  • vec_dims: int

    查询向量的维度。

  • slice_num: int

    原始向量维度的切分数量, 例如原始向量维度为512, slice_num = 8, 每个子向量维度为64。

  • centroids_num: int

    聚类中心 (质心) 向量的个数。

  • database_vecs_nums: int

    数据库向量的个数。

  • query_vecs_nums: int

    查询向量的个数。

  • topK: int

    输出前 topK 个最匹配的距离值及其对应的索引。

  • IP_metric: int

    0 表示使用L2计算距离, 1 表示使用IP计算距离。

返回值说明:

  • result: tuple[numpy.ndarray, numpy.ndarray]

    输出前 topK 个最匹配的距离值及其对应的索引。

示例代码:
import numpy as np
import faiss
import sophon.sail as sail

np.random.seed(1024)
vec_dims = 512
database_vecs_num = 10000
query_vecs_num = 1

nydb_vecs = np.random.rand(database_vecs_num, vec_dims).astype('float32')
nxquery_vecs = np.random.rand(query_vecs_num, vec_dims).astype('float32')

slice_num = 8
n_bits = 8
index = faiss.IndexPQ(vec_dims, slice_num, n_bits)
index.train(nydb_vecs)
index.add(nydb_vecs)

# save centroids
centroids_faiss = index.pq.centroids
centroids = faiss.vector_float_to_array(centroids_faiss)
print('centroids.shape: ', centroids.shape)
np.save('centroids_random.npy', centroids)

# Compute PQ codes for the database vectors and save
db_codes = index.pq.compute_codes(nydb_vecs)
print('db_codes.shape:', db_codes.shape)
np.save('db_codes.npy', db_codes)

# faiss
D, I = index.search(nxquery_vecs, k=5)
print("The index of faiss:\n", I)
print("The distance of faiss:\n", D)

# test faiss_indexPQ_ADC of sail
handle = sail.Handle(0)
bmcv = sail.Bmcv(handle)

# get centroids
centroids_vecs = np.load("centroids_random.npy").astype(np.float32)
print("centroids_vecs shape:", centroids_vecs.shape)
print("centroids_vecs dtype:", type(centroids_vecs))
# get PQ codes for the database vectors
nycodes_vecs = np.load("db_codes.npy")
print("nycodes_vecs shape:", nycodes_vecs.shape)
print("nycodes_vecs dtype:", type(nycodes_vecs))

# to tensor
centroids_tensor = sail.Tensor(handle, centroids_vecs, False)
nycode_tensor = sail.Tensor(handle, nycodes_vecs, False)

# D_, I_ = bmcv.faiss_indexPQ_ADC(nxquery_vecs, centroids_tensor, nycode_tensor, vec_dims, slice_num, 256, database_vecs_num, query_vecs_num, 5, 0)
D_, I_ = bmcv.faiss_indexPQ_ADC(nxquery_vecs, centroids_vecs, nycodes_vecs, vec_dims, slice_num, 256, database_vecs_num, query_vecs_num, 5, 0)
print("The index of sail:\n", I_)
print("The distance of sail:\n", D_)

5.8.51. faiss_indexPQ_SDC

使用SDC (Symmetric Distance Computation, 对称距离计算)查找表加速 PQ 编码之间的距离计算, 输出与查询向量前 topK 个最匹配的距离值及其对应的索引。

接口形式:
faiss_indexPQ_SDC(self, nxcodes_vecs: numpy.ndarray, nycodes_vecs: numpy.ndarray, sdc_table: numpy.ndarray,
                slice_num: int, centroids_num: int, database_vecs_num: int, query_vecs_num: int, topK: int, IP_metric: int) -> tuple[numpy.ndarray, numpy.ndarray]:

faiss_indexPQ_SDC(self, nxcodes_vecs: numpy.ndarray, nycodes_vecs: Tensor, sdc_table: Tensor,
                slice_num: int, centroids_num: int, database_vecs_num: int, query_vecs_num: int, topK: int, IP_metric: int) -> tuple[numpy.ndarray, numpy.ndarray]:

参数说明:

  • nxcodes_vecs: numpy.ndarray

    编码的查询向量, 数据类型仅支持numpy.uint8, 大小为query_vecs_nums * slice_num。

  • nycodes_vecs: numpy.ndarray 或者 Tensor

    编码的数据库向量, 数据类型仅支持numpy.uint8 或者sail.Dtype.BM_UINT8, 大小为database_vecs_nums * slice_num。

  • sdc_table: numpy.ndarray 或者 Tensor

    sdc对称距离表, 数据类型仅支持numpy.float32 或者sail.Dtype.BM_FLOAT32, 大小为slice_num * centroids_num * centroids_num。

  • slice_num: int

    原始向量维度的切分数量, 例如原始向量维度为512, slice_num = 8, 每个子向量维度为64。

  • centroids_num: int

    聚类中心 (质心) 向量的个数。

  • database_vecs_nums: int

    数据库向量的个数。

  • query_vecs_nums: int

    查询向量的个数。

  • topK: int

    输出前 topK 个最匹配的距离值及其对应的索引。

  • IP_metric: int

    0 表示使用L2计算距离, 1 表示使用IP计算距离。

返回值说明:

  • result: tuple[numpy.ndarray, numpy.ndarray]

    输出前 topK 个最匹配的距离值及其对应的索引。

示例代码:
import numpy as np
import faiss
import sophon.sail as sail

np.random.seed(1024)
vec_dims = 512             # The dimension of the vectors.
database_vecs_num = 10000  # The number of the database vectors.
query_vecs_num = 1         # The number of the query vectors.

# 1. Random database and query
database = np.random.rand(database_vecs_num, vec_dims).astype('float32')
query = np.random.rand(query_vecs_num, vec_dims).astype('float32')

# 2. The parameters of PQ
slice_num = 8       # Divide the vector of the vec_dims dimension into 8 subvectors
n_bits = 8          # centroids = 256 = 2^n_bits

# 3. Create a PQ index
index = faiss.IndexPQ(vec_dims, slice_num, n_bits)
index.train(database)  # Train the PQ index
index.add(database)

# 4. Set to SDC (Symmetric Distance Calculation)
index.search_type = faiss.IndexPQ.ST_SDC

# 5. Calculate sdc_table and save it
index.pq.compute_sdc_table()

sdc_table = faiss.vector_float_to_array(index.pq.sdc_table)
print('sdc_table shape:', sdc_table.shape)
np.save('sdc_table.npy', sdc_table)

# 6. Query operations using faiss
topK = 5
D, I = index.search(query, topK)
print("The index of faiss:\n", I)
print("The distance of faiss:\n", D)

# Calculate and save the PQ encoding of the database vector (for sail test)
db_codes = index.pq.compute_codes(database)
print('db_codes.shape:', db_codes.shape)
np.save('db_codes.npy', db_codes)

# Calculate and save the PQ encoding of the query vectors (for sail test)
query_code = index.pq.compute_codes(query)
print('query_code.shape:', query_code.shape)
np.save('query_code.npy', query_code)
print("________________________________________________________________________________")

# test faiss_indexPQ_SDC
handle = sail.Handle(0)
bmcv = sail.Bmcv(handle)

# 1. get PQ codes of the database vectors
nycodes_vecs = np.load("db_codes.npy")
print("nycodes_vecs shape:", nycodes_vecs.shape)
print("nycodes_vecs dtype:", nycodes_vecs.dtype)

# 2. get PQ codes of the query vectors
nxcodes_vecs = np.load('query_code.npy')
print("nxcodes_vecs shape:", nxcodes_vecs.shape)
print("nxcodes_vecs dtype:", nxcodes_vecs.dtype)

# 3. get the SDC table
SDC_tables = np.load('sdc_table.npy')

D_, I_ = bmcv.faiss_indexPQ_SDC(nxcodes_vecs, nycodes_vecs, SDC_tables, slice_num, 256, database_vecs_num, query_vecs_num, topK, 0)
print("The index of sail:\n", I_)
print("The distance of sail:\n", D_)