OpenCV多幅图像合为一幅图像

3 篇文章 0 订阅
1 篇文章 0 订阅

在使用 OpenCV 显示图片时,一个窗口只能显示一幅图片,且不便于给图片添加标题,因此在需要显示多个图像并进行比较的情况下不太方便。使用 PIL 可以显示多个图片并添加标题,但鉴于使用 OpenCV时还要专门用 PIL 把 BGR 转为 RGB 并显示图像,简直是简直了!!!于是使用 OpenCV 和 numpy 写了两个函数:
ImgReplace(ImgA,ImgB,Position)用于将图片 ImgB 粘贴到 ImgA 的 position 位置处,并返回处理过的图像。ImgB的尺寸必须小于ImgA。ImgShow(Img,Layout,Title='',Text=[''],Scaling=1,Bk_color=(0,0,0),Font_size=0.7,Font_thick=1,Font_color=(255,255,255))用于将多幅图像合为一幅图像,并为合成图像和各个小图像添加标题。多个小图像的尺寸可以不同,小图像之间横向最小距离20像素,纵向最小距离50像素。函数共有9个参数,其中有两个参数 Img 和 Layout 是必要参数,其它参数可默认,详细参数说明见代码。

  1. ShowImg.py:
# -*- coding: utf-8 -*-
"""
Created on Tue Oct 15 21:27:29 2019

@author: Belth Pixtink

filename:ShowImg.py
******************************************************************************
ImgReplace(ImgA,ImgB,Position)
用途:将ImgB贴到ImgA的指定位置
ImgA:主图像
ImgB;需要拷贝的图像,尺寸应小于ImgA
Position:粘贴到ImgA中的位置
******************************************************************************
ImgShow(Img,Layout,Title='',Text=[''],Scaling=1,Bk_color=(255,255,255),
Font_size=0.7,Font_thick=1,Font_color=(0,0,0))
用途:将多幅图像合成为一幅图像
Img:必要参数,带合成的图像列表:Img[Img1,Img2,...]
Layout:必要参数,图像的排列方式,Layout[c,r],c:横向图片数量,r:纵向图片数量
Title:合成的主图像标题,上方正中显示,不支持汉字显示,默认无主标题
Text:每幅子图像的标题,列表形式:Text[Text1,Text2...],不支持汉字显示,默认无子标题
Scaling:合成图像的缩放因子,默认为1,不缩放
Bk_color:主图像的颜色,即合成后图像的背景色,元组形式:(B,G,R),默认为(0,0,0),黑色
Font_size:标题字体大小,取值范围0~1.2,默认为0.7
Font_thick:标题字体粗细,取值范围1~6,默认为1
Font_color:标题字体颜色,元组形式:(B,G,R),默认为(255,255,255),白色
******************************************************************************
"""

import cv2
import numpy as np

def ImgReplace(ImgA,ImgB,Position):
     X_size=ImgB.shape[0]
     Y_size=ImgB.shape[1]
     if ImgA.shape[0]>X_size and ImgA.shape[1]>Y_size:
          roi=ImgA[Position[1]:Position[1]+X_size,Position[0]:Position[0]+Y_size]
          gray=cv2.cvtColor(ImgB, cv2.COLOR_BGR2GRAY)
          ret, mask = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY)
          mask_inv = cv2.bitwise_not(mask)
          img = cv2.bitwise_and(roi, roi, mask=mask_inv)
          dst = cv2.add(img,ImgB)
          ImgA[Position[1]:Position[1]+X_size,Position[0]:Position[0]+Y_size] = dst
     else:
          print('ERROR: The size of ImgA should be larger than ImgB!!!')
     return ImgA

