1. 程式人生 > >Opencv對視訊進行運動物體的提取

Opencv對視訊進行運動物體的提取

要求:利用幀差法或背景差分法對視訊進行運動物體的提取。影象處理步驟為:讀取幀、平滑、幀差或背景差、二值化、膨脹、腐蝕。每一步的處理結果都用單獨視窗顯示出來。

一、原理

 平滑:

 平滑也可叫濾波,或者合在一起叫平滑濾波,平滑濾波是低頻增強的空間域濾波技術。它的目的有兩類:一類是模糊;另一類是消除噪音。空間域的平滑濾波一般採用簡單平均法進行,就是求鄰近像元點的平均亮度值。鄰域的大小與平滑的效果直接相關,鄰域越大平滑的效果越好,但鄰域過大,平滑會使邊緣資訊損失的越大,從而使輸出的影象變得模糊,因此需合理選擇鄰域的大小。

“平滑處理”也稱“模糊處理”(blurring),是一項簡單且使用頻率很高的影象處理方法。平滑處理的用途很多,但最常見的是用來減少影象上的噪聲或者失真。降低影象解析度時,平滑處理是很重要的。

 二值化的基本原理

      影象的二值化處理就是講影象上的點的灰度置為0255,也就是講整個影象呈現出明顯的黑白效果。即將256個亮度等級的灰度影象通過適當的閥值選取而獲得仍然可以反映影象整體和區域性特徵的二值化影象。在數字影象處理中,二值影象佔有非常重要的地位,特別是在實用的影象處理中,以二值影象處理實現而構成的系統是很多的,要進行二值影象的處理與分析,首先要把灰度影象二值化,得到二值化影象,這樣子有利於再對影象做進一步處理時,影象的集合性質只與畫素值為0255的點的位置有關,不再涉及畫素的多級值,使處理變得簡單,而且資料的處理和壓縮量小。為了得到理想的二值影象,一般採用封閉、連通的邊界定義不交疊的區域。所有灰度大於或等於閥值的畫素被判定為屬於特定物體,其灰度值為255

表示,否則這些畫素點被排除在物體區域以外,灰度值為0,表示背景或者例外的物體區域。如果某特定物體在內部有均勻一致的灰度值,並且其處在一個具有其他等級灰度值的均勻背景下,使用閥值法就可以得到比較的分割效果。如果物體同背景的差別表現不在灰度值上(比如紋理不同),可以將這個差別特徵轉換為灰度的差別,然後利用閥值選取技術來分割該影象。動態調節閥值實現影象的二值化可動態觀察其分割影象的具體結果。

膨脹

     其實,膨脹就是求區域性最大值的操作。

       按數學方面來說,膨脹或者腐蝕操作就是將影象(或影象的一部分割槽域,我們稱之為A)與核(我們稱之為B)進行卷積。

 核可以是任何的形狀和大小,它擁有一個單獨定義出來的參考點,我們稱其為錨點(anchorpoint)。多數情況下,核是一個小的中間帶有參考點和實心正方形或者圓盤,其實,我們可以把核視為模板或者掩碼。   

       而膨脹就是求區域性最大值的操作,核B與圖形卷積,即計算核B覆蓋的區域的畫素點的最大值,並把這個最大值賦值給參考點指定的畫素。這樣就會使影象中的高亮區域逐漸增長。如下圖所示,這就是膨脹操作的初衷

腐蝕

  再來看一下腐蝕,,大家應該知道,膨脹和腐蝕是一對好基友,是相反的一對操作,所以腐蝕就是求區域性最小值的操作,我們一般都會把腐蝕和膨脹對應起來理解和學習。下文就可以看到,兩者的函式原型也是基本上一樣的。

   原理圖:


