【視頻鏡頭檢測】綜述與基於聚類的實現

視頻鏡頭檢測

最近CCF BDCI也搞得差不多了,理一理
推薦閱讀:浙大的一個PPT報告

什麼是視頻鏡頭檢測(shot detection)

Shot邊界檢測(Shot boundary detection ,SBD)指在視頻中自動檢測鏡頭的邊界,是視頻分析,視頻索引,視頻摘要,視頻搜索和其他基於內容的視頻操作的基本的預處理步驟。自動SBD是2001至2007年TRECVID比賽中的一項重要內容,現在視頻鏡頭檢測的技術都是比較成熟的技術了。

視頻流數據中最小的數據單位是‘鏡頭’,所以視頻分割的的目的是將視頻分割成一個個視頻鏡頭,而不是單一的幀。鏡頭的裏面就是包含的就當前場景的一個幀的序列。
在這裏插入圖片描述

如何鏡頭檢測的流程圖

在這裏插入圖片描述
常見的方法包括
Machine Learning 機器學習的方法
colour histograms(Superscript number denotes number of bins used)顏色直方圖的方法
Flash:針對閃光使用了特殊的方法。
LVals:在進行幀間比較的時候使用了亮度值。
Cmpr:operated only in the compressed (MPEG-1) domain (Cmpr).
AThr:使用了自適應的閾值法。
MCmp:使用了運動補償。
Edgs:使用了邊緣檢測。
STmp:運用了時空特徵。

代碼實現

方法有很多,在github中搜索關鍵詞:shot boundary detection,一些比價好的實現結果。
全卷積神經網絡的實現
全卷積神經網絡的實現版本2
基於opencv-python的實現
基於opencv-c++的實現

因爲時間緊迫,樓主主要調試了基於K-Means聚類的鏡頭檢測,直接上代碼,分好的鏡頭將存在shot的list中。

import cv2
import numpy as np
from functools import reduce
from sklearn.cluster import KMeans

def bhattacharyya_ruler(hist1, hist2):
    row = len(hist1)
    col = len(hist1[0])
    row2 = len(hist2)
    if (len(hist2) !=row or len(hist2[0]) != col):
        return False

    #normalization each histogram
    sum = 0
    sum2 = 0

    for i in range(row):
        a1 = reduce(lambda x,y: x+y, hist1[i], 0)
        a2 = reduce(lambda x,y:x+y, hist2[i],0)
        sum += a1
        sum2 += a2

    for i in range(row):
        hist1[i] = list(map(lambda a : float(a)/sum, hist1[i]))
        hist2[i] = list(map(lambda a: float(a) / sum2, hist2[i]))

    #measuring Bhattacharyya distance
    dist = 0
    for i in range(row):
        for j in range(col):
            dist += np.sqrt(hist1[i][j] * hist2[i][j])
    return dist

if __name__ == "__main__":
	file_addr = "video.mp4" #video path
	cap = cv2.VideoCapture(file_addr)
	
	#ROI window parameter
	n_rows = 3 
	n_images_per_row = 3 
	fc = 0 #frame_counter
	
	images = [] #frames
	hist = [] #histograms
	
	while cap.isOpened():
	    # Capture frame-by-frame
	    ret, frame = cap.read()
	    if not ret:
	        break
	    hueFrames = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) #convert Hue value
	    height, width, ch = hueFrames.shape # find shape of frame and channel
	    #cv2.imshow('frame'+str(fc+1), frame)
	    roi_height = int(height / n_rows) #to divide 9 pieces find height value for each frame
	    roi_width = int(width / n_images_per_row) #to divide 9 pieces find width value for each frame
	
	    #ROI part
	    images.append([]) #first row frame_id, column raw piece_id
	    hist.append([]) #first row frame_id, column raw piece_id
	    for x in range(0, n_rows):
	        for y in range(0,n_images_per_row):
	            #i am splitting into 9 pieces of each frame and added to the images 2d matrix
	            #row defines frame_id and column defines piece_id
	            tmp_image=hueFrames[x*roi_height:(x+1)*roi_height, y*roi_width:(y+1)*roi_width]
	            images[fc].append(tmp_image)
	
	    # Display the resulting sub-frame and calc local histogram values
	    for i in range(0, n_rows*n_images_per_row):
	            hist[fc].append(cv2.calcHist([images[fc][i]], [0], None, [256], [0, 256]))
	    fc += 1#frame counter 1 up
	
	    if cv2.waitKey(1) & 0xFF == ord('q'):
	        break
	
	dist = [] 
	
	#calculate bhattacharya dist
	for i in range(0,len(hist)-1):
	    dist.append(bhattacharyya_ruler(hist[i],hist[i+1])) 
	
	clt = KMeans(n_clusters=2) 
	clt.fit(dist) #calculate Kmeans
	
	big_center = 1 #select which cluster includes shot frames
	
	shots = [] #shots list. List will be include frame id
	
	for i in range(0,len(clt.labels_)):
	    if (big_center == clt.labels_[i]):
	        #get differnt shots 
	        shots.append(i+1)
	
	cap.release()
	cv2.destroyAllWindows()

源碼:基於機器學習—聚類的鏡頭檢測
待續未完

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章