You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

导出图像轮廓区域时出现SystemError: tile cannot extend outside image求助

图像轮廓区域导出错误的解决方法

问题背景

编写Python代码识别图像轮廓并导出轮廓覆盖的区域时,出现SystemError: tile cannot extend outside image错误,确认导出区域尺寸未超原图像但问题依旧。

错误原因

  1. 数组切片顺序错误:numpy图像数组的维度是(行, 列, 通道),原代码中slices = ar[start_col:end_col][start_row:end_row]先按列切片再按行切片,逻辑完全颠倒,导致截取的区域维度错乱,超出图像范围。
  2. 灰度转换后类型问题:自定义的灰度转换函数返回float类型数组,直接用于PIL保存可能引发格式兼容问题。
  3. deprecated参数警告:measure.find_contours的array参数已被弃用,需改用image。
  4. 文件名重复:循环中所有轮廓都保存为1.png,会覆盖之前的文件,且无法区分不同轮廓区域。

修复方案

  • 修正数组切片顺序,使用ar[start_row:end_row, start_col:end_col]正确截取行和列范围。
  • 将灰度转换后的数组转为uint8类型,或使用skimage.color.rgb2gray更规范地处理灰度转换。
  • 替换find_contours的array参数为image,消除警告。
  • 循环中使用动态文件名(如f"contour_{i}.png")保存每个轮廓区域。
  • 可选:添加边界检查,确保切片范围不超出图像数组的实际维度。

修复后的完整代码

from skimage import filters, measure, color
from matplotlib import pyplot as plt
import numpy as np
import imageio
from PIL import Image

def grayscale(imgData):
    r = imgData[:, :, 0]
    g = imgData[:, :, 1]
    b = imgData[:, :, 2]
    # 转换为uint8类型的灰度图
    return (r * 299. / 1000 + g * 587. / 1000 + b * 114. / 1000).astype(np.uint8)

# 加载图像
loadimg = imageio.imread('cell1.png')
# 灰度转换(也可以直接用color.rgb2gray,返回float类型后续需要转uint8)
# img_gray = color.rgb2gray(loadimg)
img_gray = grayscale(np.asarray(loadimg))
# 高斯模糊
img_blur = filters.gaussian(img_gray, sigma=(3.0, 3.0), truncate=3.5)
# 查找轮廓,使用image参数替代deprecated的array
contours = measure.find_contours(image=img_blur, level=95)

# 遍历每个轮廓并导出区域
for i, contour in enumerate(contours, start=1):
    c = contour.astype(int)
    # 获取轮廓的边界,添加边界检查避免超出图像范围
    start_row = max(0, min(c[:, 0]))
    end_row = min(loadimg.shape[0], max(c[:, 0]))
    start_col = max(0, min(c[:, 1]))
    end_col = min(loadimg.shape[1], max(c[:, 1]))
    
    # 正确截取图像区域:行范围在前,列范围在后
    slice_region = loadimg[start_row:end_row, start_col:end_col]
    
    # 转换为PIL图像并保存
    export = Image.fromarray(slice_region)
    export.save(f"contour_{i}.png")

额外说明

  • 如果使用skimage.color.rgb2gray,注意它返回的是0-1之间的float数组,需要先乘以255再转uint8:img_gray = (color.rgb2gray(loadimg)*255).astype(np.uint8)。
  • 添加max(0, ...)和min(loadimg.shape[0], ...)是为了确保边界不会因轮廓坐标误差超出图像范围,增强代码鲁棒性。

内容的提问来源于stack exchange,提问作者ProfMonkey07

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 15:23:17