幀差法 
       幀差法是最為常用的運動目標檢測和分割方法之一,基本原理就是在影象序列相鄰兩幀或三幀間採用基於畫素的時間差分通過閉值化來提取出影象中的運動區域。首先,將相鄰幀影象對應畫素值相減得到差分影象,然後對差分影象二值化,在環境亮度變化不大的情況下,如果對應畫素值變化小於事先確定的閡值時,可以認為此處為背景畫素:如果影象區域的畫素值變化很大,可以認為這是由於影象中運動物體引起的,將這些區域標記為前景畫素,利用標記的畫素區域可以確定運動目標在影象中的位置。由於相鄰兩幀間的時間間隔非常短,用前一幀影象作為當前幀的背景模型具有較好的實時性,其背景不積累,且更新速度快、演算法簡單、計算量小。演算法的不足在於對環境噪聲較為敏感,閩值的選擇相當關鍵,選擇過低不足以抑制影象中的噪聲,過高則忽略了影象中有用的變化。對於比較大的、顏色一致的運動目標,有可能在目標內部產生空洞,無法完整地提取運動目標。 

二、編碼過程及實現

1、讀取視訊

VideoCapture video("C:\\Users\\lenovo\\Desktop\\人工智慧\\多媒體\\Car.avi");

2、讀取幀

video >> frame;//讀幀進frame  
			imshow("frame", frame);
			if (frame.empty())//對幀進行異常檢測  
			{
				cout << "frame is empty!" << endl;
				break;
			}
3、處理
if (i == 0)//如果為第一幀(temp還為空)  
			{
				result = MoveDetect(frame, frame);//呼叫MoveDetect()進行運動物體檢測,返回值存入result  
			}
			else//若不是第一幀(temp有值了)  
			{
				result = MoveDetect(temp, frame);//呼叫MoveDetect()進行運動物體檢測,返回值存入result  

			}

			imshow("result", result);
			if (waitKey(1000.0 / FPS) == 27)//按原FPS顯示  
			{
				cout << "ESC退出!" << endl;
				break;
			}
			temp = frame.clone();

3、.平滑處理

IplImage *tempimg_src, *tempimg_dst;
	tempimg_src = &IplImage(temp);
	tempimg_dst = cvCreateImage(cvGetSize(tempimg_src), 8, 3);
	cvSmooth(tempimg_src, tempimg_dst, CV_BLUR, 3, 3, 0, 0);//平滑函式

	IplImage *frameimg_src, *frameimg_dst;
	frameimg_src = &IplImage(frame);
	frameimg_dst = cvCreateImage(cvGetSize(frameimg_src), 8, 3);
	cvSmooth(frameimg_src, frameimg_dst, CV_BLUR, 3, 3, 0, 0);//平滑函式


4、幀差

Mat temp1, frame1;
	temp1 = cvarrToMat(tempimg_dst);
	frame1 = cvarrToMat(frameimg_dst);
	//將background和frame轉為灰度圖  
	Mat gray1, gray2;
	cvtColor(temp1, gray1, CV_BGR2GRAY);
	cvtColor(frame1, gray2, CV_BGR2GRAY);
	//將background和frame做差  
	Mat diff;
	absdiff(gray1, gray2, diff);
	imshow("幀差圖", diff);

5、二值化

Mat diff_thresh;

	Mat kernel_erode = getStructuringElement(MORPH_RECT, Size(3, 3));//函式會返回指定形狀和尺寸的結構元素。
																	 //呼叫之後,呼叫膨脹與腐蝕函式的時候,第三個引數值儲存了getStructuringElement返回值的Mat型別變數。也就是element變數。
	Mat kernel_dilate = getStructuringElement(MORPH_RECT, Size(18, 18));

	//進行二值化處理,選擇50,255為閾值
	threshold(diff, diff_thresh, 50, 255, CV_THRESH_BINARY);
	imshow("二值化處理後", diff_thresh);


6、膨脹  

dilate(diff_thresh, diff_thresh, kernel_dilate);
imshow("膨脹處理後", diff_thresh);

7、腐蝕

erode(diff_thresh, diff_thresh, kernel_erode);
imshow("腐蝕處理後", diff_thresh);


8、查詢輪廓並繪製輪廓

