Python 带有标题和边框周围空间的OpenCV子绘图图像

Python 带有标题和边框周围空间的OpenCV子绘图图像,python,opencv,image-processing,Python,Opencv,Image Processing,我希望在OpenCV Python中显示一些图像,每个子地块周围都有标题和边框。类似这样的事情(由下面的帖子提供:): 我想要什么: 但我只能通过修改代码来实现这一点 import cv2 im1 = cv2.imread('Lenna.png') final_frame = cv2.hconcat((im1, im1)) cv2.imshow('lena', final_frame) 我拥有的 是否可以使用OpenCV获取此信息? 我知道一个解决办法是在图像上添加文本,但这不是我

我希望在OpenCV Python中显示一些图像,每个子地块周围都有标题和边框。类似这样的事情(由下面的帖子提供:):

我想要什么:

但我只能通过修改代码来实现这一点

 import cv2
 im1 = cv2.imread('Lenna.png')
 final_frame = cv2.hconcat((im1, im1))
 cv2.imshow('lena', final_frame)
我拥有的

是否可以使用OpenCV获取此信息? 我知道一个解决办法是在图像上添加文本,但这不是我想要的,因为这样可以覆盖重要信息

更新

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


我有一个快速而肮脏的解决方案。您可以根据自己的需要对其进行优化。我在代码旁边也有解释:

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)

您可以为不同的边界找到许多其他选项


总体思路是创建一个新图像,其宽度+=width/10和高度+=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)
导入cv2
将numpy作为np导入
img=cv2.imread(“/Users/anmoluppal/Downloads/Lenna.png”)
高度、宽度,ch=img.shape
新宽度,新高度=宽度+宽度/20,高度+高度/8
#用新的宽度和高度装入新的帆布箱。
画布=np.ones((新高度,新宽度,ch),数据类型=np.uint8)*125
#新建用原始图像替换画布中心
顶部填充,左侧填充=60,10
如果填充顶部+高度<新高度,填充左侧+宽度<新宽度:
画布[padding\u top:padding\u top+高度,padding\u left:padding\u left+宽度]=img
其他:
打印“给定的填充超出限制。”
text1=“示例图像1”
text2=“示例图像2”
img1=cv2.putText(canvas.copy(),text1,(int(0.25*width),30),cv2.FONT\u HERSHEY\u COMPLEX,1,np.array([255,0,0]))
img2=cv2.putText(canvas.copy(),text2,(int(0.25*width),30),cv2.FONT\u HERSHEY\u COMPLEX,1,np.array([255,0,0]))
最终=cv2.hconcat((img1,img2))
cv2.imwrite(“./debug.png”,最终版本)

我使用其他答案创建了一个可用于任意行/列的通用函数:

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)
下面是一个示例用法:

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)
该脚本生成以下cv2图像:


希望这个答案有帮助。你可以修改它以满足你的要求。一个小评论。为什么不增加中顶部边框的大小,例如
常量=cv2.copyMakeBorder(img1100,10,10,10,cv2.border\u常量,value=black)
。这样就不再需要紫色的矩形了。我不是要找什么花哨的东西,而是要找一些快速简单的东西:)就像我说的,你可以随时修改它。您还可以调整文本的位置:我希望这对你有帮助:)嘿,这是一个更好的解决方案。伟大的工作伙伴!!!!我的方法很快又脏:不用担心,伙计,你的解决方案是使用内置方法,比如
cv2.copyMakeBorder
,而不是数学,这对我来说很好,谢谢欣赏:)如果你有相同大小的图像,你必须小心
numpy数组
将数组数组展平为n维数组。在本例中,是一个五维数组。我还没有找到一个好方法来强制
numpy
保留数组数组,但是这个解决方法正在起作用:
a1=np.random.random((300300,1))
a2=a1
imgs=np.empty([1,2],dtype=object)
imgs[0,0]=a1
imgs[0,1]=a2
#--- I finally concatenated both the above images horizontally---
final_img = cv2.hconcat((vcat, vcat))
cv2.imshow('Final', final_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
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)
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)
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)