如何使用 Python 在 OpenCV 中裁剪图像
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15589517/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to crop an image in OpenCV using Python
提问by Nolik
How can I crop images, like I've done before in PIL, using OpenCV.
如何使用 OpenCV 裁剪图像,就像我之前在 PIL 中所做的那样。
Working example on PIL
PIL 的工作示例
im = Image.open('0.png').convert('L')
im = im.crop((1, 1, 98, 33))
im.save('_0.png')
But how I can do it on OpenCV?
但是我怎么能在 OpenCV 上做到呢?
This is what I tried:
这是我尝试过的:
im = cv.imread('0.png', cv.CV_LOAD_IMAGE_GRAYSCALE)
(thresh, im_bw) = cv.threshold(im, 128, 255, cv.THRESH_OTSU)
im = cv.getRectSubPix(im_bw, (98, 33), (1, 1))
cv.imshow('Img', im)
cv.waitKey(0)
But it doesn't work.
但它不起作用。
I think I incorrectly used getRectSubPix. If this is the case, please explain how I can correctly use this function.
我想我错误地使用了getRectSubPix. 如果是这种情况,请解释我如何正确使用此功能。
采纳答案by Froyo
It's very simple. Use numpy slicing.
这很简单。使用 numpy 切片。
import cv2
img = cv2.imread("lenna.png")
crop_img = img[y:y+h, x:x+w]
cv2.imshow("cropped", crop_img)
cv2.waitKey(0)
回答by samkhan13
i had this question and found another answer here: copy region of interest
我有这个问题,并在这里找到了另一个答案:复制感兴趣的区域
If we consider (0,0) as top left corner of image called imwith left-to-right as x direction and top-to-bottom as y direction. and we have (x1,y1) as the top-left vertex and (x2,y2) as the bottom-right vertex of a rectangle region within that image, then:
如果我们将 (0,0) 视为图像的左上角,im从左到右称为 x 方向,从上到下称为 y 方向。我们将 (x1,y1) 作为该图像中矩形区域的左上角顶点和 (x2,y2) 作为右下角顶点,然后:
roi = im[y1:y2, x1:x2]
here is a comprehensive resource on numpy array indexing and slicingwhich can tell you more about things like cropping a part of an image. images would be stored as a numpy array in opencv2.
这里有一个关于numpy 数组索引和切片的综合资源,它可以告诉你更多关于裁剪图像的一部分的信息。图像将作为 numpy 数组存储在 opencv2 中。
:)
:)
回答by Dan Erez
here is some code for more robust imcrop ( a bit like in matlab )
这是一些更强大的 imcrop 代码(有点像在 matlab 中)
def imcrop(img, bbox):
x1,y1,x2,y2 = bbox
if x1 < 0 or y1 < 0 or x2 > img.shape[1] or y2 > img.shape[0]:
img, x1, x2, y1, y2 = pad_img_to_fit_bbox(img, x1, x2, y1, y2)
return img[y1:y2, x1:x2, :]
def pad_img_to_fit_bbox(img, x1, x2, y1, y2):
img = np.pad(img, ((np.abs(np.minimum(0, y1)), np.maximum(y2 - img.shape[0], 0)),
(np.abs(np.minimum(0, x1)), np.maximum(x2 - img.shape[1], 0)), (0,0)), mode="constant")
y1 += np.abs(np.minimum(0, y1))
y2 += np.abs(np.minimum(0, y1))
x1 += np.abs(np.minimum(0, x1))
x2 += np.abs(np.minimum(0, x1))
return img, x1, x2, y1, y2
回答by belgraviton
Robust crop with opencv copy border function:
具有opencv复制边框功能的稳健裁剪:
def imcrop(img, bbox):
x1, y1, x2, y2 = bbox
if x1 < 0 or y1 < 0 or x2 > img.shape[1] or y2 > img.shape[0]:
img, x1, x2, y1, y2 = pad_img_to_fit_bbox(img, x1, x2, y1, y2)
return img[y1:y2, x1:x2, :]
def pad_img_to_fit_bbox(img, x1, x2, y1, y2):
img = cv2.copyMakeBorder(img, - min(0, y1), max(y2 - img.shape[0], 0),
-min(0, x1), max(x2 - img.shape[1], 0),cv2.BORDER_REPLICATE)
y2 += -min(0, y1)
y1 += -min(0, y1)
x2 += -min(0, x1)
x1 += -min(0, x1)
return img, x1, x2, y1, y2
回答by smttsp
Note that, image slicing is not creating a copy of the cropped imagebut creating a pointerto the roi. If you are loading so many images, cropping the relevant parts of the images with slicing, then appending into a list, this might be a huge memory waste.
需要注意的是,图像切片也没有创造的一个副本cropped image,但创建pointer的roi。如果您要加载这么多图像,用切片裁剪图像的相关部分,然后附加到列表中,这可能会造成巨大的内存浪费。
Suppose you load N images each is >1MPand you need only 100x100region from the upper left corner.
假设您每个都加载 N 个图像,>1MP并且您只需要100x100左上角的区域。
Slicing:
Slicing:
X = []
for i in range(N):
im = imread('image_i')
X.append(im[0:100,0:100]) # This will keep all N images in the memory.
# Because they are still used.
Alternatively, you can copy the relevant part by .copy(), so garbage collector will remove im.
或者,您可以通过 复制相关部分.copy(),因此垃圾收集器将删除im.
X = []
for i in range(N):
im = imread('image_i')
X.append(im[0:100,0:100].copy()) # This will keep only the crops in the memory.
# im's will be deleted by gc.
After finding out this, I realized one of the commentsby user1270710mentioned that but it took me quite some time to find out (i.e., debugging etc). So, I think it worths mentioning.
找出在此之后,我意识到一个评论由user1270710提到,但我花了相当长的一段时间去找出(即,调试等)。所以,我觉得值得一提。
回答by m.hatami
this code crop an image from x=0,y=0 position to h=100,w=200
此代码将图像从 x=0,y=0 位置裁剪为 h=100,w=200
import numpy as np
import cv2
image = cv2.imread('download.jpg')
y=0
x=0
h=100
w=200
crop = image[y:y+h, x:x+w]
cv2.imshow('Image', crop)
cv2.waitKey(0)
回答by Sanyal
Below is the way to crop an image.
下面是裁剪图像的方法。
image_path:The path to the image to edit
image_path:要编辑的图像的路径
coords:A tuple of x/y coordinates (x1, y1, x2, y2)[open the image in mspaint and check the "ruler" in view tab to see the coordinates]
coords:x/y 坐标元组 (x1, y1, x2, y2)[在 mspaint 中打开图像并检查视图选项卡中的“标尺”以查看坐标]
saved_location: Path to save the cropped image
saved_location: 保存裁剪图像的路径
from PIL import Image
def crop(image_path, coords, saved_location:
image_obj = Image.open("Path of the image to be cropped")
cropped_image = image_obj.crop(coords)
cropped_image.save(saved_location)
cropped_image.show()
if __name__ == '__main__':
image = "image.jpg"
crop(image, (100, 210, 710,380 ), 'cropped.jpg')
回答by zabop
Alternatively, you could use tensorflow for the cropping and openCV for making an array from the image.
或者,您可以使用 tensorflow 进行裁剪,并使用 openCV 从图像制作数组。
import cv2
img = cv2.imread('YOURIMAGE.png')
Now imgis a (imageheight, imagewidth, 3) shape array. Crop the array with tensorflow:
现在img是一个 (imageheight, imagewidth, 3) 形状数组。使用 tensorflow 裁剪数组:
import tensorflow as tf
offset_height=0
offset_width=0
target_height=500
target_width=500
x = tf.image.crop_to_bounding_box(
img, offset_height, offset_width, target_height, target_width
)
Reassemble the image with tf.keras, so we can look at it if it worked:
使用 tf.keras 重新组装图像,以便我们可以查看它是否有效:
tf.keras.preprocessing.image.array_to_img(
x, data_format=None, scale=True, dtype=None
)
This prints out the pic in a notebook (tested in Google Colab).
这会在笔记本中打印出图片(在 Google Colab 中测试)。
The whole code together:
整个代码合起来:
import cv2
img = cv2.imread('YOURIMAGE.png')
import tensorflow as tf
offset_height=0
offset_width=0
target_height=500
target_width=500
x = tf.image.crop_to_bounding_box(
img, offset_height, offset_width, target_height, target_width
)
tf.keras.preprocessing.image.array_to_img(
x, data_format=None, scale=True, dtype=None
)