vector<vector<Point> > contours;
	findContours(diff_thresh, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);//找輪廓函式
	drawContours(result, contours, -1, Scalar(0, 0, 255), 2);//在result上繪製輪廓  
															 //7.查詢正外接矩形  
	vector<Rect> boundRect(contours.size());
	for (int i = 0; i < contours.size(); i++)
	{
		boundRect[i] = boundingRect(contours[i]);
		rectangle(result, boundRect[i], Scalar(0, 255, 0), 2);//在result上繪製正外接矩形  
	}
	return result;//返回result  


9、完整程式碼

///運動物體檢測——幀差法  
#include"opencv2/opencv.hpp"  
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/core/core.hpp>
#include<opencv2/imgproc/imgproc.hpp>
using namespace cv;
#include <iostream>  
using namespace std;
//運動物體檢測函式宣告  
Mat MoveDetect(Mat temp, Mat frame);

int main()
{
	//讀取幀、平滑、幀差或背景差、二值化、膨脹、腐蝕。
	VideoCapture video("C:\\Users\\lenovo\\Desktop\\人工智慧\\多媒體\\Car.avi");
	if (!video.isOpened())
		return -1;
	while (1)
	{
		int frameCount = video.get(CV_CAP_PROP_FRAME_COUNT);//獲取幀數  
		double FPS = video.get(CV_CAP_PROP_FPS);//獲取FPS  
		Mat frame;//儲存幀  
		Mat temp;//儲存前一幀影象  
		Mat result;//儲存結果影象  
		for (int i = 0; i < frameCount; i++)
		{
			//讀取幀
			video >> frame;//讀幀進frame  
			imshow("frame", frame);
			if (frame.empty())//對幀進行異常檢測  
			{
				cout << "frame is empty!" << endl;
				break;
			}
			//處理幀
			if (i == 0)//如果為第一幀(temp還為空)  
			{
				result = MoveDetect(frame, frame);//呼叫MoveDetect()進行運動物體檢測,返回值存入result  
			}
			else//若不是第一幀(temp有值了)  
			{
				result = MoveDetect(temp, frame);//呼叫MoveDetect()進行運動物體檢測,返回值存入result  
			}

			imshow("result", result);
			if (waitKey(1000.0 / FPS) == 27)//按原FPS顯示  
			{
				cout << "ESC退出!" << endl;
				break;
			}
			temp = frame.clone();
		}
	}
	return 0;

}
Mat MoveDetect(Mat temp, Mat frame)
{

	//平滑、幀差或背景差、二值化、膨脹、腐蝕。
	Mat result = frame.clone();
	//1.平滑處理
	IplImage *tempimg_src, *tempimg_dst;
	tempimg_src = &IplImage(temp);
	tempimg_dst = cvCreateImage(cvGetSize(tempimg_src), 8, 3);
	cvSmooth(tempimg_src, tempimg_dst, CV_BLUR, 3, 3, 0, 0);//平滑函式

	IplImage *frameimg_src, *frameimg_dst;
	frameimg_src = &IplImage(frame);
	frameimg_dst = cvCreateImage(cvGetSize(frameimg_src), 8, 3);
	cvSmooth(frameimg_src, frameimg_dst, CV_BLUR, 3, 3, 0, 0);//平滑函式

															  //2.幀差
	Mat temp1, frame1;
	temp1 = cvarrToMat(tempimg_dst);
	frame1 = cvarrToMat(frameimg_dst);
	//將background和frame轉為灰度圖  
	Mat gray1, gray2;
	cvtColor(temp1, gray1, CV_BGR2GRAY);
	cvtColor(frame1, gray2, CV_BGR2GRAY);
	//將background和frame做差  
	Mat diff;
	absdiff(gray1, gray2, diff);
	imshow("幀差圖", diff);


	//對差值圖diff_thresh進行閾值化處理  二值化
	Mat diff_thresh;
	Mat kernel_erode = getStructuringElement(MORPH_RECT, Size(3, 3));//函式會返回指定形狀和尺寸的結構元素。																 //呼叫之後,呼叫膨脹與腐蝕函式的時候,第三個引數值儲存了getStructuringElement返回值的Mat型別變數。也就是element變數。
	Mat kernel_dilate = getStructuringElement(MORPH_RECT, Size(18, 18));

	//進行二值化處理,選擇50,255為閾值
	threshold(diff, diff_thresh, 50, 255, CV_THRESH_BINARY);
	imshow("二值化處理後", diff_thresh);
	//膨脹  
	dilate(diff_thresh, diff_thresh, kernel_dilate);
	imshow("膨脹處理後", diff_thresh);
	//腐蝕  
	erode(diff_thresh, diff_thresh, kernel_erode);
	imshow("腐蝕處理後", diff_thresh);

	//查詢輪廓並繪製輪廓  
	vector<vector<Point> > contours;
	findContours(diff_thresh, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);//找輪廓函式
	drawContours(result, contours, -1, Scalar(0, 0, 255), 2);//在result上繪製輪廓  
	 //查詢正外接矩形  
	vector<Rect> boundRect(contours.size());
	for (int i = 0; i < contours.size(); i++)
	{
		boundRect[i] = boundingRect(contours[i]);
		rectangle(result, boundRect[i], Scalar(0, 255, 0), 2);//在result上繪製正外接矩形  
	}
	return result;//返回result  
}

