最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

OpenCV4 實(shí)現(xiàn)背景分離的詳細(xì)步驟(背景減法模型)

 更新時(shí)間:2021年09月16日 14:47:23   作者:RayChiu757374816  
背景分離(BS)是一種通過(guò)使用靜態(tài)相機(jī)來(lái)生成前景掩碼(即包含屬于場(chǎng)景中的移動(dòng)對(duì)象像素的二進(jìn)制圖像)的常用技術(shù),本文給大家介紹OpenCV4 實(shí)現(xiàn)背景分離的詳細(xì)步驟,需要的朋友可以參考下

定義:

背景分離,又稱(chēng)背景減法模型。

背景分離(BS)是一種通過(guò)使用靜態(tài)相機(jī)來(lái)生成前景掩碼(即包含屬于場(chǎng)景中的移動(dòng)對(duì)象像素的二進(jìn)制圖像)的常用技術(shù)。

顧名思義,BS計(jì)算前景掩碼,在當(dāng)前幀與背景模型之間執(zhí)行減法運(yùn)算,其中包含場(chǎng)景的靜態(tài)部分,或者更一般而言,考慮到所觀察場(chǎng)景的特征,可以將其視為背景的所有內(nèi)容。

背景建模包括兩個(gè)主要步驟:

1. 背景初始化;

2. 背景更新。

初步,計(jì)算背景的初始模型,而在第二步中,更新模型以適應(yīng)場(chǎng)景中可能的變化。

OpenCV中三個(gè)背景分離的重要函數(shù)

BackgroundSubtractorMOG()

這是一個(gè)以混合高斯模型為基礎(chǔ)的前景/背景分割算法。

它使用 K(K=3 或 5)個(gè)高斯分布混合對(duì)背景像素進(jìn)行建模。使用這些顏色(在整個(gè)視頻中)存在時(shí)間的長(zhǎng)短作為混合的權(quán)重。背景的顏色一般持續(xù)的時(shí)間最長(zhǎng),而且更加靜止。

在 x,y平面上一個(gè)像素就是一個(gè)像素,沒(méi)有分布,但是背景建模是基于時(shí)間序列的,因此每一個(gè)像素點(diǎn)所在的位置在整個(gè)時(shí)間序列中就會(huì)有很多值,從而構(gòu)成一個(gè)分布

使用函數(shù)時(shí)先用函數(shù):CV2.createBackgroundSubtractorMOG() 創(chuàng)建一個(gè)背景對(duì)象。這個(gè)函數(shù)有些可選參數(shù),比如要進(jìn)行建模場(chǎng)景的時(shí)間長(zhǎng)度,高斯混合成分的數(shù)量,閾值等。將他們?nèi)吭O(shè)置為默認(rèn)值。然后在整個(gè)視頻中我們是需要使用backgroundsubtractor.apply() 就可得到前景的掩模了,移動(dòng)的物體會(huì)被標(biāo)記為白色,背景會(huì)被標(biāo)記為黑色的,前景的掩模就是白色的了。

不過(guò)目前這個(gè)方法已經(jīng)被棄用了,OpenCV中也沒(méi)有了相關(guān)函數(shù)的API。

BackgroundSubtractorMOG2

這個(gè)也是以高斯混合模型為基礎(chǔ)的背景/前景分割算法。這個(gè)算法的一個(gè)特點(diǎn)是它為每 一個(gè)像素選擇一個(gè)合適數(shù)目的高斯分布。(上一個(gè)方法中我們使用是 K 高斯分布),這樣就會(huì)對(duì)由于亮度等發(fā)生變化引起的場(chǎng)景變化產(chǎn)生更好的適應(yīng)。

和前面一樣我們需要?jiǎng)?chuàng)建一個(gè)背景對(duì)象。但在這里我們我們可以選擇是否檢測(cè)陰影。如果 detectShadows = True(默認(rèn)值),它就會(huì)檢測(cè)并將影子標(biāo)記出來(lái),但是這樣做會(huì)降低處理速度。影子會(huì)被標(biāo)記為灰色。

BackgroundSubtractorMOG2算法的兩個(gè)改進(jìn)點(diǎn):

  1.  -陰影檢測(cè)
  2. -速度快了一倍

