運動影像分割
在一個視頻檔案中,分割出前景目標,之前網上看了一些方法,包括幀差法、GMM等,
幀差法太簡單,但是只能提取輪廓,而且會出現前景目標部磁區域消失的問題,GMM對于小白菜來說有點高深,看不太懂,
接下來給大家介紹一下幀差和一種能夠提取前景目標區域的一種方法,
幀差法
二幀差法:
利用后一幀影像與前一幀影像的差值,取差值的絕對值作為運動目標的檢測幀,將檢測幀進行使用合適閾值進行二值化,再通過一些常用的影像處理演算法進行影像增強,其實二幀差法利用了一階梯度的思想,對于背景點,變化很小,所以兩幀的差很小;對于前景點,像素變化比較大,幀差比較大,不足之處是對噪聲比較敏感,如果幀率比較高,可能會出現前景目標整體消失的情況,如果前景目標部磁區域未動的話,也會檢測不到,

來看一下二幀差的效果,分別用大目標分割和小目標分割測驗,大目標可以通過形態學處理增強,小目標很難增強,因為如果膨脹腐蝕的話會改變目標的輪廓和大小,很難去控制,左圖紅色圈出的就是部分消失的情況,

三幀差法:
直接上流程圖和結果,三偵差可以抑制一些噪聲,但是還會出現前景目標部分消失的問題,因為用的是與操作,所以線潭訓細一點,


背景建模法(名字很酷吧)
對于一段視頻來說,每個像素點在每一幀的像素值既有可能是背景,也有可能是前景,對于視頻檔案來說,所有像素點就構成了一個隨機程序,
由我們的任務目標,根據統計概率知識做出如下假設:
(1)對于同一個像素點,作為背景時的統計概率較高;
(2)背景的像素值是穩定的,
因此我們利用視頻檔案中每個像素點出現頻率最高的像素值構建出一個背景模型,也就是最大概率準則,
然后再使用每一幀圖片,與我們的背景模型在一個可接受域內做前景目標構造,

看一下建立的背景:
均值背景可以看出前景目標的運動軌跡,大家可以試試,最大概率背景也就是我們上面提到的方法建立的背景,有點毛糙,可能是視頻錄制的不是很好,中值背景稍微光滑點,其實感覺在大多數情況下,中值背景應該和最大概率背景是一樣的,

看一下,分割結果,背景建模法對于小目標檢測還是很不錯的感覺,

頻域上使用背景建模法
接下來我們嘗試把這種方法應用在頻域上,將每一幀圖片的傅里葉變換減去背景圖的傅里葉變換,然后進行反變換得到運動目標的檢測幀,然后再利用形態學方法將得到的二值圖進行影像增強,效果如下圖所示,其實在頻域上減去背景的話并不會直接將背景減去,反而是一個類似影像融合的程序,把前景目標和建模的背景融合到了一起,

最后給大家分享一下背景建模法的代碼把,因為個人編程能力有限,編程習慣不太好,不喜勿噴,
import cv2
import numpy as np
from collections import Counter
cap = cv2.VideoCapture("luren.mp4")
cap2 = cv2.VideoCapture("luren.mp4")
frameNum = 0
NpKernel1 = np.uint8(np.ones((3,3)))
NpKernel2 = np.uint8(np.ones((5,5)))
ret, frame = cap.read()
tempframe = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
h,w = tempframe.shape
tempframe=tempframe.reshape(-1)
pix_list = [[] for i in range(len(tempframe))]
pixbg_list = []
for i in range(len(tempframe)):
pix_list[i].append(tempframe[i])
frameNum += 1
while cap.isOpened():
ret, frame = cap.read()
if ret == True:
tempframe = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
tempframe = tempframe.reshape(-1)
for i in range(len(tempframe)):
pix_list[i].append(tempframe[i])
frameNum += 1
print(frameNum)
else:
break
cap.release()
for i in range(len(tempframe)):
#pixbg_list.append(Counter(pix_list[i]).most_common(1)[0][0]) # 最大概率值
# pixbg_list.append((np.sum(np.array(pix_list[i])) / len(pix_list[i])).astype(dtype='uint8')) #均值
pixbg_list.append(np.median(np.array(pix_list[i])).astype(dtype='uint8')) # 中值
pixbg = np.array(pixbg_list).reshape(h,w)
print('ok')
# pixbg = cv2.medianBlur(pixbg, 3)
cv2.imshow('pixbg', pixbg)
cv2.waitKey(0)
while cap2.isOpened():
cv2.waitKey(100)
ret, frame = cap2.read()
if ret == True:
tempframe = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
threshold_frame = np.ones_like(tempframe)
a = tempframe>=pixbg-10
b = tempframe<=pixbg+10
threshold_frame[a & b] = 0
threshold_frame = threshold_frame * 255
# erode_img = cv2.erode(threshold_frame, NpKernel1)
# erode_img = cv2.erode(erode_img, NpKernel1)
# #
# # erode_img = cv2.erode(threshold_frame, NpKernel1)
# # dilate_img = cv2.dilate(erode_img, NpKernel2)
# #
# dilate_img = cv2.dilate(erode_img, NpKernel2)
# erode_img = cv2.erode(dilate_img, NpKernel2)
# dilate_img = cv2.dilate(erode_img, NpKernel2)
median = cv2.medianBlur(threshold_frame, 3)
cv2.imshow('Frame', frame)
cv2.imshow('threshold_frame', median)
if cv2.waitKey(33) & 0xFF == ord('q'):
break
else:
break
cap2.release()
cv2.destroyAllWindows()
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/250145.html
標籤:其他
