Python如何裁剪图片,并且裁剪的图片如何变换原图坐标?

Python如何裁剪图片
并且裁剪的图片如何变换原图坐标

需要滑窗裁剪图片
但是裁剪图片之后
识别的小框 在原图的坐标是怎么样的

比如 原图
1000*1000

裁剪N个小图

在其中一个小图
画框
但是这个小图里面的框 是小图的坐标

那么这个框 在 原图中的 坐标 是什么

Python如何裁剪图片,并且裁剪的图片如何变换原图坐标?


回答:

opencv 读取图片的话,是 numpy.ndarray 类型,可以用切片操作裁剪图片 img[y1:y2, x1:x2].copy(),也可以直接用 numpy.hsplit 分割图片,必须保证宽高能平分

import cv2

import 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()

Python如何裁剪图片,并且裁剪的图片如何变换原图坐标?Python如何裁剪图片,并且裁剪的图片如何变换原图坐标?

如果不能平分,可以考虑换成 numpy.array_split 分割,它会把剩余宽高分给靠左的 w % nCols 列和靠上的 h % nRows 行,如 128 * 128 分成 3 行 3 列是

import cv2

import 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 os

from 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如何裁剪图片,并且裁剪的图片如何变换原图坐标?Python如何裁剪图片,并且裁剪的图片如何变换原图坐标?


回答:

Python如何裁剪图片,并且裁剪的图片如何变换原图坐标?

以上是 Python如何裁剪图片,并且裁剪的图片如何变换原图坐标? 的全部内容, 来源链接: utcz.com/p/938556.html

回到顶部