代码地址:https://github.com/obss/sahi
slice_image是sahi库中一个函数,理解这个函数是理解切片的入口。
一、官方函数使用示例
from sahi.slicing import slice_image
image_path=r'small-vehicles1.jpeg'
output_dir=r'ashi_result'
output_file_name='1-'
#手动设置slice_height,slice_width,overlap_height_ratio,overlap_width_ratio
def set_cfg():
slice_image_result = slice_image(
image=image_path,
output_file_name=output_file_name,
output_dir=output_dir,
slice_height=256,
slice_width=256,
overlap_height_ratio=0.2,
overlap_width_ratio=0.2,
)
#根据图片自动计算slice_height,slice_width,overlap_height_ratio,overlap_width_ratio
def auto_cfg():
slice_image_result = slice_image(
image=image_path,
output_file_name=output_file_name,
output_dir=output_dir
)
# set_cfg()
auto_cfg()
原图:
自动切片图:
二、slice_image函数梳理
slice_image位于slicing.py中,在此,仅对于图片进行分析,标注coco格式切片后续有时间另说。
slice_image中最重要的是get_slice_bboxes和get_auto_slice_params
1、get_slice_bboxes函数
def get_slice_bboxes(
image_height: int,
image_width: int,
slice_height: Optional[int] = None,
slice_width: Optional[int] = None,
auto_slice_resolution: bool = True,
overlap_height_ratio: float = 0.2,
overlap_width_ratio: float = 0.2,
) -> List[List[int]]:
"""Slices `image_pil` in crops.
Corner values of each slice will be generated using the `slice_height`,
`slice_width`, `overlap_height_ratio` and `overlap_width_ratio` arguments.
Args:
image_height (int): Height of the original image.
image_width (int): Width of the original image.
slice_height (int, optional): Height of each slice. Default None.
slice_width (int, optional): Width of each slice. Default None.
overlap_height_ratio(float): Fractional overlap in height of each
slice (e.g. an overlap of 0.2 for a slice of size 100 yields an
overlap of 20 pixels). Default 0.2.
overlap_width_ratio(float): Fractional overlap in width of each
slice (e.g. an overlap of 0.2 for a slice of size 100 yields an
overlap of 20 pixels). Default 0.2.
auto_slice_resolution (bool): if not set slice parameters such as slice_height and slice_width,
it enables automatically calculate these params from image resolution and orientation.
Returns:
List[List[int]]: List of 4 corner coordinates for each N slices.
[
[slice_0_left, slice_0_top, slice_0_right, slice_0_bottom],
...
[slice_N_left, slice_N_top, slice_N_right, slice_N_bottom]
]
"""
slice_bboxes = []
y_max = y_min = 0
# 手动设置切片宽高
if slice_height and slice_width:
y_overlap = int(overlap_height_ratio * slice_height)
x_overlap = int(overlap_width_ratio * slice_width)
# 自动设置切片宽高
elif auto_slice_resolution:
x_overlap, y_overlap, slice_width, slice_height = get_auto_slice_params(height=image_height, width=image_width)
else:
raise ValueError("Compute type is not auto and slice width and height are not provided.")
while y_max < image_height:
x_min = x_max = 0
y_max = y_min + slice_height
while x_max < image_width:
x_max = x_min + slice_width
#处理越界
if y_max > image_height or x_max > image_width:
xmax = min(image_width, x_max)
ymax = min(image_height, y_max)
xmin = max(0, xmax - slice_width)
ymin = max(0, ymax - slice_height)
slice_bboxes.append([xmin, ymin, xmax, ymax])
else:#正常
slice_bboxes.append([x_min, y_min, x_max, y_max])
x_min = x_max - x_overlap
y_min = y_max - y_overlap
return slice_bboxes
2、get_auto_slice_params
def get_auto_slice_params(height: int, width: int) -> Tuple[int, int, int, int]:
"""
According to Image HxW calculate overlap sliding window and buffer params
factor is the power value of 2 closest to the image resolution.
factor <= 18: low resolution image such as 300x300, 640x640
18 < factor <= 21: medium resolution image such as 1024x1024, 1336x960
21 < factor <= 24: high resolution image such as 2048x2048, 2048x4096, 4096x4096
factor > 24: ultra-high resolution image such as 6380x6380, 4096x8192
Args:
height:
width:
Returns:
slicing overlap params x_overlap, y_overlap, slice_width, slice_height
"""
resolution = height * width #图幅面积
factor = calc_resolution_factor(resolution) #2的次幂
if factor <= 18:
return get_resolution_selector("low", height=height, width=width)
elif 18 <= factor < 21:
return get_resolution_selector("medium", height=height, width=width)
elif 21 <= factor < 24:
return get_resolution_selector("high", height=height, width=width)
else:
return get_resolution_selector("ultra-high", height=height, width=width)
def get_resolution_selector(res: str, height: int, width: int) -> Tuple[int, int, int, int]:
"""
Args:
res: resolution of image such as low, medium
height:
width:
Returns:
trigger slicing params function and return overlap params
"""
orientation = calc_aspect_ratio_orientation(width=width, height=height) #以长的边为主
x_overlap, y_overlap, slice_width, slice_height = calc_slice_and_overlap_params(
resolution=res, height=height, width=width, orientation=orientation
)
return x_overlap, y_overlap, slice_width, slice_height
def calc_slice_and_overlap_params(
resolution: str, height: int, width: int, orientation: str
) -> Tuple[int, int, int, int]:
"""
This function calculate according to image resolution slice and overlap params.
Args:
resolution: str
height: int
width: int
orientation: str
Returns:
x_overlap, y_overlap, slice_width, slice_height
"""
if resolution == "medium":
split_row, split_col, overlap_height_ratio, overlap_width_ratio = calc_ratio_and_slice(
orientation, slide=1, ratio=0.8
)
elif resolution == "high":
split_row, split_col, overlap_height_ratio, overlap_width_ratio = calc_ratio_and_slice(
orientation, slide=2, ratio=0.4
)
elif resolution == "ultra-high":
split_row, split_col, overlap_height_ratio, overlap_width_ratio = calc_ratio_and_slice(
orientation, slide=4, ratio=0.4
)
else: # low condition
split_col = 1
split_row = 1
overlap_width_ratio = 1
overlap_height_ratio = 1
# split_row为沿着宽方向切片量,split_col为沿着高方向切片量
slice_height = height // split_col
slice_width = width // split_row
x_overlap = int(slice_width * overlap_width_ratio)
y_overlap = int(slice_height * overlap_height_ratio)
return x_overlap, y_overlap, slice_width, slice_height
def calc_ratio_and_slice(orientation, slide=1, ratio=0.1):
"""
According to image resolution calculation overlap params
Args:
orientation: image capture angle
slide: sliding window
ratio: buffer value
Returns:
overlap params
"""
#slice_row为沿着宽方向切片量,slice_col为沿着高方向切片量
if orientation == "vertical": #高长,沿着高方向切片量多些
slice_row, slice_col, overlap_height_ratio, overlap_width_ratio = slide, slide * 2, ratio, ratio
elif orientation == "horizontal":#宽长,沿着宽方向切片量多些
slice_row, slice_col, overlap_height_ratio, overlap_width_ratio = slide * 2, slide, ratio, ratio
elif orientation == "square":#宽高相等
slice_row, slice_col, overlap_height_ratio, overlap_width_ratio = slide, slide, ratio, ratio
return slice_row, slice_col, overlap_height_ratio, overlap_width_ratio # noqa