背景
在之前學習爬蟲項目中憋他,得到的部分視頻是有水印的进陡,因此有能通過比較好的技術手段實現(xiàn)水印去除的需求。一般情況下萝衩,如果能獲取到無水印的原始素材是最好回挽,但某些網(wǎng)站本身的原始素材就是加了水印。對于這種情況猩谊,少量可以通過某些視頻剪輯軟件完成水印去除千劈,但對于大量素材,依賴人工完成是不現(xiàn)實的牌捷。
描述
這篇文章將提供一種方法墙牌,描述在特定類型視頻中,使用技術手段完成水印去除的實現(xiàn)暗甥,僅供參考學習喜滨,請合理使用,避免法律風險淋袖。
主要的實現(xiàn)方式其實非常簡單鸿市,主要是各種現(xiàn)有工具的整合,最終也達到了比較好的效果即碗。在限定品類之后,去除效果評估合格率達到了97%陌凳。
調研
在網(wǎng)上調研之后剥懒,主要有以下可參考的實現(xiàn),可以看到合敦,他們各自有不同的優(yōu)勢和缺點初橘。
高端大氣上AI
首先AI有比較高的接入成本和學習門檻,而且本身有些玄學充岛。拋開算法保檐,最終的效果還是依賴輸入樣本的訓練。再回到我們素材自身崔梗,不同作者其水印會是變化的(id為水右怪弧)。算法訓練蒜魄,其實獲得準確位置的能力有待確定扔亥。
總結缺點: 依賴眾多,需要訓練谈为,Id+logo變化的情況預計訓練模型不會容易適配旅挤,效果也不理想。ffmpeg delogo
實際是在水印位置添加濾鏡伞鲫,類似毛玻璃效果粘茄。這種是比較直接的方式,但問題的核心變成了如何獲取水印的位置秕脓。還有個問題就是柒瓣,ffmpeg delogo 的效果在不同視頻素材不穩(wěn)定儒搭。例如,如果一個視頻幀水印位置畫面內容比較多嘹朗,去除水印后會比較明顯师妙。不過一般情況下,水印在右上或者左上屹培,畫面內容相對較少默穴。
總結缺點:產生模糊區(qū)域,需要確定位置和大小褪秀。蒙版+opencv + python 逐幀處理
可否將視頻處理成圖片蓄诽,然后再按每張圖片來處理?當然理論是可行的媒吗,這就將問題變成了圖片去水印仑氛,而且像openCV有比較成熟的去水印算法。但是幾個問題闸英。
首先是openCV的圖片去水印需要一個蒙版锯岖,即有個純色+水印的圖片,當然也不太適合不同視頻水印logo變化的情況甫何。按每個視頻創(chuàng)建蒙版也是沒法做成自動化的出吹。
另一個是視頻處理成圖片后,內容過大辙喂。測試中捶牢,一個19MB的1080P60hz視頻,處理成圖片變成了3GB大小巍耗,而且每幀處理也比較耗時秋麸,更不說合并成視頻的耗時。
缺點明確: 生成蒙版+逐幀處理+耗時較大
- cv 獲取固定圖標+ id生成位置坐標
最后一種方案是折衷的方式炬太,也是最終采用的灸蟆。首先,水印的獲取仍然使用openCV娄琉,不過是采用CV的圖像識別次乓。對于視頻,也不是按照所有幀的方式孽水,而是隨機得選取某些幀獲取截圖票腰,然后用cv去拿到水印坐標。這里有個前提女气,是水印中有部分是不變的杏慰,比如logo。先人工將這部分摳圖下來,然后代入CV做識別缘滥,拿到了logo的坐標轰胁。因為不同幀會有變化,造成CV失敗的誤差朝扼,需要在失敗的坐標中篩選成功率高的赃阀。
然后由于水印是 logo+id的形式,再根據(jù)id的字數(shù)和字體字號占的像素數(shù)擎颖,通過之前獲取的坐標算出水印的大小榛斯。如此我們就知道了水印的位置和大小,就可以使用ffmpeg delogo做去除了搂捧。
總結驮俗,最后實際是采用了第四種方案和第二種的結合,當然這也是根據(jù)具體場景綜合考慮的允跑,未必就是通用和最優(yōu)的實現(xiàn)王凑。
技術方案
描述
如上面的介紹,最終識別部分方案可以匯總成如下的流程:既然已經(jīng)知道了水印的位置和大小聋丝,就可以使用ffmpeg delogo 的方式來去除索烹。絕大部分視頻的處理效果是可以接受的。
摳圖獲取統(tǒng)一logo ---> 視頻隨機分幀 ---> CV識別logo坐標 ---> 根據(jù)視頻作者昵稱計算水印大小 ---> ffmpeg delogo去除水印弱睦。
計算水印位置大小核心代碼
import cv2
from matplotlib import pyplot as plt
# source=input('source:')
# tpl=input('template:')
source = '/export/data/晴天獨奏/mask/1.png'
tpl = 'mark_bili_1280.png'
img = cv2.imread(source, 0)
img2 = img.copy()
template = cv2.imread(tpl, 0)
# 非1080*1920需要等比例縮放
w, h = template.shape[::-1]
ow, oh = img.shape[::-1]
# # All the 6 methods for comparison in a list
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
#
# methods = ['cv2.TM_CCOEFF_NORMED']
for meth in methods:
img = img2.copy()
method = eval(meth)
# Apply template Matching
res = cv2.matchTemplate(img, template, method)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
# If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(img, top_left, bottom_right, 255, 1)
print('x={},y={},w={},h={}'.format(top_left[0], top_left[1], bottom_right[0]-top_left[0], bottom_right[1] - top_left[1]))
plt.subplot(121), plt.imshow(res, cmap='gray')
plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(img, cmap='gray')
plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
plt.suptitle(meth)
plt.show()
比較識別效果
最終去除效果對比
視頻分幀代碼
import os
import sys
import cv2
video_name = sys.argv[1]
if video_name is None:
print("input video name!")
exit(1)
com = 'ffmpeg -ss 10 -i {} -f image2 -vframes 1 -y frame.png'.format(video_name)
os.system(com)
cv2.namedWindow('frame', 0)
img = cv2.imread('frame.png')
cv2.imshow('frame', img)
cv2.waitKey(0)
批量匹配水印
用于在批量的截圖中標記識別的水印术荤,并打印出坐標
import os
import cv2
# source=input('source:')
# tpl=input('template:')
tpl = '/export/code/github/demo/src/test/resources/mark/mark_bili_1280-1.png'
template = cv2.imread(tpl, 0)
# 非1080*1920需要等比例縮放
w, h = template.shape[::-1]
# # All the 6 methods for comparison in a list
# methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR',
# 'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED']
#
dir = '/export/data/BV1dT4y1E7w3/out/'
# dir = '/export/code/github/demo/data/out/'
files = []
for f in os.walk(dir):
f = f[2]
for x in f:
if '.png' not in x:
continue
files.append(x)
break
count = 1
for f in files:
source = dir + f
img = cv2.imread(source, 0)
img2 = img.copy()
ow, oh = img.shape[::-1]
meth = 'cv2.TM_CCOEFF_NORMED'
img = img2.copy()
method = eval(meth)
# Apply template Matching
res = cv2.matchTemplate(img, template, method)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
# If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
top_left = min_loc
else:
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(img, top_left, bottom_right, 255, 1)
cv2.imwrite(source + ".mark.png", img)
print('id:{} x={}:y={}:w={}:h={}'.format(count, top_left[0], top_left[1], bottom_right[0] - top_left[0], bottom_right[1] - top_left[1]))
count = count + 1
遇到的問題
- 1.識別錯位
錯位有以下幾個原因造成。
- 1.1 部分視頻分辨率不統(tǒng)一每篷,如變成1280*720。 解決辦法是額外使用該分辨率下的logo 模板做CV識別端圈。
- 1.2 視頻網(wǎng)站在某個時間之后更換了logo樣式焦读。 解決辦法是只選取固定時間點之后的視頻。
- 1.3 水印中作者昵稱部分舱权,因為中英文字體大小矗晃,造成水印去除殘留。 解決辦法是根據(jù)不同字體用對應不同像素計算水印大小宴倍。以及多加些額外的冗余值张症,保證去除范圍比實際水印范圍大。
- 1.4 其他識別錯位鸵贬。有極少數(shù)視頻因為內容的原因俗他,隨機取的幀無法正確得到水印位置勒叠。解決方法是設置閾值佃牛,比如隨機20幀,只有某個坐標重復達到或超過5次风响,才作為有效坐標,否則羡亩,重新截圖分幀摩疑,再次失敗。實際驗證效果不是很理想畏铆,遂超過次數(shù)后雷袋,判斷為失敗,過濾掉辞居。還有就是本身沒有水印楷怒,這種目前只能以來人工介入。
- ffmpeg 消耗CPU資源過高
這個主要是開始沒有太注意ffmpeg的參數(shù)速侈,默認占滿全部CPU率寡,導致開始時候卡頓。 可以通過-threads
參數(shù)設置占用的CPU - 視頻水印去除后毛玻璃效果過于明顯
這種情況因為完全和視頻內容有關系倚搬,目前的方案依賴ffmpeg冶共,暫時無解。能想到的是優(yōu)化ffmpeg的去水印算法每界,非現(xiàn)實快速可達的方案捅僵。 - 項目中都是java,有沒有方法將如上包括openCV, ffmpeg的調用使用java實現(xiàn)眨层?
這算是個嘗試庙楚,當然答案是可以實現(xiàn)的,有現(xiàn)成的Bytedeco
趴樱,可以避免自己寫大量命令行調用馒闷。
總結
以上就是本篇文章的所有內容,限于篇幅叁征,部分細節(jié)沒有全部補充纳账。過程中某些情況下,雖然已經(jīng)知道了方法捺疼,但是仍然需要花大量的時間去調試和驗證才能知道最終的效果疏虫。當然最后也是在不斷的實踐下有了明顯的提升。如之前所說啤呼,在控制輸入樣本的前提下卧秘,比如只選擇右上角水印,盡量保證視頻分辨率一致等官扣,最終的評估合格率達到了97%翅敌,還是令人滿意的。
參考資料
- ziweipolaris/watermark-removal: 通過水印減除方法去掉視頻中的水印醇锚,快速但不完美
- 基于GAN的圖像水印去除器哼御,效果堪比PS高手 – 閃念基因 – 個人技術分享
- 毫秒級圖像去噪坯临!新AI系統(tǒng)完美去水印恋昼! - 云+社區(qū) - 騰訊云
- 去噪看靠、去水印、超分辨率液肌,這款不用學習的神經(jīng)網(wǎng)絡無所不能 - 云+社區(qū) - 騰訊云
- 【深度學習去水印】- CSDN
- 去噪挟炬、去水印、超分辨率嗦哆,這款不用學習的神經(jīng)網(wǎng)絡無所不能 | 機器之心
- [論文分享(一)] 水印自動去除(上)---水印的自動識別和特征提取 - 知乎
- 短視頻解析谤祖,去水印原理整理匯總-博客
- Python實現(xiàn)超簡單【抖音】無水印視頻批量下載fei347795790的博客-CSDN博客抖音批量下載 無水印
- 接近無損的視頻去水印方法
- Python OpenCV去除圖片水印_XerCis的博客-CSDN博客_cv2 去除水印
- python利用opencv去除水印方法 - 菲菲菲菲菲常新的新手 - 博客園
- 兩種Python基于OpenCV的固定位置半透明水印去除方案 - 麥拂沙的個人空間 - OSCHINA
- 基于python的圖片修復程序-可用于水印去除 - 簡書
- JavaCV入門示例及UnsatisfiedLinkError異常踩坑記錄
- Bytedeco - Home