BackgroundSubtractorGMG

此算法結(jié)合了靜態(tài)背景圖像估計(jì)和每個(gè)像素的貝葉斯分割。它使用前面很少的圖像(默認(rèn)為前 120 幀)進(jìn)行背景建模。使用了概率前景估計(jì)算法(使用貝葉斯估計(jì)鑒定前景)。這是一種自適應(yīng)的估計(jì),新觀察到的 對(duì)象比舊的對(duì)象具有更高的權(quán)重,從而對(duì)光照變化產(chǎn)生適應(yīng)。一些形態(tài)學(xué)操作 如開(kāi)運(yùn)算閉運(yùn)算等被用來(lái)除去不需要的噪音,在前幾幀圖像中你會(huì)得到一個(gè)黑色窗口,對(duì)結(jié)果進(jìn)行形態(tài)學(xué)開(kāi)運(yùn)算對(duì)與去除噪聲很有幫助。

不過(guò)同樣的,這個(gè)方法目前也是不再用了。

BackgroundSubtractorKNN

KNN作為大名鼎鼎的機(jī)器學(xué)習(xí)算法,其用在背景分離應(yīng)用中也是得心應(yīng)手,但是在此不對(duì)KNN作過(guò)多的解釋。

C++實(shí)現(xiàn):

#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/video.hpp>
#include <iostream>
#include <sstream>
using namespace cv;
using namespace std;
 
const int HISTORY_NUM = 7;// 14;// 歷史信息幀數(shù)
const int nKNN = 3;// KNN聚類(lèi)后判斷為背景的閾值
const float defaultDist2Threshold = 20.0f;// 灰度聚類(lèi)閾值
 
struct PixelHistory
{
	unsigned char* gray;// 歷史灰度值
	unsigned char* IsBG;// 對(duì)應(yīng)灰度值的前景/背景判斷,1代表判斷為背景,0代表判斷為前景
};
 
 
int main()
{
	PixelHistory* framePixelHistory = NULL;// 記錄一幀圖像中每個(gè)像素點(diǎn)的歷史信息
	cv::Mat frame, FGMask, FGMask_KNN;
	int keyboard = 0;
	int rows, cols;
	rows = cols = 0;
	bool InitFlag = false;
	int frameCnt = 0;
	int gray = 0;
	VideoCapture capture("768X576.avi");
	Ptr<BackgroundSubtractorKNN> pBackgroundKnn =
		createBackgroundSubtractorKNN();
	pBackgroundKnn->setHistory(200);
	pBackgroundKnn->setDist2Threshold(600);
	pBackgroundKnn->setShadowThreshold(0.5);
 
	while ((char)keyboard != 'q' && (char)keyboard != 27)
	{
		// 讀取當(dāng)前幀
		if (!capture.read(frame))
			exit(EXIT_FAILURE);
 
		cvtColor(frame, frame, COLOR_BGR2GRAY);
		if (!InitFlag)
		{
			// 初始化一些變量
			rows = frame.rows;
			cols = frame.cols;
			FGMask.create(rows, cols, CV_8UC1);// 輸出圖像初始化
 
			// framePixelHistory分配空間
			framePixelHistory = (PixelHistory*)malloc(rows * cols * sizeof(PixelHistory));
			for (int i = 0; i < rows * cols; i++)
			{
				framePixelHistory[i].gray = (unsigned char*)malloc(HISTORY_NUM * sizeof(unsigned char));
				framePixelHistory[i].IsBG = (unsigned char*)malloc(HISTORY_NUM * sizeof(unsigned char));
				memset(framePixelHistory[i].gray, 0, HISTORY_NUM * sizeof(unsigned char));
				memset(framePixelHistory[i].IsBG, 0, HISTORY_NUM * sizeof(unsigned char));
			}
 
			InitFlag = true;
		}
		if (InitFlag)
		{
			FGMask.setTo(Scalar(255));
			for (int i = 0; i < rows; i++)
			{
				for (int j = 0; j < cols; j++)
				{
					gray = frame.at<unsigned char>(i, j);
					int fit = 0;
					int fit_bg = 0;
					// 比較確定前景/背景
					for (int n = 0; n < HISTORY_NUM; n++)
					{
						if (fabs(gray - framePixelHistory[i * cols + j].gray[n]) < defaultDist2Threshold)// 灰度差別是否位于設(shè)定閾值內(nèi)
						{
							fit++;
							if (framePixelHistory[i * cols + j].IsBG[n])// 歷史信息對(duì)應(yīng)點(diǎn)之前被判斷為背景
							{
								fit_bg++;
							}
						}
					}
					if (fit_bg >= nKNN)// 當(dāng)前點(diǎn)判斷為背景
					{
						FGMask.at<unsigned char>(i, j) = 0;
					}
					// 更新歷史值
					int index = frameCnt % HISTORY_NUM;
					framePixelHistory[i * cols + j].gray[index] = gray;
					framePixelHistory[i * cols + j].IsBG[index] = fit >= nKNN ? 1 : 0;// 當(dāng)前點(diǎn)作為背景點(diǎn)存入歷史信息
 
				}
			}
		}
 
		pBackgroundKnn->apply(frame, FGMask_KNN);
		imshow("Frame", frame);
		imshow("FGMask", FGMask);
		imshow("FGMask_KNN", FGMask_KNN);
 
		keyboard = waitKey(30);
		frameCnt++;
	}
	capture.release();
 
	return 0;
 
}