def ImgShow(Img,Layout,Title='',Text=[''],Scaling=1,Bk_color=(0,0,0),Font_size=0.7,Font_thick=1,Font_color=(255,255,255)):
     x = list()
     y = list()
     H_interval = list()
     W_interval = list()
     Width = 0
     Height = 0
     PicNum = len(Img)
     if Text[0]=='' and len(Text) == 1:
          Text = Text*PicNum
     elif len(Text) < PicNum:
          for i in range(len(Text),PicNum):
               Text.append('')
     if Font_size > 1.2:
          Font_size = 1.2
     if Font_thick > 6:
          Font_thick = 6
     for i in range(0,PicNum,1):
          x.append(Img[i].shape[1])
          y.append(Img[i].shape[0])
     for i in range(PicNum,Layout[0]*Layout[1],1):
          x.append(0)
          y.append(0)
     for i in range(0,Layout[1]):
          Height = Height + max(y[i*Layout[0]:i*Layout[0]+Layout[0]:])
          H_interval.append(Height)
     for i in range(0,Layout[0]):
          Width = Width + max(x[i::Layout[0]])
          W_interval.append(Width)
     Syn = np.zeros((Height+(Layout[1]+1)*50+20,Width+(Layout[0]+1)*20,3),np.uint8)
     cv2.rectangle(Syn,(0,0),(Syn.shape[1],Syn.shape[0]),Bk_color,-1)
     column = 20
     if Title == '':
          row = 50
     else:
          row = 100
          cv2.putText(Syn,Title,(int(Syn.shape[1]/2-(len(Title)*Font_size*1.5*18)/2),50),cv2.FONT_HERSHEY_SIMPLEX,Font_size*1.5,Font_color,Font_thick+1,cv2.LINE_AA)
     for i in range(0,Layout[1],1):
          for j in range(0,Layout[0],1):
               if i*Layout[0]+j < PicNum:
                    Syn = ImgReplace(Syn,Img[i*Layout[0]+j],[column,row])
                    cv2.putText(Syn,Text[i*Layout[0]+j],(column,row-5),cv2.FONT_HERSHEY_SIMPLEX,Font_size,Font_color,Font_thick,cv2.LINE_AA)
                    column = W_interval[j]+20*(j+2)
          row = row+max(y[Layout[0]*i:Layout[0]*(i+1):])+50
          column = 20
     if Scaling != 1:
          Syn = cv2.resize(Syn,(int(Syn.shape[1]*Scaling),int(Syn.shape[0]*Scaling)),interpolation = cv2.INTER_AREA)
     return Syn
  1. 调用 ImgShow :
# -*- coding: utf-8 -*-
"""
Created on Mon Oct 14 21:51:54 2019

@author: Belth Pixtink
"""
import cv2
import numpy as np
import ImgShow

print('Start...')
Pic=cv2.imread('D:/Pictures/ET.png')
PicM = cv2.resize(Pic,(480,270),interpolation = cv2.INTER_AREA)

Ck1 = np.array([[ -1,-1, 0],
                [ -1, 0, 1],
                [  0, 1, 1]])
Ck2 = np.array([[-1,1,-1],
                [ 1,0, 1],
                [-1,1,-1]])
Ck3 = np.array([[ 1, 1,1],
                [ 1,-8,1],
                [ 1, 1,1]])
Ck4 = np.array([[0.3,0.1,0.4],
                [0.5, 0,-0.5],
                [-0.4,-0.1,-0.3]])
Ck5 = np.array([[0,0,-1,0,0],
                [0,0,-1,0,0],
                [0,0, 2,0,0],
                [0,0, 0,0,0],
                [0,0, 0,0,0]])
#共计六幅图片
PicConv1 = cv2.filter2D(PicM,-1,Ck1)
PicConv2 = cv2.filter2D(PicM,-1,Ck2)
PicConv3 = cv2.filter2D(PicM,-1,Ck3)
PicConv4 = cv2.filter2D(PicM,-1,Ck4)
PicConv5 = cv2.filter2D(PicM,-1,Ck5)
#修改图片尺寸以测试函数
PicConv1 = cv2.resize(PicConv1,(510,390),interpolation = cv2.INTER_AREA)
PicConv2 = cv2.resize(PicConv2,(640,360),interpolation = cv2.INTER_AREA)
PicConv3 = cv2.resize(PicConv3,(720,400),interpolation = cv2.INTER_AREA)
PicConv4 = cv2.resize(PicConv4,(360,200),interpolation = cv2.INTER_AREA)
PicConv5 = cv2.resize(PicConv5,(480,270),interpolation = cv2.INTER_AREA)

T = ['Ck0','Ck1','Ck2','Ck3','Ck4','Ck5']
IMG = ImgShow.ImgShow([PicM,PicConv1,PicConv2,PicConv3,PicConv4,PicConv5],[3,2],Text=T,Title='Pictures',Scaling=1,Font_size=0.9,Font_thick=3,Font_color = (255,0,128),Bk_color=(192,192,192))
cv2.imwrite('D:/Pictures/Test.png',IMG)
print('End...')

运行效果:

  1. 3x2排列:
    @BelthPixtink
  2. 4x2排列:
    @BelthPixtink
  3. 2x3排列:
    @BelthPixtink
    == --------------------------------------------------------华丽的分割线--------------------------------------------------------==
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值