OpenCV对带有标题和边框的图像进行子绘图

Rox*_*nne 1 python opencv image-processing

我希望在OpenCV Python中显示一些图像,每个子图周围都带有标题和边框。类似于以下内容(由以下stackoverflow帖子提供:OpenCV(Python)video subplots):

我想要的是: 在此处输入图片说明

但是我只能通过修改代码来做到这一点。

 import cv2
 im1 = cv2.imread('Lenna.png')
 final_frame = cv2.hconcat((im1, im1))
 cv2.imshow('lena', final_frame)
Run Code Online (Sandbox Code Playgroud)

是)我有的 在此处输入图片说明

是否可以使用OpenCV获得它?我知道一种解决方法是将文字放在图像上,但这不是我想要的,因为这样可以覆盖重要信息。

更新

我的不好,我最初没有指定:我有4个子图(所以有4个不同的图像),而不是示例中的两个。另外,由于我有视频(时间限制),因此我希望解决方案尽可能快

在此处输入图片说明

Zda*_*daR 6

一般的想法是使用width += width/10和创建新图像height += height/20。输入一些文字作为标题,并将输入图像沿中心放置为:

import cv2
import numpy as np


img = cv2.imread("/Users/anmoluppal/Downloads/Lenna.png")

height, width, ch = img.shape
new_width, new_height = width + width/20, height + height/8

# Crate a new canvas with new width and height.
canvas = np.ones((new_height, new_width, ch), dtype=np.uint8) * 125

# New replace the center of canvas with original image
padding_top, padding_left = 60, 10
if padding_top + height < new_height and padding_left + width < new_width:
    canvas[padding_top:padding_top + height, padding_left:padding_left + width] = img
else:
    print "The Given padding exceeds the limits."

text1 = "Sample Image 1"
text2 = "Sample Image 2"
img1 = cv2.putText(canvas.copy(), text1, (int(0.25*width), 30), cv2.FONT_HERSHEY_COMPLEX, 1, np.array([255, 0, 0]))
img2 = cv2.putText(canvas.copy(), text2, (int(0.25*width), 30), cv2.FONT_HERSHEY_COMPLEX, 1, np.array([255, 0, 0]))

final = cv2.hconcat((img1, img2))
cv2.imwrite("./debug.png", final)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


Jer*_*uke 5

我有一个非常快捷和肮脏的解决方案。您可以对其进行优化以适合您的需求。我在代码旁边也有解释:

import cv2
import numpy as np

img1 = cv2.imread('lena.jpg')

#--- Here I am creating the border---
black = [0,0,0]     #---Color of the border---
constant=cv2.copyMakeBorder(img1,10,10,10,10,cv2.BORDER_CONSTANT,value=black )
cv2.imshow('constant',constant)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

您可以在此页面上找到许多其他用于不同边框的选项

#--- Here I created a violet background to include the text ---
violet= np.zeros((100, constant.shape[1], 3), np.uint8)
violet[:] = (255, 0, 180) 
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

#--- I then concatenated it vertically to the image with the border ---

vcat = cv2.vconcat((violet, constant))
cv2.imshow('vcat', vcat)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

#--- Now I included some text ---
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(vcat,'FRAME',(30,50), font, 2,(0,0,0), 3, 0)
cv2.imshow('Text', vcat)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

#--- I finally concatenated both the above images horizontally---
final_img = cv2.hconcat((vcat, vcat))
cv2.imshow('Final', final_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明


Dan*_*Dan 5

我使用其他答案制作了一个适用于任意行/列的通用函数:

def cvSubplot(imgs,     # 2d np array of imgs (each img an np arrays of depth 1 or 3).
              pad=10,   # number of pixels to use for padding between images. must be even
              titles=None,  # (optional) np array of subplot titles
              win_name='CV Subplot' # name of cv2 window
              ):
    '''
    Makes cv2 based subplots. Useful to plot image in actual pixel size
    '''

    rows, cols = imgs.shape

    subplot_shapes = np.array([list(map(np.shape, x)) for x in imgs])
    sp_height, sp_width, depth = np.max(np.max(subplot_shapes, axis=0), axis=0)

    title_pad = 30
    if titles is not None:
        pad_top = pad + title_pad
    else:
        pad_top = pad

    frame = np.zeros((rows*(sp_height+pad_top), cols*(sp_width+pad), depth ))

    for r in range(rows):
        for c in range(cols):
            img = imgs[r, c]
            h, w, _ = img.shape
            y0 = r * (sp_height+pad_top) + pad_top//2
            x0 = c * (sp_width+pad) + pad//2
            frame[y0:y0+h, x0:x0+w, :] = img

            if titles is not None:
                frame = cv2.putText(frame, titles[r, c], (x0, y0-title_pad//4), cv2.FONT_HERSHEY_COMPLEX, .5, (255,255,255))

    cv2.imshow(win_name, frame)
    cv2.waitKey(0)
Run Code Online (Sandbox Code Playgroud)

下面是一个示例用法:

import cv2
import numpy as np

a1 = np.random.random((40,400,1))
a2 = np.random.random((200,200,1))
a3 = np.random.random((100,100,1))
a4 = np.random.random((300,150,1))
a5 = np.random.random((100,150,1))
filler = np.zeros((0,0,1))

titles = np.array([['A', 'B', 'C'], ['D', 'E', 'Filler']])

imgs = np.array([[a1, a2, a3], [a4, a5, filler]])

cvSubplot(imgs, pad=20, titles=titles)
Run Code Online (Sandbox Code Playgroud)

该脚本生成以下 cv2 图像:

在此处输入图片说明