此demo是对上一个demo的改进, 上一个demo基于OpenCV的VideoCapture类,这个类只能读取视频文件,gif文件和本地摄像头的采集画面。总之,根据官方文档,其需要一个起始帧,而无法读取单独的图片文件。所以我们对其进行和稍微的改进( 利用:ret,frame = cv2.VideoCapture('source').read() ),当其读取失败时,返回ret为False。我们依据其输入源文件的文件类型,来改变它的输入结构(cv2.imread())。
但是,这个改动Python会raise很多警告信息(主要是cv2.VideoCapture的输入源文件类型错误),但是不影响使用 。
import PySimpleGUI as sg #pip install pysimplegui
import cv2 #pip install opencv-python
import numpy as np #pip install numpy
# input: BGimage, FGimage, graylevel
# graylevel of the FGimage to generate Key signal
# output: tuple ,miximage and FGimage key
def imageMix(imgBG,imgFG,graylev):
#blackFrame = np.zeros((360,640,3) , np.uint8)
if imgFG.any() == 0:
return (imgBG,imgFG)
imgFG_gray = cv2.cvtColor(imgFG, cv2.COLOR_BGR2GRAY)
ret, imgFG_key = cv2.threshold(imgFG_gray, graylev, 255, cv2.THRESH_BINARY)
if imgBG.any() == 0:
imgFG_fuse = cv2.bitwise_and(imgFG, imgFG,mask=imgFG_key) #fuse fg
return (imgFG_fuse,imgFG_key)
imgFG_key_inv = cv2.bitwise_not(imgFG_key)
imgBG_fuse = cv2.bitwise_and(imgBG,imgBG,mask=imgFG_key_inv) #fuse bg
imgFG_fuse = cv2.bitwise_and(imgFG, imgFG,mask=imgFG_key) #fuse fg
img_mix = cv2.addWeighted(imgBG_fuse, 1, imgFG_fuse, 1, 0) #fuse image
return (img_mix,imgFG_key)
#背景色
sg.theme('LightGreen')
#定义窗口布局
#Frame内元素
first_col_1 = [[sg.Image(filename='',size=(640,360),pad=(1,1),subsample=3,key='SRC')]]
first_col_2 = [[sg.Image(filename='',size=(640,360),pad=(1,1),subsample=4,key='Fill')]]
second_col_1 = [[sg.Image(filename='',size=(640,360),pad=(1,1),subsample=3,key='Mix')]]
second_col_2 = [[sg.Image(filename='',size=(640,360),pad=(1,1),subsample=3,key='Key')]]
col1= sg.Column([
[sg.Frame(title='SRC', layout=first_col_1 , title_location=sg.TITLE_LOCATION_BOTTOM, s=(650,378),element_justification='center'),
sg.Frame(title='Fill', layout=first_col_2 , title_location=sg.TITLE_LOCATION_BOTTOM, s=(650,378),element_justification='center')],
[sg.Frame(title='Mix', layout=second_col_1 , title_location=sg.TITLE_LOCATION_BOTTOM, s=(650,378),element_justification='center'),
sg.Frame(title='Key', layout=second_col_2 , title_location=sg.TITLE_LOCATION_BOTTOM, s=(650,378),element_justification='center')],
])
third_col_1 = [[ sg.Text('INPUT:'), sg.Input(default_text="", s=(75,2)), sg.FileBrowse('...',initial_folder='.\\image',key='SRC_in')]]
third_col_2 = [[ sg.Text('INPUT:'),sg.Input(default_text="",s=(75,2)), sg.FileBrowse('...',initial_folder='.\\image',key='Fill_in')]]
col2 = sg.Column([
[sg.Frame(title='SRC input:', layout=third_col_1 , title_location=sg.TITLE_LOCATION_TOP_LEFT, s=(650,45),element_justification='left'),
sg.Frame(title='Fill input:', layout=third_col_2 , title_location=sg.TITLE_LOCATION_TOP_LEFT, s=(650,45),element_justification='left')]
])
fouth_col_1 = [[sg.Text('Gray: '),sg.Slider((0, 255), 32, 1, orientation='h', size=(600, 15), key='gray_slider')]]
fouth_col_2 = [[sg.OK(), sg.Exit()]]
col3 = sg.Column([
[sg.Frame(title='GRAY:', layout=fouth_col_1 , title_location=sg.TITLE_LOCATION_TOP_LEFT, s=(650,75),element_justification='left'),
sg.Frame(title='Handle:', layout=fouth_col_2 , title_location=sg.TITLE_LOCATION_TOP_LEFT, s=(650,75),element_justification='right',vertical_alignment='bottom')]
])
#整合布局内容
layout = [[col1], [col2], [col3]]
window = sg.Window('OpenCV实时图像处理',
layout,
location=(800, 400),
finalize=True)
img_types = ['bmp','dib','jpeg','jpg','jpe','jp2','png','pbm','pgm','ppm','pxm','pnm','pfm','sr,ras','tiff','tif','exr','pic','hdr']
SRC_input = ''
Fill_input = ''
capture_src = cv2.VideoCapture(SRC_input)
capture_tlt = cv2.VideoCapture(Fill_input)
while True:
event, values = window.read(timeout=0, timeout_key='timeout')
#print(values['SRC_in'].split('.')[-1:1:],values['Fill_in'].split('.')[-1:1:])
#fill 信号转key 信号的灰阶
grade_gray = values['gray_slider']
#检查SRC输入源是否改变
if values['SRC_in'] != SRC_input:
#print(values['SRC_in'].split('.')[-1])
SRC_input = values['SRC_in']
capture_src.release()
capture_src = cv2.VideoCapture(SRC_input)
#实时读取图像
ret1, frame_left = capture_src.read()
#SRC图像匹配输出
if ret1:
img_src = cv2.resize(frame_left,(640,360))
else:
file_type = values['SRC_in'].split('.')[-1]
if file_type in img_types:
img_src = cv2.imread(values['SRC_in'])
img_src = cv2.resize(img_src,(640,360))
else:
img_src = np.zeros((360,640,3) , np.uint8)
#检查Fill输入源是否改变
if values['Fill_in'] != Fill_input:
Fill_input = values['Fill_in']
capture_tlt.release()
capture_tlt = cv2.VideoCapture(Fill_input)
#实时读取图像
ret2, frame_right = capture_tlt.read()
#GUI实时更新图像
if ret2:
img_tlt = cv2.resize(frame_right,(640,360))
else:
file_type = values['Fill_in'].split('.')[-1]
if file_type in img_types:
img_tlt = cv2.imread(values['Fill_in'])
img_tlt = cv2.resize(img_tlt,(640,360))
#img_tlt = cv2.cvtColor(img_tlt,cv2.COLOR_BGR2RGB)
else:
img_tlt = np.zeros((360,640,3) , np.uint8)
#图像融合
dst,mask = imageMix(img_src,img_tlt,grade_gray)
# fusion video
imgbytes1 = cv2.imencode('.png', dst)[1].tobytes()
window['Mix'].update(data=imgbytes1)
#fill video
imgbytes2 = cv2.imencode('.png', img_tlt)[1].tobytes()
window['Fill'].update(data=imgbytes2)
#source video
imgbytes3 = cv2.imencode('.png', img_src)[1].tobytes()
window['SRC'].update(data=imgbytes3)
# key video
imgbytes4 = cv2.imencode('.png', mask)[1].tobytes()
window['Key'].update(data=imgbytes4)
if event in (None ,'Exit'):
break
window.close()