最近產(chǎn)品有了一個(gè)天才的想法血筑,做一個(gè)影集類似的功能,前面用圖片制作影像消恍、合成音頻的操作都還挺順利岂昭,但是到了給視頻添加特效的時(shí)候就遇到了困難。
以前使用Pr或繪聲繪影的時(shí)候就在想狠怨,這些軟件背后的代碼是什么樣的呢约啊?看來這一次我自己也可以親手體驗(yàn)一番了邑遏。
這次主要遇到了兩個(gè)問題:
- 在圖片間插入過場動(dòng)畫 (這一篇將不會(huì)講到這個(gè))
- 在視頻開頭添加一個(gè)半透明的幾何圖案
圖片合成
Google了一大票答案,很容易得出答案恰矩,OpenCV提供了<e>addWeighted</e>接口來做圖片合成的事情记盒。遂從手機(jī)上扒下來兩張圖來試試。
圖一 ( 4032 x 1884 )
圖二 ( 1126 x 1122 )
# video.py
import cv2
view1 = cv2.imread('view1.jpg')
view2 = cv2.imread('view2.jpg')
# addWeighted(src1, alpha, src2, beta, gamma, dst=None, dtype=None)
# alpha/beta 對應(yīng)兩張圖片的透明度, 0是完全透明 1是完全不透明
view = cv2.addWeighted(view1, 0.7, view2, 0.5, 0)
cv2.imwrite('view.jpg', view)
運(yùn)行一下外傅,呀纪吮,報(bào)錯(cuò)了
Traceback (most recent call last):
File "video.py", line 270, in <module>
view = cv2.addWeighted(view1, 0.7, view2, 1, 0)
cv2.error: OpenCV(3.4.2) /io/opencv/modules/core/src/arithm.cpp:659: error: (-209:Sizes of input arguments do not match) The operation is neither 'array op array' (where arrays have the same size and the same number of channels), nor 'array op scalar', nor 'scalar op array' in function 'arithm_op'
通過報(bào)錯(cuò)信息,得知待合成圖片的尺寸和<e>通道</e>必須要相等萎胰,這個(gè)尺寸好理解碾盟,通道是啥意思呢?
修改圖片尺寸
修改一下上面的代碼技竟,使它變成
# video.py
import cv2
view1 = cv2.imread('view1.jpg')
width = int((4032 - 1126) / 2)
height = int((1884 - 1122) / 2)
# 暴力裁剪
# TODO: 這里有更好的裁剪方案
view1 = view1[height:height + 1122, width:width + 1126]
view2 = cv2.imread('view2.jpg')
view = cv2.addWeighted(view1, 0.7, view2, 0.5, 0)
cv2.imwrite('view.jpg', view)
成品
view.jpg ( 1126 x 1122 )
帶Alpha通道的圖片和普通照片的合成
合成完圖片后冰肴,產(chǎn)品站在我身后,推了推眼鏡榔组,發(fā)現(xiàn)事情并不簡單熙尉。
“給你一個(gè)框,給我放到圖片里去”
背景實(shí)際上是透明的瓷患,這個(gè)黑色是在CSS中添加的骡尽,方便顯示
我琢磨著,兩張圖的尺寸相同應(yīng)該就能合成成一張圖了吧擅编!但是正如上文所提到的攀细,圖片中的通道數(shù)和也必須要一致才能調(diào)用<e>addWeighted</e>方法進(jìn)行合成。
# video.py
import cv2
# 使用cv2.IMREAD_UNCHANGED 將會(huì)保留 PNG的Alpha通道
# 而直接讀取PNG也可以進(jìn)行圖像混合爱态,不過這種情況不在本次的討論中
blank = cv2.imread('blank.png', cv2.IMREAD_UNCHANGED)
print(blank.shape) # (756, 567, 4)
view1 = cv2.imread('view1.jpg')
width = int((4032 - 756) / 2)
height = int((1884 - 567) / 2)
# 合適的裁剪
view1 = view1[height:height + 756, width:width + 567]
print(view1.shape) # (756, 567, 3)
由于通道不相等谭贪,兩張圖片并不能合成為一張圖片,我們可以
- 去掉blank的alpha通道
- 為view1增加一條alpha通道
這里锦担,我選擇的是第二種方法
# video.py
import cv2
import numpy
# 實(shí)現(xiàn)細(xì)節(jié)
b_channel, g_channel, r_channel = cv2.split(view1)
# 添加alpha通道
alpha_channel = numpy.ones(b_channel.shape, dtype=b_channel.dtype) * 50
view1 = cv2.merge((b_channel, g_channel, r_channel, alpha_channel))
print(view1) # (756, 567, 4)
成品
原文地址 >> https://code.evink.me/2018/11/post/mix-png-and-jpg-use-OpenCV/