python實(shí)現(xiàn):

import cv2
 
cap=cv2.VideoCapture('./768x576.avi')
 
fgbg = cv2.createBackgroundSubtractorKNN()
 
while (1):
    ret, frame = cap.read()
 
    fgmask = fgbg.apply(frame)
 
    cv2.imshow('frame', fgmask)
    k = cv2.waitKey(100) & 0xff
    if k == 27:
        break
 
cap.release()
cv2.destroyAllWindows()

利用圖像減法函數(shù)實(shí)現(xiàn)(python版本):

import cv2
import time
"""
背景減法
"""
cap = cv2.VideoCapture("./768x576.avi")
 
_, first_frame = cap.read()
first_gray = cv2.cvtColor(first_frame, cv2.COLOR_BGR2GRAY)
first_gray = cv2.GaussianBlur(first_gray, (5, 5), 0)
cv2.imshow("First frame", first_frame)
cv2.imwrite('first_frame.jpg', first_frame)
 
count_frame = 0
start = time.time()
 
while True:
    count_frame += 1
    _, frame = cap.read()
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    gray_frame = cv2.GaussianBlur(gray_frame, (5, 5), 0)
 
    difference = cv2.absdiff(first_gray, gray_frame)
    _, difference = cv2.threshold(difference, 25, 255, cv2.THRESH_BINARY)
 
    cv2.imshow("Frame", frame)
    cv2.imshow("difference", difference)
 
    key = cv2.waitKey(30)
    if key == 27:
        break
 
    end = time.time()
    print("time %.2f s" % (end-start))
    print(count_frame)
 
cap.release()
cv2.destroyAllWindows()