相關推薦

Opencv視訊進行運動物體提取

要求:利用幀差法或背景差分法對視訊進行運動物體的提取。影象處理步驟為:讀取幀、平滑、幀差或背景差、二值化、膨脹、腐蝕。每一步的處理結果都用單獨視窗顯示出來。一、原理 平滑: 平滑也可叫濾波,或者合在一起叫平滑濾波,平滑濾波是低頻增強的空間域濾波技術。它的目的有兩類:一類是模糊

Opencv視訊進行目標檢測

在Opencv3.3版本中集成了deeplearning功能。其實現了對caffe和tensorflow兩個框架的推理,但不支援訓練。本文使用caffe訓練的檔案對目標進行檢測。整個思路是首先讀取視訊檔案,然後載入模型檔案,最後讀取到視訊的每一幀對其進行檢測。

0002-OpenCV影象進行讀取→顯示→儲存的原始碼!

程式碼流程如下: 讀取源影象→轉化化灰度圖→儲存輸出圖片檔案到本地程式碼如下: 程式碼中涉及到的圖片下載地址:http://pan.baidu.com/s/1c14zqik 密碼:lil3影象處理開發資料、影象處理開發需求、影象處理接私活掙零花錢,可以搜尋公眾號"qxsf321",並關注! //

java視訊進行轉碼

