Python如何裁剪图片,并且裁剪的图片如何变换原图坐标?
Python如何裁剪图片
并且裁剪的图片如何变换原图坐标
需要滑窗裁剪图片
但是裁剪图片之后
识别的小框 在原图的坐标是怎么样的
比如 原图
1000*1000
裁剪N个小图
在其中一个小图
画框
但是这个小图里面的框 是小图的坐标
那么这个框 在 原图中的 坐标 是什么
回答:
opencv 读取图片的话,是 numpy.ndarray
类型,可以用切片操作裁剪图片 img[y1:y2, x1:x2].copy()
,也可以直接用 numpy.hsplit
分割图片,必须保证宽高能平分
import cv2import numpy as np
from requests import get
img_url = 'https://avatar-static.segmentfault.com/569/558/569558099-1030000000094051_huge256'
img: np.ndarray = cv2.imdecode(np.frombuffer(get(img_url).content, np.uint8), cv2.IMREAD_COLOR)
h, w = img.shape[:2]
nRows, nCols = 4, 4
sub_h, sub_w = h//nRows, w//nCols
# 分割图片
sub_imgs = np.array(np.hsplit(np.array(np.hsplit(img, nCols)), nRows))
# 填充矩形
r, c, x1, y1, x2, y2 = 2, 3, 10, 20, 54, 44
sub_imgs[r, c, y1:y2, x1:x2] = (0, 0, 255)
img[sub_h*r+y1:sub_h*r+y2, sub_w*c+x1:sub_w*c+x2] = (0, 0, 255)
# 显示
div_w, div_color = 16, np.array([222, 222, 222], np.uint8)
img_split = np.ones((h+div_w*(nRows-1), w+div_w*(nCols-1), 3), np.uint8) * div_color
step_y, step_x = sub_h+div_w, sub_w+div_w
for i, row in enumerate(sub_imgs):
for j, sub_img in enumerate(row):
img_split[step_y*i:step_y*i+sub_h, step_x*j:step_x*j+sub_w] = sub_img
cv2.imshow('img', img)
cv2.imshow('img_split', img_split)
cv2.waitKey()
如果不能平分,可以考虑换成 numpy.array_split
分割,它会把剩余宽高分给靠左的 w % nCols
列和靠上的 h % nRows
行,如 128 * 128 分成 3 行 3 列是
import cv2import numpy as np
from requests import get
img_url = 'https://avatar-static.segmentfault.com/569/558/569558099-1030000000094051_huge128'
img: np.ndarray = cv2.imdecode(np.frombuffer(get(img_url).content, np.uint8), cv2.IMREAD_COLOR)
nRows, nCols = 3, 3
sub_imgs = [np.array_split(row, nCols, 1) for row in np.array_split(img, nRows, 0)]
print(*([f'{img.shape[1]} * {img.shape[0]}' for img in row] for row in sub_imgs), sep='\n')
# ['43 * 43', '43 * 43', '42 * 43']
# ['43 * 43', '43 * 43', '42 * 43']
# ['43 * 42', '43 * 42', '42 * 42']
再给个基于 pillow 库 crop
裁剪图片的图片分割函数
import osfrom io import BytesIO
from itertools import chain
import PIL.Image as Images
from PIL.Image import Image
from requests import get
def split_box(box: tuple[int, int, int, int], ncols: int = 1, nrows: int = 1) -> list[list[tuple[int, int, int, int]]]:
subw, extraw = divmod(box[2] - box[0], ncols)
subh, extrah = divmod(box[3] - box[1], nrows)
kx, ky = box[0] + (subw + 1) * extraw, box[1] + (subh + 1) * extrah
lr1, lr2 = range(box[0], kx + 1, subw + 1), range(kx, box[2] + 1, subw)
ul1, ul2 = range(box[1], ky + 1, subh + 1), range(ky, box[3] + 1, subh)
return [[(left, upper, right, lower)
for left, right in chain(zip(lr1[:-1], lr1[1:]), zip(lr2[:-1], lr2[1:]))]
for upper, lower in chain(zip(ul1[:-1], ul1[1:]), zip(ul2[:-1], ul2[1:]))]
def split_image(img: Image, ncols: int = 1, nrows: int = 1) -> list[list[Image]]:
return [[img.crop(box) for box in row] for row in split_box((0, 0, *img.size), ncols, nrows)]
img_url = 'https://avatar-static.segmentfault.com/569/558/569558099-1030000000094051_huge128'
img = Images.open(BytesIO(get(img_url).content))
# 分割图片
subimgs = split_image(img, 3, 3)
subboxs = split_box((0, 0, *img.size), 3, 3)
# 填充矩形
subimgs[1][2].paste((255, 0, 0), (10, 10, 20, 20))
subx, suby = subboxs[1][2][:2]
img.paste((255, 0, 0), (subx+10, suby+10, subx+20, suby+20))
# 输出大小
print(*([subimg.size for subimg in row] for row in subimgs), sep='\n')
# 显示
img_split = Images.new('RGB', (img.width + 16 * 2, img.height + 16 * 2), (222, 222, 222))
for i, row in enumerate(subimgs):
for j, sub_img in enumerate(row):
img_split.paste(sub_img, (subboxs[i][j][0] + 16 * j, subboxs[i][j][1] + 16 * i))
img.show()
img_split.show()
# 保存
# os.makedirs('img', exist_ok=True)
# img.save('img/img.jpg')
# for i, row in enumerate(subimgs):
# for j, sub_img in enumerate(row):
# sub_img.save(f'img/subimgs[{i}][{j}].jpg')
回答:
以上是 Python如何裁剪图片,并且裁剪的图片如何变换原图坐标? 的全部内容, 来源链接: utcz.com/p/938556.html