程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式師世界 >> 編程語言 >  >> 更多編程語言 >> Python

Python如何裁剪圖片,並且裁剪的圖片如何變換原圖坐標?

編輯:Python

Python如何裁剪圖片
並且裁剪的圖片如何變換原圖坐標

需要滑窗裁剪圖片
但是裁剪圖片之後
識別的小框 在原圖的坐標是怎麼樣的

比如 原圖
1000*1000

裁剪N個小圖

在其中一個小圖
畫框
但是這個小圖裡面的框 是小圖的坐標

那麼這個框 在 原圖中的 坐標 是什麼



其他答案1:


其他答案2:

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

如果不能平分,可以考慮換成 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.png')
# for i, row in enumerate(subimgs):
# for j, sub_img in enumerate(row):
# sub_img.save(f'img/subimgs[{i}][{j}].png')


  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式師世界 All Rights Reserved