這裡有兩個方案: 1.利用國外一個大佬寫的jar包jave,裡面集成了ffmpeg,目前原始碼應該是更新到1.0.2,看了下原始碼應該發現,這個功能還是非常強大的,如果不需要轉碼,只需要獲取下圖片,視訊資訊,更是方便= = 。     JAVE(Java Aud

opencvMat進行排序

由於sort函式和sortId函式是對一行或一列進行排序的,所以對整個需要reshape一下,還要指定是行還是列。 Mat c1 = (Mat_<uchar>(3, 3) << 1, 5, 6, 2, 4, 3, 8, 9, 7); Mat c3 = c1.resha

直播被禁、視訊被刪是何人所為?python與OpenCV視訊實時監測!

  這篇博文的目的是應用計算機視覺和影象處理技術,展示一個條形碼檢測的基本實現。我所實現的演算法本質上基於StackOverflow 上的這個問題,瀏覽程式碼之後,我提供了一些對原始演算法的更新和改進。 學習Python中有不明白推薦加入交流群    

【java小程式】利用ffmpeg視訊進行截圖操作

ffmpeg程式對視訊進行的截圖的命令如下語法如下: ffmpeg.exe -ss 00:00:01 -i spring.mp4 -vframes 1 bb.jpg 00:00:01 擷取視訊圖片的時間。 spring.map4 需要擷取的視訊名稱。 1

OpenCV影象進行mask操作

這裡的mask操作指的是,對一幅影象image,有一個binary的mask影象,image_masked = image & mask 可以採用 Mat的copyTo成員函式,利用mask引數實現。 #include <opencv2/core/core.h

利用FFmpeg視訊進行轉碼壓縮

基本原理 執行FFmpeg的視訊壓縮命令 ffmpeg -i input.mov -b:v 640k output.mp4 #include "jni.h" #include "ffmpeg.h" //視訊轉碼壓縮主函式入口 //ffmpeg_mod.c有

【ARM-Linux開發】【CUDA開發】【視訊開發】關於Linux下利用GPU視訊進行硬體加速轉碼的方案

最近一直在研究Linux下利用GPU進行硬體加速轉碼的方案,折騰了很久,至今沒有找到比較理想的硬加速轉碼方案。似乎網上討論這一方案的文章也特別少,這個過程中也進行了各種嘗試,遇到很多具體問題,以下便對之前所作的一些工作做一些總結和分享,省的時間長了自己也忘記了,也希望後來

利用opencv影象進行二值化處理

利用該方法對圖形進行二值化處理,能夠很好的除去光線對圖片的影響 #include<iostream> #include<opencv2\opencv.hpp> using namespace cv; using namespace

OpenCV學習筆記:運動物體檢測、跟蹤和繪製曲線運動軌跡

一、簡介本文章的起源是本人在做一個專案,用攝像頭識別筆,根據筆的運動,繪製出其軌跡。主要應用到的方法,有運動物體識別、運動物體檢測,以及繪製運動物體的運動軌跡。1、 運動物體的識別方法很多,主要就是要提取相關物體的特徵,主要分為:        (1)各種色彩空間直方圖,利用

opencv影象進行標定

簡介   本篇是使用opencv函式:cvFindChessboardCorners、cvFindCornerSubPix、cvDrawChessboardCorners,來找到、優化並顯示出來標定棋盤 圖片的角點。   關於這三個函式得講解看,可以參考:http://w

【圖像處理】openCV光流法追蹤運動物體

num blank ndis water 不同 h+ width 相關性 ida openCV光流法追蹤運動物體 email:[email protected]/* */ 一、光流簡單介紹 摘自:zouxy09 光流的概念是G

使用OpenCV一系列影象生成視訊avi

直接上程式碼了,過程很簡單,注意路徑,環境:opencv3,macos //功能:將連續圖片合成視訊AVI //注意:檢查路徑是否存在空格,否則影響結果 //注意:根據檔名設定迴圈,何時開始迴圈 #include<opencv2/opencv.hpp> #include<

利用opencv圖片大小進行修改

執行環境:ubuntu16.04 + opencv 2.4.13 + c++ (系統g++版本5.4.0) #include <iostream> #include <fstream> #include <opencv2/core/core.hpp> #inc

Python-OpenCV運動物體檢測

運動物體檢查,在移動目標定位和智慧安防系統中有廣泛的應用,它的實現原理:捕獲連續幀之間的變化情況,將每次捕獲的影象進行對比,然後檢查差值影象中的所有斑塊(顏色相近的地方)。 Demo在實現的過程中,首先需要設定“背景幀”,通過捕獲連續幀,比較“背景幀”與其它幀之間的差異,這種方法檢測結果還是

OpenCV---如何影象進行銳化(11)

附程式碼如下: import cv2 as cv import numpy as np def sharpe(): src = cv.imread("D:/matplotlib/0.jpg") cv.imshow("input",src) lap_5 = np.array

OpenCV--如何影象進行卷積操作(9)

附程式碼如下: import cv2 as cv import numpy as np def blur1(): src = cv.imread("D:/matplotlib/0.jpg") cv.imshow("input",src) blur2 = cv.blur(

OpenCV---如何影象進行雙線性插值運算(7)

附程式碼如下: import cv2 as cv import numpy as np def resize(): src = cv.imread("D:/matplotlib/0.jpg") cv.imshow("input",src) h, w = src.shape