vin*_*nt 7 python opencv image python-imaging-library
我有一组不同尺寸的图像(45,50,3), (69,34,3), (34,98,3)。我想对这些图像添加填充,如下所示:
取整个图像的最大宽度和长度,然后将图像放入该尺寸
import os
import glob
import cv2
input_path="/home/images"
os.chdir(indput_path)
images=glob.glob("*.png")
Length=[]
Width=[]
for img in images:
img=cv2.imread(img)
width,length=img.shape[0:2]
Length.append(length)
Width.append(width)
W=max(Width)
L=max(Length)
Run Code Online (Sandbox Code Playgroud)
如何在opencv中添加填充,以使所有图像的大小相同?在示例中,l给出了图像的形状(69,98,3)
EDIT1:
Run Code Online (Sandbox Code Playgroud)
假设我有一个要转换为(80,60,3)形状的图像(49,39,3):input_image尺寸:{width = 49,heigh = 39}
所以top = height / 2 = 19.5
底部=高度/ 2 = 19.5
左=宽度/2=24.5
右=宽度/2=24.5
output_image尺寸:{width = 80,height = 60}
最高= 30
底部= 30
左= 40
右= 40
import cv2
import numpy as np
from matplotlib import pyplot as plt
BLUE = [255,255,255]
img1 = cv2.imread('/image.png')
constant=cv2.copyMakeBorder(img1,30,30,40,40,cv2.BORDER_CONSTANT,value=BLUE)
plt.subplot(231),plt.imshow(img1,'gray'),plt.title('ORIGINAL')
plt.subplot(233),plt.imshow(constant,'gray'),plt.title('CONSTANT')
plt.show()
print(constant.shape)
(109, 119, 3)
Run Code Online (Sandbox Code Playgroud)
但是应该是 (80,60,3)
EDIT2:
Run Code Online (Sandbox Code Playgroud)
有效
constant= cv2.copyMakeBorder(img1,15,16,10,11,cv2.BORDER_CONSTANT,value=BLUE)
Run Code Online (Sandbox Code Playgroud)
fmw*_*w42 21
这是在 Python/OpenCV/Numpy 中执行此操作的另一种方法。它使用 numpy 切片将输入图像复制到具有所需输出大小和给定偏移量的新图像中。在这里,我计算偏移量以进行中心填充。我认为使用宽度、高度、xoffset、yoffset 更容易做到这一点,而不是每边填充多少。
输入:
import cv2
import numpy as np
# read image
img = cv2.imread('lena.jpg')
old_image_height, old_image_width, channels = img.shape
# create new image of desired size and color (blue) for padding
new_image_width = 300
new_image_height = 300
color = (255,0,0)
result = np.full((new_image_height,new_image_width, channels), color, dtype=np.uint8)
# compute center offset
x_center = (new_image_width - old_image_width) // 2
y_center = (new_image_height - old_image_height) // 2
# copy img image into center of result image
result[y_center:y_center+old_image_height,
x_center:x_center+old_image_width] = img
# view result
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows()
# save result
cv2.imwrite("lena_centered.jpg", result)
Run Code Online (Sandbox Code Playgroud)
siv*_*ivi 11
像这样(填充在 openCV 上称为边框):
BLUE = [255,255,255]
constant= cv2.copyMakeBorder(image.copy(),10,10,10,10,cv2.BORDER_CONSTANT,value=BLUE)
Run Code Online (Sandbox Code Playgroud)
蓝色甚至可以变成白色
来源:https : //docs.opencv.org/3.4/da/d0c/tutorial_bounding_rects_circles.html
小智 9
尝试使用此功能:
from PIL import Image, ImageOps
def padding(img, expected_size):
desired_size = expected_size
delta_width = desired_size - img.size[0]
delta_height = desired_size - img.size[1]
pad_width = delta_width // 2
pad_height = delta_height // 2
padding = (pad_width, pad_height, delta_width - pad_width, delta_height - pad_height)
return ImageOps.expand(img, padding)
def resize_with_padding(img, expected_size):
img.thumbnail((expected_size[0], expected_size[1]))
# print(img.size)
delta_width = expected_size[0] - img.size[0]
delta_height = expected_size[1] - img.size[1]
pad_width = delta_width // 2
pad_height = delta_height // 2
padding = (pad_width, pad_height, delta_width - pad_width, delta_height - pad_height)
return ImageOps.expand(img, padding)
if __name__ == "__main__":
img = Image.open("./demo.jpg")
print(img)
img = resize_with_padding(img, (500, 400))
print(img.size)
img.show()
img.save("resized_img.jpg")
Run Code Online (Sandbox Code Playgroud)
原始图像

使用填充调整大小后

见https://gist.github.com/BIGBALLON/cb6ab73f6aaaa068ab6756611bb324b2
小智 8
您可以使用:
image = cv2.copyMakeBorder( src, top, bottom, left, right, borderType)
Run Code Online (Sandbox Code Playgroud)
其中src是您的源图像,顶部,底部,左侧,右侧是图像周围的填充。
您可以在循环中使用max(sizes)-图片的大小值,将填充添加到每个图片中。bordertype可以是以下之一:
由于我没有看到公认的答案,而且还必须确定函数的顶部、底部、左侧、右侧,因此我很容易找到对我有用的方法。摘自:https : //jdhao.github.io/2017/11/06/resize-image-to-square-with-padding/
import cv2
desired_size = 368
im_pth = "/home/jdhao/test.jpg"
im = cv2.imread(im_pth)
old_size = im.shape[:2] # old_size is in (height, width) format
ratio = float(desired_size)/max(old_size)
new_size = tuple([int(x*ratio) for x in old_size])
# new_size should be in (width, height) format
im = cv2.resize(im, (new_size[1], new_size[0]))
delta_w = desired_size - new_size[1]
delta_h = desired_size - new_size[0]
top, bottom = delta_h//2, delta_h-(delta_h//2)
left, right = delta_w//2, delta_w-(delta_w//2)
color = [0, 0, 0]
new_im = cv2.copyMakeBorder(im, top, bottom, left, right, cv2.BORDER_CONSTANT,
value=color)
cv2.imshow("image", new_im)
cv2.waitKey(0)
cv2.destroyAllWindows()
Run Code Online (Sandbox Code Playgroud)
这是一个为您做所有事情的函数:
import cv2
def pad_images_to_same_size(images):
"""
:param images: sequence of images
:return: list of images padded so that all images have same width and height (max width and height are used)
"""
width_max = 0
height_max = 0
for img in images:
h, w = img.shape[:2]
width_max = max(width_max, w)
height_max = max(height_max, h)
images_padded = []
for img in images:
h, w = img.shape[:2]
diff_vert = height_max - h
pad_top = diff_vert//2
pad_bottom = diff_vert - pad_top
diff_hori = width_max - w
pad_left = diff_hori//2
pad_right = diff_hori - pad_left
img_padded = cv2.copyMakeBorder(img, pad_top, pad_bottom, pad_left, pad_right, cv2.BORDER_CONSTANT, value=0)
assert img_padded.shape[:2] == (height_max, width_max)
images_padded.append(img_padded)
return images_padded
Run Code Online (Sandbox Code Playgroud)
这里一行就可以做到
from PIL import Image
from PIL import ImageOps
image = Image.open("demo.jpg").convert("RGB")
ImageOps.pad(image,(100,100)).save('imaged-with-border.png')
Run Code Online (Sandbox Code Playgroud)
这将使我的图像通过填充100x100保持其纵横比zero