到此這篇關(guān)于OpenCV4 實(shí)現(xiàn)背景分離、背景減法模型的文章就介紹到這了,更多相關(guān)OpenCV4 實(shí)現(xiàn)背景分離內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解C++17中類(lèi)模板參數(shù)推導(dǎo)的使用

    詳解C++17中類(lèi)模板參數(shù)推導(dǎo)的使用

    自C++17起就通過(guò)使用類(lèi)模板參數(shù)推導(dǎo),只要編譯器能根據(jù)初始值推導(dǎo)出所有模板參數(shù),那么就可以不指明參數(shù),下面我們就來(lái)看看C++17中類(lèi)模板參數(shù)推導(dǎo)的具體使用吧
    2024-03-03
  • C語(yǔ)言中讀取時(shí)間日期的基本方法

    C語(yǔ)言中讀取時(shí)間日期的基本方法

    這篇文章主要介紹了C語(yǔ)言中讀取時(shí)間日期的基本方法,分別是time()函數(shù)和gmtime()函數(shù)的使用,注意返回值的區(qū)別,需要的朋友可以參考下
    2015-08-08
  • C語(yǔ)言中獲取和改變目錄的相關(guān)函數(shù)總結(jié)

    C語(yǔ)言中獲取和改變目錄的相關(guān)函數(shù)總結(jié)

    這篇文章主要介紹了C語(yǔ)言中獲取和改變目錄的相關(guān)函數(shù)總結(jié),包括getcwd()函數(shù)和chdir()函數(shù)以及chroot()函數(shù)的使用方法,需要的朋友可以參考下
    2015-09-09
  • C++實(shí)現(xiàn)完整功能的通訊錄管理系統(tǒng)詳解

    C++實(shí)現(xiàn)完整功能的通訊錄管理系統(tǒng)詳解

    來(lái)了來(lái)了,通訊錄管理系統(tǒng)踏著七彩祥云飛來(lái)了,結(jié)合前面的結(jié)構(gòu)體知識(shí)和分文件編寫(xiě)方法,我總結(jié)并碼了一個(gè)帶菜單的通訊錄管理系統(tǒng),在這篇文章中將會(huì)提到C的清空屏幕函數(shù),嵌套結(jié)構(gòu)體具體實(shí)現(xiàn),簡(jiǎn)單且充實(shí),跟著我的思路,可以很清晰的解決這個(gè)項(xiàng)目
    2022-05-05
  • 淺談關(guān)于C++memory_order的理解

    淺談關(guān)于C++memory_order的理解

    這篇文章主要介紹了淺談關(guān)于C++memory_order的理解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • C++詳解實(shí)現(xiàn)Stack方法

    C++詳解實(shí)現(xiàn)Stack方法

    C++ Stack(堆棧)是一個(gè)容器類(lèi)的改編,為程序員提供了堆棧的全部功能,也就是說(shuō)實(shí)現(xiàn)了一個(gè)先進(jìn)后出(FILO)的數(shù)據(jù)結(jié)構(gòu)
    2022-06-06
  • C語(yǔ)言熱門(mén)考點(diǎn)結(jié)構(gòu)體與內(nèi)存對(duì)齊詳解

    C語(yǔ)言熱門(mén)考點(diǎn)結(jié)構(gòu)體與內(nèi)存對(duì)齊詳解

    在掌握基本的結(jié)構(gòu)體使用后,我們?cè)诿嬖嚭痛笮捅荣愔谐3?huì)遇到一個(gè)熱門(mén)考點(diǎn):結(jié)構(gòu)體內(nèi)存對(duì)齊,也就是計(jì)算結(jié)構(gòu)體大小。接下來(lái)請(qǐng)跟著筆者一起來(lái)學(xué)習(xí)這塊知識(shí)點(diǎn)吧
    2021-10-10
  • C++中對(duì)象的常引用總結(jié)

    C++中對(duì)象的常引用總結(jié)

    以下是對(duì)C++中對(duì)象的常引用進(jìn)行了詳細(xì)的總結(jié)介紹,需要的朋友可以過(guò)來(lái)參考下,希望對(duì)大家有所幫助
    2013-10-10
  • C++模板的特化超詳細(xì)精講

    C++模板的特化超詳細(xì)精講

    最近我學(xué)習(xí)了C++中的模板相關(guān)知識(shí),模板是泛型編程的基礎(chǔ),十分重要。所以特意整理出來(lái)一篇文章供我們一起復(fù)習(xí)和學(xué)習(xí)
    2022-08-08
  • C C++算法題解LeetCode1408數(shù)組中的字符串匹配

    C C++算法題解LeetCode1408數(shù)組中的字符串匹配

    這篇文章主要為大家介紹了C C++算法題解LeetCode1408數(shù)組中的字符串匹配示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10

最新評(píng)論

伽师县| 南川市| 土默特左旗| 奈曼旗| 乃东县| 佛教| 盐亭县| 保亭| 大连市| 舒城县| 宁远县| 富阳市| 惠州市| 平远县| 巫山县| 永州市| 乐昌市| 资阳市| 封丘县| 广昌县| 阜新市| 云林县| 日土县| 余庆县| 都匀市| 弋阳县| 集贤县| 疏附县| 南漳县| 信宜市| 康平县| 靖远县| 郧西县| 随州市| 河北省| 汤阴县| 区。| 松潘县| 长宁区| 垫江县| 焉耆|