帧差法代码讲课稿
帧间差分法运动目标检测过程及原理
帧间差分法运动目标检测过程及原理帧间差分法是一种常用的视频运动目标检测技术,它通过比较视频序列中相邻帧之间的差异来检测目标的运动。
该方法常用于视频监控、智能交通系统、视频分析等领域。
本文将介绍帧间差分法的运动目标检测过程及原理,以及其在实际应用中的优势和局限性。
一、帧间差分法的原理帧间差分法的原理基于一个简单的假设:如果某个像素点在相邻两帧之间的亮度发生了变化,那么这个像素点所对应的物体就有可能发生了运动。
根据这个假设,可以通过计算相邻两帧之间的像素点亮度差异来确定目标的运动。
在实际应用中,帧间差分法通常使用以下公式来计算相邻两帧的像素点差异:D(x,y,t) = |I(x,y,t) - I(x,y,t-1)|D(x,y,t)表示在时间t时刻的像素点(x,y)的差分值,I(x,y,t)表示在时间t时刻的像素点(x,y)的亮度值,t-1表示时间t之前的时刻。
通过计算相邻两帧之间的像素点差异,可以得到一副差分图像,该图像中像素点的数值表示了该点在帧间差分中的差异程度。
接着,可以对差分图像进行阈值处理,将高于阈值的像素点标记为目标像素点,从而实现目标的运动检测。
帧间差分法的运动目标检测过程包括以下几个步骤:1. 视频帧获取和预处理首先需要从视频流中获取连续的视频帧,并对每一帧进行预处理,包括灰度化、降噪、边缘检测等操作,以便后续运动目标检测的准确性和鲁棒性。
2. 帧间差分计算对相邻两帧的视频进行帧间差分计算,得到差分图像。
可以使用绝对差值、差分平均值等方式来计算差分图像。
3. 阈值处理对差分图像进行阈值处理,将高于阈值的像素点标记为目标像素点。
阈值的选择是帧间差分法中需要仔细考虑的一个关键问题,合适的阈值能够更好地区分目标和背景,提高检测准确度。
4. 目标区域提取通过连通域分析、形态学处理等方法,将标记为目标像素点的区域进行进一步的提取和分割,得到目标的位置信息。
5. 目标跟踪和输出对提取得到的目标区域进行目标跟踪和输出,可以采用卡尔曼滤波、光流算法等方法来对目标进行跟踪,最终实现目标的运动检测和输出。
【目标追踪】三帧差法原理及实现
【目标追踪】三帧差法原理及实现三帧差法原理及实现•(一)帧差法原理及实现:•(二)帧差法存在的问题:•(三)三帧差法的原理:•(四)三帧差法的实现代码:•(五)视频中的目标追踪效果:(一)帧差法原理及实现:这里可以看一下我的这篇博客,这里就不赘述了:【目标追踪】python帧差法原理及其实现(二)帧差法存在的问题:运动物体本身颜色相近时,会出现较大的空洞。
位置变化缓慢时,难以检测到目标。
对光线非常敏感。
(三)三帧差法的原理:三帧差法的关键是,不再仅仅采用相邻的两帧图片作差查找运动目标,而是在相邻三帧图片的两张帧差图中取“与”操作,即:(四)三帧差法的实现代码:(具体处理和代码解析还是推荐看一下我的上一篇博客:【目标追踪】python帧差法原理及其实现)代码:import cv2import numpy as npfrom nms import py_cpu_nmsfrom time import sleepclass Detector(object):def __init__(self, name='my_video', frame_num=10, k_size=7, color=(0, 255, 0)): = nameself.color = colorself.nms_threshold = 0.3self.time = 1/frame_num # 频率self.es = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (k_size, k_size))def catch_video(self, video_index=0, k_size=7,iterations=3, threshold=20, bias_num=1,min_area=360, show_test=True, nms=True,logical='or'):# video_index:摄像头索引(数字)或者视频路径(字符路径)# k_size:中值滤波的滤波器大小# iteration:腐蚀+膨胀的次数,0表示不进行腐蚀和膨胀操作# threshold:二值化阙值# bias_num:计算帧差图时的帧数差# min_area:目标的最小面积# show_test:是否显示二值化图片# nms:是否进行非极大值抑制# logical:三帧差取or或andlogical = logical.lower()if not bias_num > 0:raise Exception('bias_num must > 0')if isinstance(video_index, str):is_camera = False# 如果是视频,则需要调整帧率else:is_camera = Truecap = cv2.VideoCapture(video_index) # 创建摄像头识别类if not cap.isOpened():# 如果没有检测到摄像头,报错raise Exception('Check if the camera is on.')frame_num = 0previous = []while cap.isOpened():catch, frame = cap.read() # 读取每一帧图片if not catch:raise Exception('Unexpected Error.')if frame_num < bias_num:value = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) previous = [value]*bias_numframe_num += 1raw = frame.copy()gray1 = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)gray1 = cv2.absdiff(gray1, previous[0])gray1 = cv2.medianBlur(gray1, k_size)_, mask1 = cv2.threshold(gray1, threshold, 255, cv2.THRESH_BINARY)gray2 = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)gray2 = cv2.absdiff(gray2, previous[1])gray2 = cv2.medianBlur(gray2, k_size)_, mask2 = cv2.threshold(gray2, threshold, 255, cv2.THRESH_BINARY)if logical == 'or':mask = (np.logical_or(mask1, mask2) + 0)elif logical == 'and':mask = (np.logical_and(mask1, mask2) + 0)else:raise Exception('Logical must be \'OR\' or \'AND\'')mask = (mask * 255).astype(np.uint8)mask = cv2.dilate(mask, self.es, iterations)mask = cv2.erode(mask, self.es, iterations)_, cnts, _ = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)bounds = self.nms_cnts(cnts, mask, min_area, nms=nms)for b in bounds:x, y, w, h = bthickness = (w*h)//min_areathickness = thickness if thickness <= 3 else 3thickness = thickness if thickness >= 1 else 1cv2.rectangle(frame, (x, y), (x+w, y+h), self.color, thickness) if not is_camera:sleep(self.time)cv2.imshow(, frame) # 在window上显示图片if show_test:cv2.imshow(+'_frame', mask) # 边界value = cv2.cvtColor(raw, cv2.COLOR_BGR2GRAY)previous = self.pop(previous, value)cv2.waitKey(10)if cv2.getWindowProperty(, cv2.WND_PROP_AUTOSIZE) < 1:# 点x退出breakif show_test and cv2.getWindowProperty(+'_frame', cv2.WND_PROP_AUTOSIZE) < 1:# 点x退出break# 释放摄像头cap.release()cv2.destroyAllWindows()def nms_cnts(self, cnts, mask, min_area, nms=True):# 对检测到的边界框使用非极大值抑制bounds = [cv2.boundingRect(c) for c in cnts if cv2.contourArea(c) > min_area]if len(bounds) == 0:return []if not nms:return boundsscores = [self.calculate(b, mask) for b in bounds]bounds = np.array(bounds)scores = np.expand_dims(np.array(scores), axis=-1)keep = py_cpu_nms(np.hstack([bounds, scores]), self.nms_threshold)return bounds[keep]def calculate(self, bound, mask):x, y, w, h = boundarea = mask[y:y+h, x:x+w]pos = area > 0pos = pos.astype(np.float)# 得分应与检测框大小也有关系score = np.sum(pos)/(w*h)return scoredef pop(self, l, value):l.pop(0)l.append(value)return lif __name__ == "__main__":detector = Detector(name='test')detector.catch_video('./test.avi', bias_num=2, iterations=1,k_size=5, show_test=True, min_area=360, nms=False) (五)视频中的目标追踪效果:。
opencv 帧差法 抖动
opencv 帧差法抖动## OpenCV Frame Differencing and Jittering.Frame differencing is a technique used in computer vision to detect changes in a sequence of images. It involves computing the absolute difference between two consecutive frames and thresholding the result to identify significant changes. This technique is often used for motion detection, object tracking, and other applications that require detecting changes in a video stream.However, frame differencing can sometimes produce noisy or jittery results, especially when the camera is moving or the scene contains moving objects. This is because thepixel values in the difference image can be affected by noise, motion blur, and other factors.To reduce jitter in frame differencing, several techniques can be used:1. Smoothing: Applying a Gaussian blur or other smoothing filter to the input frames before computing the difference can help reduce noise and jitter.2. Median filtering: Median filtering is a non-linear filtering technique that can effectively remove isolated noise pixels while preserving edges. Applying a medianfilter to the difference image can help reduce jitter caused by noise.3. Morphological operations: Morphological operations such as erosion and dilation can be used to remove small noise regions and fill in gaps in the difference image. This can help reduce jitter caused by motion blur.4. Temporal filtering: Temporal filtering techniques such as Kalman filtering or particle filtering can be used to smooth out the difference image over time. This can help reduce jitter caused by camera motion or moving objects.Here is an example of how to reduce jitter in frame differencing using OpenCV in Python:python.import cv2。
三帧差分
这几天研究了下三帧差法做物体检测。
三帧差法的具体算法如下。
提取连续的三帧图像,I(k-1),I(k),I(k+1) 。
(1) d(k,k-1) [x,y] = | I(k)[x,y] - I(k-1)[x,y] |;d(k,k+1)[x,y] = | I(k+1)[x,y] - I(k)[x,y] |;(2) b(k,k-1)[x,y] = 1; if d(k,k-1) [x,y] >= T;b(k,k-1)[x,y] = 0; if d(k,k-1) [x,y] < T;b(k+1,k)[x,y] = 1 if d(k+1,k) [x,y] >= T;b(k+1,k)[x,y] = 0 if d(k+1,k) [x,y] < T;(3) B(k)[x,y] = 1 ; if b(k,k-1)[x,y] && b(k+1,k)[x,y] == 1 ;B(k)[x,y] = 0 ; if b(k,k-1)[x,y] && b(k+1,k)[x,y] ==0 ;到了这里,比较关键的就是第2步的阈值T的选取问题,单纯用otsu算法分割貌似效果不太好,如果手动设置一个较小的值(如10)效果还可以,但手动设置有一定的限制性。
接下来要研究局部阈值的选取。
用otsu取阈值实现的一个三分差法代码。
效果不是很好。
#include "highgui.h"#include "cv.h"#include "cxcore.h"#include "cvaux.h"#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <queue>#include <vector>#include <windows.h>using namespace std;//#pragma comment(lib, "highgui200.lib")//#pragma comment(lib, "cv200.lib")//#pragma comment(lib, "cxcore200.lib")//#pragma comment(lib, "cvaux200.lib")#define GET_IMAGE_DATA(img, x, y) ((uchar*)(img->imageData + img->widthStep * (y)))[x]int T = 10;int Num[300];int Sum[300];void InitPixel(IplImage * img, int &_low, int &_top){memset(Num,0,sizeof(Num));memset(Sum,0,sizeof(Sum));_low = 255;_top = 0;for(int i = 0;i < img->height;i++){for(int j = 0;j < img->width;j++){int temp = ((uchar*)(img->imageData + img->widthStep*i))[j];if(temp < _low)_low = temp;if(temp > _top)_top = temp;Num[temp] += 1;}}for(int i = 1 ; i < 256 ; i++){Sum[i] = Sum[i-1]+ i*Num[i];Num[i] += Num[i-1];}}int otsu (IplImage *img){int _low,_top,mbest=0;float mn = img->height*img->width;InitPixel(img,_low,_top);float max_otsu = 0;mbest = 0;if( _low == _top)mbest = _low;else{for(int i = _low; i< _top ; i++){float w0 = (float)((Num[_top]-Num[i]) / mn);float w1 = 1 - w0;float u0 = (float)((Sum[_top]-Sum[i])/(Num[_top]-Num[i]));float u1 = (float)(Sum[i]/Num[i]);float u = w0*u0 + w1*u1;float g = w0*(u0 - u)*(u0 - u) + w1*(u1 - u)*(u1 - u);if( g > max_otsu){mbest = i;max_otsu = g;}}}return mbest;}int main(){int ncount=0;IplImage *image1=NULL;IplImage *image2=NULL;IplImage *image3=NULL;IplImage *Imask =NULL;IplImage *Imask1=NULL;IplImage *Imask2=NULL;IplImage *Imask3=NULL;IplImage *mframe=NULL;CvCapture *capture = cvCreateFileCapture("E:\\Motion\\IndoorGTTest2.avi");//CvCapture *capture = cvCreateCameraCapture(0);cvNamedWindow("src");cvNamedWindow("dst");cvNamedWindow("Imask1");cvNamedWindow("Imask2");cvNamedWindow("Imask3");//cvCreateTrackbar("T","dst",&T,255,0);while(mframe=cvQueryFrame(capture)){DWORD start=GetTickCount();if(ncount>1000000000)ncount=100;ncount+=1;if(ncount==1){image1=cvCreateImage(cvGetSize(mframe),IPL_DEPTH_8U,1);image2=cvCreateImage(cvGetSize(mframe),IPL_DEPTH_8U,1);image3=cvCreateImage(cvGetSize(mframe),IPL_DEPTH_8U,1);Imask =cvCreateImage(cvGetSize(mframe),IPL_DEPTH_8U,1);Imask1=cvCreateImage(cvGetSize(mframe),IPL_DEPTH_8U,1);Imask2=cvCreateImage(cvGetSize(mframe),IPL_DEPTH_8U,1);Imask3=cvCreateImage(cvGetSize(mframe),IPL_DEPTH_8U,1);cvCvtColor(mframe,image1,CV_BGR2GRAY);}if(ncount==2)cvCvtColor(mframe,image2,CV_BGR2GRAY);if(ncount>=3){if(ncount==3)cvCvtColor(mframe,image3,CV_BGR2GRAY);else{cvCopy(image2,image1);cvCopy(image3,image2);cvCvtColor(mframe,image3,CV_BGR2GRAY);}cvAbsDiff(image2,image1,Imask1);cvAbsDiff(image3,image2,Imask2);//cvShowImage("Imask1",Imask1);//cvShowImage("Imask2",Imask2);int mbest1 = otsu(Imask1);cvSmooth(Imask1, Imask1, CV_MEDIAN);cvThreshold(Imask1,Imask1,mbest1, 255, CV_THRESH_BINARY);int mbest2 = otsu(Imask2);cvSmooth(Imask2,Imask2, CV_MEDIAN);cvThreshold(Imask2,Imask2,mbest2, 255, CV_THRESH_BINARY);cout<<mbest1<<" "<<mbest2<<endl;cvAnd(Imask1,Imask2,Imask);/*cvErode(Imask, Imask);cvDilate(Imask,Imask);*/DWORD finish=GetTickCount();// cout<<finish-start<<"ms"<<endl;cvShowImage("src",image2);cvShowImage("dst",Imask);}char c = cvWaitKey(30);if(c==27)break;}return 0;}\#include "stdafx.h"#include "cv.h"#include "cxcore.h"#include "highgui.h"#include "stdio.h"int main(int argc, _TCHAR* argv[]){IplImage* pFrame = NULL;IplImage* pFrImg1 = NULL;IplImage* pFrImg2 = NULL;IplImage* pFrImg3 = NULL;IplImage* result1 = NULL;IplImage* result2 = NULL;IplImage* result = NULL;IplImage* tempImg1 = NULL;CvSize size;CvMat* pFrMat1 = NULL;CvMat* pFrMat2 = NULL;CvMat* pFrMat3 = NULL;CvMat* reMat1 = NULL;CvMat* reMat2 = NULL;CvMat* reMat = NULL;CvMat* tempMat1 = NULL;CvCapture* pCapture = NULL;int nFrmNum = 0;char* reWin = "effect" + nFrmNum;cvNamedWindow("video", 1);cvNamedWindow("effect", 1);cvMoveWindow("video", 0, 0);cvMoveWindow("effect", 400, 400);if( argc != 1 ){fprintf(stderr, "Usage: bkgrd <video_file_name>\n"); return -1;}if( !(pCapture = cvCaptureFromFile("F:\\仿真结果\\B vector.avi"))){fprintf(stderr, "Can not open video file %s\n", "F:\\仿真结果\\B vector.avi");return -2;}while(pFrame = cvQueryFrame( pCapture )){nFrmNum++;if ( nFrmNum > 500){nFrmNum = 0;break;}}printf("视频帧数:%d\n",nFrmNum);cvSetCaptureProperty(pCapture,CV_CAP_PROP_POS_FRAMES,);//第一帧pFrame = cvQueryFrame( pCapture );if(nFrmNum>2){pFrImg1 = cvCreateImage(cvGetSize(pFrame),IPL_DEPTH_8U, 1);pFrImg2 = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1);pFrImg3 = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1);result1 = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1);result2 = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1);result = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1);pFrMat1 = cvCreateMat(pFrame->height, pFrame->width, CV_8UC1);pFrMat2 = cvCreateMat(pFrame->height, pFrame->width, CV_8UC1);pFrMat3 = cvCreateMat(pFrame->height, pFrame->width, CV_8UC1);reMat1 = cvCreateMat(pFrame->height, pFrame->width,CV_8UC1);reMat2 = cvCreateMat(pFrame->height, pFrame->width,CV_8UC1);reMat = cvCreateMat(pFrame->height, pFrame->width,CV_8UC1);size = cvSize(pFrame->width, pFrame->height);tempImg1 = cvCreateImage( cvSize((size.width & -2)/2, (size.height & -2)/2), 8, 1 );}else{printf("帧数小于3!\n");return -1;}//先读取两帧cvCvtColor(pFrame, pFrImg1, CV_BGR2GRAY);cvConvert(pFrImg1, pFrMat1);pFrame = cvQueryFrame( pCapture );cvCvtColor(pFrame, pFrImg2, CV_BGR2GRAY);cvConvert(pFrImg2, pFrMat2);int count = 2;while((pFrame = cvQueryFrame( pCapture ))){count++;cvCvtColor(pFrame, pFrImg3, CV_BGR2GRAY);cvConvert(pFrImg3, pFrMat3);cvSmooth(pFrMat1, pFrMat1, CV_GAUSSIAN , 3, 1);cvSmooth(pFrMat2, pFrMat2, CV_GAUSSIAN , 3, 1);cvSmooth(pFrMat3, pFrMat3, CV_GAUSSIAN , 3, 1);//当前帧跟前一帧相减cvAbsDiff(pFrMat2, pFrMat1, reMat1);cvAbsDiff(pFrMat3, pFrMat2, reMat2);//二值化前景图cvThreshold(reMat1, result1, 60.0, 255.0, CV_THRESH_BINARY); cvThreshold(reMat2, result2, 60.0, 255.0, CV_THRESH_BINARY);///cvAdaptiveThreshold( reMat1, result1, 255,CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 5, 5 );//cvAdaptiveThreshold( reMat2, result2, 255,CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 5, 5 );//两个帧差值相与cvAnd(result1,result2,result,0);//使用Gaussian金字塔分解对输入图像向下采样,输出图像的高度和宽度应是输入图像的一半cvPyrDown(result, tempImg1, 7 );//对输入图像进行膨胀cvDilate(result, result, 0, 1);//使用Gaussian金字塔分解对输入图像向上采样,输出图像的高度和宽度应是输入图像的2倍cvPyrUp(tempImg1, result, 7 );//cvErode(result, result, 0, 1);//cvDilate(result, result, 0, 1);//cvPyrDown(result, tempImg1, 7 );//cvPyrUp(tempImg1, result, 7 );cvErode(result, result, 0, 3);cvDilate(result, result, 0, 3);//翻转图像,使其正立显示cvFlip(result, NULL, 0);cvShowImage("video", pFrame);cvShowImage("effect", result);cvCopy(pFrMat2, pFrMat1, NULL);cvCopy(pFrMat3, pFrMat2, NULL);if( cvWaitKey( 20 ) >= 0 )break;printf("\nFrame = %d\n", count);}//销毁窗口cvDestroyWindow("video");//cvDestroyWindow(reWin);cvDestroyWindow("effect");//释放图像和矩阵cvReleaseImage(&pFrImg1);cvReleaseImage(&pFrImg2);cvReleaseImage(&result1);cvReleaseImage(&result2);cvReleaseImage(&result);cvReleaseImage(&tempImg1);cvReleaseMat(&pFrMat1);cvReleaseMat(&pFrMat2);cvReleaseMat(&reMat1);cvReleaseMat(&reMat2);cvReleaseMat(&reMat);cvReleaseCapture(&pCapture); return 0;}。
帧差法
帧差法近些年来, 世界各地的学者们针对视频图像中的运动目标检测与跟踪问题做了大量而深入的研究, 提出了很多极其有效的算法难点主要在于视频序列中有各种不同的干扰因素, 这些因素主要包括: 光线明暗的变化、成像传感器本身的固有噪声、运动目标自身的形变或位移变化、背景中的杂波、运动目标的互相遮挡或者自遮挡等, 这些问题还有待于做进一步的研究。
目前, 常用的运动目标检侧方法有: 光流法、背景差分法和帧间差分法。
1.光流法光流法能够检测出运动目标较完整的运动信息, 不需要预先知道场景的任何信息, 能够较好的处理运动背景的情况, 并且可以用于摄像机运动的情况, 适用于帧间位移较大的情况。
但是由于透明性、阴影、多光源、遮挡和噪声等原因,利用光流法进行运动物体检测时, 计算量很大, 无法保证实时性和实用性, 故难以应用到实时系统, 同时对噪声比较敏感, 计算结果精度较低, 难以得到运动目标的精确边界。
2 .背景差分法操作简单, 能够提供完全的特征数据, 但对目标的检测能力较低, 尤其对天气、光照等噪声的影响极其敏感,3T 为预先设定的阈值, 可根据经验选取T , 若选取过大, 则检测的目标则可能出现较大的空洞甚至漏检, 若T 选取过小, 将出现大量噪声。
由于帧间差分法的不足, 就有学者提出了三帧差法, 三帧差法充分考虑了动像素的时间相关性, 对动态检测比较灵敏, 对随机噪声也有很好的抑制作用,但也存在一定缺陷, 即差分图像的检测阈值需手动设定, 大多数情况下只能依据实践经验。
三帧差分法的关键是选取合适的阈值对图像进行二值化。
运动目标自动跟踪是指对目标进行连续的检测并确定其运动轨迹[1].在视频监控领域中,目标智能识别与自动跟踪系统是近几年来的研究重点.在军事、国防和工业等领域有着广泛的应用前景.当前运动目标的检测方法主要有3类:光流法[2]、帧间差分法[3]和背景差分法[4].背景差分法具有简单、运算速度快等诸多优点,使得该法作为运动目标检测的基本方法被普遍采用.但该法暴露出若干问题:一种是因外部条件引起的,如对光线的变化、噪声等造成差分图像检测精度不高,甚至失效;另一种是由差分图像法本身内在局限引起的,主要有空洞[5]、拖影,以及运动目标被拉长等现象.光流法[6]虽然能够适用于静态背景和动态背景两种环境,有较好的适应性,但是其计算复杂度高,运算时间开销很大,不能满足实时性的要求.帧差法[7]比较简单,实时性高,它主要包括减背景方法和相邻帧相减法,即三帧差分法.减背景方法存在背景获取困难、受光照影响严重且更新困难等问题.三帧差分法受光照和阴影影响较小.笔者对三帧差分法进行改进,提出了一种简单有效的运动目标检测方法.1 运动目标实时跟踪系统1. 1 帧差法的基本原理帧间差分法的基本原理就是将前后两帧图像对应像素点的灰度值相减,在环境亮度变化不大的情况下,如果对应像素灰度相差很小,可以认为此处物是静止的;如果图像区域某处的灰度变化很大,可以认为这是由于图像中运动物体引起的,将这些区域标记下来,利用这些标记的像素区域,就可以求出运动目标在图像中的位置.一般采用的帧差法是在连续的图像序列[8]中2个或3个相邻帧间采用基于像素的时间差分并且阈值化来提取图像的运动区域.该运动目标实时跟踪系统是采用三帧差分来进行运动目标检测,这种方法不仅能提高运动目标检测[9]的速度,而且提高了所检测运动目标图像的完整性.均值滤波均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标象素为中心的周围8个像素,构成一个滤波模板,即去掉目标像素本身),再用模板中的全体像素的平均值来代替原来像素值。
《数字视频处理及应用》课件第4章
在进行长时间的视频应用时,由于背景静止标准定义
的广泛性,背景物体会发生一定的变化,因此,高斯混合
模型需要对各分布模型进行更新。对于每个像素值,首先
应该检查它是否匹配混合模型的某个模型,检测方法如下:
for k 1 to K
该方法的基本思想是将图像分为背景和前景,对背景进 行建模,然后把当前帧与背景模型进行逐像素的比较,那些 与背景模型符合的像素被标记为背景像素,不符合的像素被 标记为前景像素,同时更新背景模型。最简单的背景模型是 时间平均图像,大多数研究人员目前都致力于开发不同的背 景模型,以减少动态场景变化对运动分割的影响。
B
arg
min b
b
k
k 1
T
(4-9)
其中, T是最小模型个数的度量。如果T选得比较小,背景
模型会被认为是单峰的; 如果T选得比较大,背景模型会被
认为是多峰的。
算法运行时,每读入一帧样本,若存在分布Ci与样本xj 相匹配,即满足xj∈[μi-3σi,μi+3σi], 则认为当前像素为 背景点,否则就判为前景点。
4.1.3 背景差法 背景差法将当前帧和不断更新的参考模型进行比较,
与模型不一致的区域被标识为运动区域。背景差法是目前 运动目标检测比较常用的方法,特别是在背景相对静止的 场合。背景差法复杂度不高,但对动态场景中由光照等自 然条件引起的变化比较敏感,因此如何将这些变化标记为 背景是学者们一直研究的课题。
I(x+dx,y+dy,t+dt)=I(x,y,t) 应用泰勒展开式,当dx,dy,dt很小时,
(4-3)
I
x dx, y dy,t dt
I
x,
y,t
I x
帧差法原理
帧差法原理帧差法是一种常用的视频图像处理算法,它通过比较相邻帧之间的像素变化来检测视频中的运动物体。
该算法广泛应用于视频监控、智能交通、动态目标追踪等领域。
下面我们将详细介绍帧差法的原理和实现过程。
一、帧差法原理帧差法是一种以运动物体像素变化为基础,通过像素点连续性つ计算出目标位置和大小的一种方法。
它的基本原理是利用相邻帧之间的差异信息计算出图像中的运动物体,并对其进行分析和处理。
帧差法的基本步骤如下:1. 提取视频帧首先需要从视频中提取帧数据,这一过程称为视频帧提取。
2. 帧间差分利用相邻帧像素信息的差异计算出差分图像,常见的通过前一帧和当前帧的信息计算出它们之间的像素差异,得到的差分图像可以表示为:d(x, y, t) = |I(x, y, t)-I(x, y, t-1)|其中,d表示差分图像,x,y表示像素坐标,t表示帧序号,I表示图像。
显然,通过差分图像我们可以得到相邻帧之间存在的运动物体像素变化。
3. 去除噪声由于摄像头噪声,运动物体遮挡、变形等因素的干扰,我们需要对差分图像进行处理,去除噪声。
这可以通过一些滤波算法来完成,例如中值滤波、高斯滤波等。
4. 运动物体检测差分图像中的像素变化可以看作是运动物体的轮廓线,我们需要进一步将这些轮廓线进行分析,得到运动目标的位置和大小。
这可以通过一些形态学分析算法来完成,例如连通域分析、形态学操作等。
二、帧差法实现Python是一个很好的图像处理语言,它有着丰富的图像处理库及工具,如OpenCV、Matplotlib等。
下面我们将以Python为例,简单介绍帧差法的实现过程。
1. 导入库首先需要导入Python图像处理库OpenCV的相关工具。
OpenCV是一个广泛使用的图像处理库,它提供了各种图像处理函数和算法的实现工具。
import cv22. 视频帧提取在视频帧提取的过程中,我们需要指定视频文件,然后从中提取帧数据。
cap = cv2.VideoCapture(0)while True:ret, frame = cap.read()cv2.imshow('frame', frame)if cv2.waitKey(1) & 0xFF == ord('q'):breakcap.release()cv2.destroyAllWindows()这里我们使用VideoCapture函数打开摄像头,循环读取摄像头的每一帧数据,并使用imshow函数将帧数据显示在窗口中,当按下q键时退出循环。
图像处理算法之帧间差分法
图像处理算法之帧间差分法
1. 基本原理
帧间差分法是⼀种通过对视频图像序列的连续两帧图像做差分运算获取运动⽬标轮廓的⽅法。
当监控场景中出现异常⽬标运动时,相邻两帧图像之间会出现较为明显的差别,两帧相减,求得图像对应位置像素值差的绝对值,判断其是否⼤于某⼀阈值,进⽽分析视频或图像序列的物体运动特性。
其数学公式描述如下:
D(x,y)为连续两帧图像之间的差分图像,I(t)和I(t-1)分别为t 和t-1时刻的图像,T 为差分图像⼆值化时选取的阈值,D(x,y) = 1表⽰前景,D(x,y)= 0表⽰背景。
2. 优缺点
优点:算法实现简单,程序设计复杂度低,运⾏速度快;动态环境⾃适应性强,对场景光线变化不敏感。
缺点:“空洞”现象(运动物体内部灰度值相近);“双影”现象(差分图像物体边缘轮廓较粗);不能提取出运动对象的完整区域,仅能提取轮廓;算法效果严重依赖所选取的帧间时间间隔和分割阈值。
3. 三帧差法
⽬的:解决帧间差分法的“双影”问题。
算法步骤如下:
可在⼀定程度上消除帧间差分法的“双影”现象。
帧间差分法 车辆测速 代码
帧间差分法车辆测速代码(实用版)目录1.帧间差分法概述2.车辆测速的现状与需求3.帧间差分法在车辆测速中的应用4.帧间差分法车辆测速的代码实现5.总结正文1.帧间差分法概述帧间差分法(Frame Difference Method)是一种基于运动目标检测的视频处理技术。
其基本原理是通过比较连续两帧或多帧图像之间的差异,从而检测出运动目标的位置和速度。
这种方法具有计算简单、实时性好、抗干扰性强等优点,被广泛应用于车辆测速等领域。
2.车辆测速的现状与需求随着我国交通事业的快速发展,车辆测速技术在交通安全和管理中发挥着越来越重要的作用。
目前,市场上的车辆测速方法主要有雷达测速、激光测速、线圈测速等。
这些方法虽然在一定程度上能够满足实际需求,但仍存在一定的局限性,如受环境影响大、精度不高、易受干扰等。
因此,研究和开发一种更为精确、可靠、实用的车辆测速方法具有重要的现实意义。
3.帧间差分法在车辆测速中的应用帧间差分法作为一种基于图像处理的车辆测速技术,具有较强的实用价值。
它通过对连续帧图像的差分处理,可以有效检测出运动目标的位置和速度,从而实现对车辆的精确测速。
帧间差分法具有计算简单、实时性好、抗干扰性强等优点,能够在各种复杂环境下稳定工作,满足车辆测速的实际需求。
4.帧间差分法车辆测速的代码实现以下是一个简单的 Python 代码示例,使用 OpenCV 库实现帧间差分法车辆测速:```pythonimport cv2import numpy as npdef frame_difference(image1, image2):gray1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)gray2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)absdiff = cv2.absdiff(gray1, gray2)thresh = cv2.threshold(absdiff, 25, 255,cv2.THRESH_BINARY)return threshdef vehicle_speed_measurement(video_path):# 读取视频cap = cv2.VideoCapture(video_path)if not cap.isOpened():print("无法打开视频文件")returnwhile True:ret, frame = cap.read()if not ret:break# 差分处理prev_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) gray_diff = frame_difference(prev_frame, frame)# 运动目标检测contours, hierarchy = cv2.findContours(gray_diff,cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)for contour in contours:# 计算车辆速度#...(此处需要根据实际需求和车辆图像特征进行速度计算)# 显示结果cv2.imshow("Vehicle Speed Measurement", frame)if cv2.waitKey(1) & 0xFF == ord("q"):breakcap.release()cv2.destroyAllWindows()if __name__ == "__main__":video_path = "path/to/your/video.mp4"vehicle_speed_measurement(video_path)```5.总结帧间差分法作为一种基于图像处理的车辆测速技术,具有计算简单、实时性好、抗干扰性强等优点,能够满足车辆测速的实际需求。
三帧差分法
三帧差分法的问题大家帮忙看看这个三帧差分法的代码哪里出了问题?参照论坛上的相邻帧差法,改造成三帧差分法。
clc;clear;targetavi='SampleVideo.avi'; %%原始视频resultavi='result.avi'; %%检测结果视频%%%%%%%%%%%%%%%%%%%%%%读取视频mov=aviread(targetavi);%mov=mmreader(targetavi);fnum=size(mov,2);%%%%%%%%%%%%%%%%%%%%%%建立结果视频aviobj = avifile(resultavi);aviobj.Quality = 100;aviobj.Fps = 15;%pression='Indeo5';pression='None';%%%%%%%%%%%%%%%%%%%%%%帧间差分法for i=2:fnumx=mov(i-1).cdata(:,:,:);y=mov(i).cdata(:,:,:);z=mov(i+1).cdata(:,:,:);m=rgb2gray(x);m=medfilt2(m);n=rgb2gray(y);n=medfilt2(n);o=rgb2gray(z);o=medfilt2(o);q=im2double(n);w=im2double(m);p=im2double(o);c=q-w;%%前两帧差分b=p-q;%%后两帧差分t=40; %%阈值,此值可以调节t=t/256;%%转化为double型数据k=find(abs(c)>=t);%%find函数作用是找到图c中的值大于t的点坐标d=find(abs(b)>=t);%%find函数作用是找到图b中的值大于t的点坐标c(k)=255;%%二值化的一b(d)=255;k=find(abs(c)<t);d=find(abs(b)<t);c(k)=0;%%二值化的零b(d)=0;f=c&b;imshow(f);adata=cat(3,f,f,f);%%灰度图像生成视频必加此句aviobj = addframe(aviobj,adata);%%生成视频hold on;drawnow;hold off;endaviobj=close(aviobj);显示的错误提示:??? Error using ==> avifile.addframe>getInputType at 384Invalid input argument. Each frame must be a numeric matrix, a MA TLAB movie structure, or a handle to a figureor axis.Error in ==> avifile.addframe at 58inputType = getInputType(varargin{i});Error in ==> ThreeFrameDifference at 61aviobj = addframe(aviobj,adata);%%生成视频TOPMatlab中文函数大全上线,欢迎大家完善!点。
帧间差分法 车辆测速 代码
帧间差分法车辆测速代码帧间差分法是一种常用的车辆测速方法,它通过分析连续视频帧之间的差异来实现车辆的速度计算。
本文将详细介绍帧间差分法的原理、步骤以及应用,并结合代码示例进行解析。
首先,我们来了解一下帧间差分法的原理。
在车辆测速中,通常使用摄像机来获取车辆经过的视频图像。
帧间差分法利用视频中相邻帧之间的像素差异来计算车辆速度。
具体来说,它通过比较相邻帧中相同位置的像素值来检测运动对象(即车辆)在图像中的位置变化,进而计算出车辆的移动速度。
接下来,我们来了解一下帧间差分法的步骤。
首先,需要获取视频输入并将其转换为一系列连续的图像帧。
然后,选取两个相邻的帧,并将它们转换为灰度图像。
接着,将这两个灰度图像之间的像素进行差分运算,得到一个差分图像。
在这个差分图像中,车辆的区域将呈现明显的像素变化。
最后,根据车辆在差分图像中的位置变化以及已知的帧间时间间隔,即可计算出车辆的速度。
下面,我们将通过代码示例来演示帧间差分法的具体实现过程。
假设我们已经获取了一段视频,并将其转换为一系列连续的图像帧。
我们将使用Python编写代码来进行车辆测速。
首先,我们需要导入所需的库和模块。
我们将使用OpenCV来处理图像和视频,以及NumPy来进行数组操作。
import cv2import numpy as np```接下来,我们定义一个函数来对相邻两帧之间的像素进行差分运算,并返回差分图像。
```pythondef frame_difference(frame1, frame2):gray1 = cv2.cvtColor(frame1, cv2.COLOR_BGR2GRAY) # 将帧转换为灰度图像gray2 = cv2.cvtColor(frame2, cv2.COLOR_BGR2GRAY)diff = cv2.absdiff(gray1, gray2) # 计算帧差_, diff = cv2.threshold(diff, 30, 255,cv2.THRESH_BINARY) # 二值化图像return diff```然后,我们定义一个函数来计算车辆的速度。
三帧差法
#include "stdafx.h"#include "cv.h"#include "cxcore.h"#include "highgui.h"#include "stdio.h"int main(int argc, _TCHAR* argv[]) {IplImage* pFrame = NULL;IplImage* pFrImg1 = NULL;IplImage* pFrImg2 = NULL;IplImage* pFrImg3 = NULL;IplImage* result1 = NULL;IplImage* result2 = NULL;IplImage* result = NULL;IplImage* tempImg1 = NULL;CvSize size;CvMat* pFrMat1 = NULL;CvMat* pFrMat2 = NULL;CvMat* pFrMat3 = NULL;CvMat* reMat1 = NULL;CvMat* reMat2 = NULL;CvMat* reMat = NULL;CvMat* tempMat1 = NULL;CvCapture* pCapture = NULL;int nFrmNum = 0;char* reWin = "effect" + nFrmNum;cvNamedWindow("video", 1);cvNamedWindow("effect", 1);cvMoveWindow("video", 0, 0);cvMoveWindow("effect", 400, 400);if( argc != 1 ){fprintf(stderr, "Usage: bkgrd <video_file_name>\n");return -1;}if( !(pCapture = cvCaptureFromFile("视频3.avi"))){fprintf(stderr, "Can not open video file %s\n", "视频3.avi");return -2;}while(pFrame = cvQueryFrame( pCapture )){nFrmNum++;if ( nFrmNum > 500){nFrmNum = 0;break;}}while(pFrame = cvQueryFrame( pCapture )){nFrmNum++;//如果是第一帧,需要申请内存,并初始化if(nFrmNum == 1){pFrImg1 = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1); pFrImg2 = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1); pFrImg3 = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1);result1 = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1); result2 = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1);result = cvCreateImage(cvGetSize(pFrame), IPL_DEPTH_8U, 1);pFrMat1 = cvCreateMat(pFrame->height, pFrame->width, CV_8UC1); pFrMat2 = cvCreateMat(pFrame->height, pFrame->width, CV_8UC1); pFrMat3 = cvCreateMat(pFrame->height, pFrame->width, CV_8UC1); reMat1 = cvCreateMat(pFrame->height, pFrame->width, CV_8UC1); reMat2 = cvCreateMat(pFrame->height, pFrame->width, CV_8UC1); reMat = cvCreateMat(pFrame->height, pFrame->width, CV_8UC1);tempMat1 = cvCreateMat(pFrame->height, pFrame->width, CV_8UC1);size = cvSize(pFrame->width, pFrame->height);tempImg1 = cvCreateImage( cvSize((size.width & -2)/2, (size.height & -2)/2), 8, 1 );cvConvert(pFrImg1, pFrMat1);cvConvert(pFrImg1, pFrMat2);cvConvert(pFrImg1, pFrMat3);cvConvert(pFrImg1, reMat1);cvConvert(pFrImg1, reMat2);//cvConvert(pFrame1, reMat);}else{cvCvtColor(pFrame, pFrImg3, CV_BGR2GRAY);cvConvert(pFrImg3, pFrMat3);//cvCvtColor(pFrImg3, pFrImg2, CV_BGR2GRAY);pFrImg2 = pFrImg3;cvConvert(pFrImg2, pFrMat2);//cvCvtColor(pFrImg2, pFrImg1, CV_BGR2GRAY);pFrImg1 = pFrImg2;cvConvert(pFrImg1, pFrMat1);cvSmooth(pFrMat1, pFrMat1, CV_GAUSSIAN , 3, 1);cvSmooth(pFrMat2, pFrMat2, CV_GAUSSIAN , 3, 1);cvSmooth(pFrMat3, pFrMat3, CV_GAUSSIAN , 3, 1);//当前帧跟前一帧相减cvAbsDiff(pFrMat2, pFrMat1, reMat1);cvAbsDiff(pFrMat3, pFrMat2, reMat2);//二值化前景图cvThreshold(reMat1, result1, 60.0, 255.0, CV_THRESH_BINARY); cvThreshold(reMat2, result2, 60.0, 255.0, CV_THRESH_BINARY);//cvAdaptiveThreshold( reMat1, result1, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 3, 5 );//cvAdaptiveThreshold( reMat2, result2, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY, 3, 5 );//两个帧差值相与cvAnd(result1,result2,result,0);//使用Gaussian金字塔分解对输入图像向下采样,输出图像的高度和宽度应是输入图像的一半cvPyrDown(result, tempImg1, 7 );//对输入图像进行膨胀cvDilate(result, result, 0, 1);//使用Gaussian金字塔分解对输入图像向上采样,输出图像的高度和宽度应是输入图像的2倍cvPyrUp(tempImg1, result, 7 );//cvErode(result, result, 0, 1);//cvDilate(result, result, 0, 1);//cvPyrDown(result, tempImg1, 7 );//cvPyrUp(tempImg1, result, 7 );cvErode(result, result, 0, 3);cvDilate(result, result, 0, 3);//翻转图像,使其正立显示cvFlip(result, NULL, 0);cvShowImage("video", pFrame);cvShowImage("effect", result);cvCopy(pFrMat2, pFrMat1, NULL);cvCopy(pFrMat3, pFrMat2, NULL);cvCopy(pFrMat1, pFrMat3, NULL);cvCopy(pFrMat1, tempMat1, NULL);if( cvWaitKey( 20 ) >= 0 )break;}printf("\nFrame = %d\n", nFrmNum);}//销毁窗口cvDestroyWindow("video");//cvDestroyWindow(reWin);cvDestroyWindow("effect");//释放图像和矩阵cvReleaseImage(&pFrame);cvReleaseImage(&pFrImg1);cvReleaseImage(&pFrImg2);cvReleaseImage(&result1);cvReleaseImage(&result2);cvReleaseImage(&result);cvReleaseImage(&tempImg1);cvReleaseMat(&pFrMat1);cvReleaseMat(&pFrMat2);cvReleaseMat(&reMat1);cvReleaseMat(&reMat2);cvReleaseMat(&reMat);cvReleaseMat(&tempMat1);cvReleaseCapture(&pCapture); return 0;}。
前景检测算法_2(帧差法1)
前景检测算法_2(帧差法1) 帧差法是背景减图法中的⼀种,只不过是帧差法不需要建模,因为它的背景模型就是上⼀帧的图,所以速度⾮常快,另外帧差法对缓慢变换的光照不是很敏感,所以其⽤途还是有的,有不少学者对其做出了出⾊的改进。
其基本原理可以⽤下⾯公式看出: |i(t)-i(t-1)|<T 背景 |i(t)-i(t-1)|>=T 前景 其中i(t),i(t-1)分别为t,t-1时刻对应像素点的像素值,T为阈值。
当然其缺点也不少,容易出现”双影”和”空洞”现象。
⽤opencv2.3.1+vs2010做了个简单的实验,其实验代码如下:1// frame_diff.cpp : 定义控制台应⽤程序的⼊⼝点。
2//34 #include "stdafx.h"5 #include <opencv2/highgui/highgui.hpp>6 #include <opencv2/imgproc/imgproc.hpp>7 #include <opencv2/core/core.hpp>89#define threshold_diff 20 //设置简单帧差法阈值1011using namespace cv;12using namespace std;1314int main(int argc,unsigned char* argv[])15 {16 Mat img_src1,img_src2,img_dst,gray1,gray2,gray_diff;17bool pause=false;1819 VideoCapture vido_file("IndoorGTTest1.avi");//在这⾥改相应的⽂件名20 namedWindow("foreground",0);21for (;;)22 {23if(!pause)24 {25 vido_file >>img_src1; //因为视频⽂件帧数已经固定了,所以每次到这句语句都是读取相邻的帧数,没到时间视频并不向前⾛26 cvtColor(img_src1,gray1,CV_BGR2GRAY);27 imshow("video_src",img_src1);//可以事先不⽤新建⼀个窗⼝28 waitKey(5);2930 vido_file >>img_src2;31 cvtColor(img_src2,gray2,CV_BGR2GRAY);32 imshow("video_src",img_src2);//可以事先不⽤新建⼀个窗⼝3334 waitKey(5);35 subtract(gray1,gray2,gray_diff);36for(int i=0;i<gray_diff.rows;i++)37for(int j=0;j<gray_diff.cols;j++)38if(abs(gray_diff.at<unsigned char>(i,j))>=threshold_diff)//这⾥模板参数⼀定要⽤unsigned char,否则就⼀直报错39 gray_diff.at<unsigned char>(i,j)=255;40else gray_diff.at<unsigned char>(i,j)=0;4142 imshow("foreground",gray_diff);43 }44char c=(char)waitKey(10);45if (c==27)46 {47break;48 }49if(c=='')50 pause=!pause;51 }52return0;53 } 实验结果如下: 可以看出其“双影”和”空洞”⽐较明显。
opencv实现三帧差法解析
opencv实现三帧差法解析今天和⼤家谈谈三帧差法来实现运动⽬标检测吧,其中运动检测画框实现追踪⽅法多种多样,⼤家可以⾃⾏百度,后⾯我也会⼀⼀实现,今天我先给⼤家玩玩三帧差法吧;;;;(注释⾮常清楚哦,程序也极其简单的)帧差法是最为常⽤的运动⽬标检测和分割⽅法之⼀,基本原理就是在图像序列相邻两帧或三帧间采⽤基于像素的时间差分通过闭值化来提取出图像中的运动区域。
⾸先,将相邻帧图像对应像素值相减得到差分图像,然后对差分图像⼆值化,在环境亮度变化不⼤的情况下,如果对应像素值变化⼩于事先确定的阂值时,可以认为此处为背景像素:如果图像区域的像素值变化很⼤,可以认为这是由于图像中运动物体引起的,将这些区域标记为前景像素,利⽤标记的像素区域可以确定运动⽬标在图像中的位置。
由于相邻两帧间的时间间隔⾮常短,⽤前⼀帧图像作为当前帧的背景模型具有较好的实时性,其背景不积累,且更新速度快、算法简单、计算量⼩。
算法的不⾜在于对环境噪声较为敏感,闽值的选择相当关键,选择过低不⾜以抑制图像中的噪声,过⾼则忽略了图像中有⽤的变化。
对于⽐较⼤的、颜⾊⼀致的运动⽬标,有可能在⽬标内部产⽣空洞,⽆法完整地提取运动⽬标。
简单说⼀下程序思路哈,参考了⼀下opencv官⽹教程#include<iostream>#include<opencv2\core\core.hpp>#include<opencv2\highgui\highgui.hpp>#include<opencv2\imgproc\imgproc.hpp>using namespace cv;using namespace std;const unsigned char FORE_GROUD = 255;int thresh = 10;int main(int argc,char*argv[]){VideoCapture video(argv[1]); //判断如果video是否可以打开if(!video.isOpened())return -1;//⽤于保存当前帧的图⽚Mat currentBGRFrame;//⽤来保存上⼀帧和当前帧的灰度图⽚Mat previousSecondGrayFrame; Mat previousFirstGrayFrame; Mat currentGaryFrame;//保存两次的帧差Mat previousFrameDifference; //previousFrameFirst - previousFrameSecond的差分Mat currentFrameDifference; //currentFrame - previousFrameFirst;//⽤来保存帧差的绝对值Mat absFrameDifferece;//⽤来显⽰前景Mat previousSegmentation; Mat currentSegmentation; Mat segmentation;//显⽰前景namedWindow("segmentation",1);createTrackbar("阈值:","segmentation",&thresh,FORE_GROUD,NULL);//帧数int numberFrame = 0;//形态学处理⽤到的算⼦Mat morphologyKernel = getStructuringElement(MORPH_RECT,Size(3,3),Point(-1,-1));for(;;){ //读取当前帧video >> currentBGRFrame;//判断当前帧是否存在if(!currentBGRFrame.data)break;numberFrame++;//颜⾊空间的转换cvtColor(currentBGRFrame,currentGaryFrame,COLOR_BGR2GRAY);if( numberFrame == 1) {//保存当前帧的灰度图previousSecondGrayFrame = currentGaryFrame.clone();//显⽰视频imshow("video",currentBGRFrame); continue; }else if( numberFrame == 2){//保存当前帧的灰度图previousFirstGrayFrame = currentGaryFrame.clone();//previousFirst - previousSecondsubtract(previousFirstGrayFrame,previousSecondGrayFrame,previousFrameDifference,Mat(),CV_16SC1);//取绝对值absFrameDifferece = abs(previousFrameDifference);//位深的改变absFrameDifferece.convertTo(absFrameDifferece,CV_8UC1,1,0);//阈值处理threshold(absFrameDifferece,previousSegmentation,double(thresh),double(FORE_GROUD),THRESH_BINARY);//显⽰视频imshow("video",currentBGRFrame);continue; }else{//src1-src2subtract(currentGaryFrame,previousFirstGrayFrame,currentFrameDifference,Mat(),CV_16SC1);//取绝对值absFrameDifferece = abs(currentFrameDifference);//位深的改变 absFrameDifferece.convertTo(absFrameDifferece,CV_8UC1,1,0);//阈值处理threshold(absFrameDifferece,currentSegmentation,double(thresh),double(FORE_GROUD),THRESH_BINARY); //与运算bitwise_and(previousSegmentation,currentSegmentation,segmentation); //中值滤波medianBlur(segmentation,segmentation,3); //形态学处理(开闭运算)//morphologyEx(segmentation,segmentation,MORPH_OPEN,morphologyKernel,Point(-1,-1),1,BORDER_REPLICATE);morphologyEx(segmentation,segmentation,MORPH_CLOSE,morphologyKernel,Point(-1,-1),2,BORDER_REPLICATE);//找边界vector< vector<oint> > contours;vector<Vec4i> hierarchy;//复制segmentationMat tempSegmentation = segmentation.clone();findContours( segmentation, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );//CV_RETR_TREE vector< vector<oint> > contours_poly( contours.size() );/*存储运动物体*/vector<Rect> boundRect;boundRect.clear();//画出运动物体for(int index = 0;index < contours.size() ;index++){approxPolyDP( Mat(contours[index]), contours_poly[index], 3, true );Rect rect = boundingRect( Mat(contours_poly[index]) );rectangle(currentBGRFrame,rect,Scalar(0,255,255),2); }//显⽰视频imshow("video",currentBGRFrame);//前景检测imshow("segmentation",segmentation);//保存当前帧的灰度图previousFirstGrayFrame = currentGaryFrame.clone();//保存当前的前景检测previousSegmentation = currentSegmentation.clone();}if(waitKey(33) == 'q')break;}return 0;}编译之后,运⾏./main.cpp **.avi以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
python+opencv实现移动侦测(帧差法)
python+opencv实现移动侦测(帧差法)本⽂实例为⼤家分享了python+opencv实现移动侦测的具体代码,供⼤家参考,具体内容如下1.帧差法原理移动侦测即是根据视频每帧或者⼏帧之间像素的差异,对差异值设置阈值,筛选⼤于阈值的像素点,做掩模图即可选出视频中存在变化的桢。
帧差法较为简单的视频中物体移动侦测,帧差法分为:单帧差、两桢差、和三桢差。
随着帧数的增加是防⽌检测结果的重影。
2.算法思路⽂章以截取视频为例进⾏单帧差法移动侦测3.python实现代码def threh(video,save_video,thres1,area_threh):cam = cv2.VideoCapture(video)#打开⼀个视频input_fps = cam.get(cv2.CAP_PROP_FPS)ret_val, input_image = cam.read()index=[]images=[]images.append(input_image)video_length = int(cam.get(cv2.CAP_PROP_FRAME_COUNT))input_image=cv2.resize(input_image,(512,512))ending_frame = video_lengthfourcc = cv2.VideoWriter_fourcc(*'XVID')out = cv2.VideoWriter(save_video,fourcc, input_fps, (512, 512))gray_lwpCV = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY)gray_lwpCV = cv2.GaussianBlur(gray_lwpCV, (21, 21), 0)background=gray_lwpCV# es = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9, 4))i = 0 # default is 0outt=[]while(cam.isOpened()) and ret_val == True and i <2999:## if i % 2==1:ret_val, input_image = cam.read()input_image=cv2.resize(input_image,(512,512))gray_lwpCV = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY)gray_lwpCV = cv2.GaussianBlur(gray_lwpCV, (21, 21), 0)diff = cv2.absdiff(background, gray_lwpCV)outt.append(diff)#跟着图像变换背景tem_diff=diff.flatten()tem_ds=pd.Series(tem_diff)tem_per=1-len(tem_ds[tem_ds==0])/len(tem_ds)if (tem_per <0.2 )| (tem_per>0.75):background=gray_lwpCVelse:diff = cv2.threshold(diff, thres1, 255, cv2.THRESH_BINARY)[1]ret,thresh = cv2.threshold(diff.copy(),150,255,0)contours, hierarchy = cv2.findContours(thresh,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)# contours, hierarchy = cv2.findContours(diff.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)for c in contours:if (cv2.contourArea(c) < area_threh) | (cv2.contourArea(c) >int(512*512*0.3) ) : # 对于矩形区域,只显⽰⼤于给定阈值的轮廓(去除微⼩的变化等噪点) continue(x, y, w, h) = cv2.boundingRect(c) # 该函数计算矩形的边界框cv2.rectangle(input_image, (x, y), (x+w, y+h), (0, 255, 0), 2)index.append(i)# cv2.imshow('contours', input_image)# cv2.imshow('dis', diff)out.write(input_image)images.append(input_image)i = i+1out.release()cam.release()return outt,index,images```##调取函数outt=threh('new_video.mp4','test6.mp4',25,3000)以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
opencv 帧差法
OpenCV帧差法OpenCV中的帧差法是一种简单但有效的背景减除技术,用于检测运动对象。
在这种方法中,我们首先拍摄一个没有任何运动对象的基础图像(或称为背景)并将其保存下来。
接下来,在连续的帧中,我们从当前帧中减去该基础图像,并获取其绝对值。
然后阈值化此结果图像以获得二进制图像,其中白色部分表示运动对象。
以下是使用OpenCV Python库实现帧差法的简单示例代码:import cv2# 读取基础图像和视频流base_img = cv2.imread('background.jpg')cap = cv2.VideoCapture('test_video.mp4')# 定义阈值和核大小threshold_value = 30kernel_size = (3, 3)while True:# 读取当前帧ret, frame = cap.read()if not ret:break# 将当前帧转换为灰度图像gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 计算当前帧与基础图像的差值diff_frame = cv2.absdiff(base_img, gray_frame)# 对差值图像进行阈值化处理_, thresh_frame = cv2.threshold(diff_frame, threshold_value, 255, cv2.THRESH_BINARY)# 使用形态学操作平滑图像smoothed_frame = cv2.morphologyEx(thresh_frame, cv2.MORPH_OPEN, kernel_size)# 显示结果cv2.imshow('Frame', frame)cv2.imshow('Diff Frame', diff_frame)cv2.imshow('Thresh Frame', thresh_frame)cv2.imshow('Smoothed Frame', smoothed_frame)# 按下ESC键退出循环if cv2.waitKey(30) == 27:break# 释放摄像机和所有窗口cap.release()cv2.destroyAllWindows()在上面的代码中,我们首先读取基础图像和视频流。
实践5-视频运动目标检测:帧差法的实现
实践5 视频运动目标检测:帧差法的实现实验任务:根据原理,获取并显示两幅图像的帧差灰度图和帧差二值图,如下图所示。
实现的算法是:(1)分别读取两张图像;(2)将2张图像分别转换为灰度图,转换函数可用:cvCvtColor/cvtColor;(3)将2张灰度图相减(求差值),得到帧差灰度图,相减函数可用:cvAbsDiff/absdiff;(4)利用阈值操作,将帧差灰度图转化为帧差二值图,阈值操作函数可用:cvThreshold/threshold;(如果假设目标设定为白色,背景设定为黑色,则需要使用逻辑“非”操作进行颜色转换,可使用cvNot/bitwise_not函数);(5)显示图像。
请将上述任务改成找茬游戏的自动找茬功能。
请改为三帧差分,并上交源代码。
函数解析:(1)cvCvtColor/cvtColorC: void cvCvtColor( const CvArr* src, CvArr* dst, int code );C++:void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0)src 输入的8-bit,16-bit或32-bit单倍精度浮点数影像。
dst 输出的8-bit,16-bit或32-bit单倍精度浮点数影像。
code色彩空间转换的模式,该code来实现不同类型的颜色空间转换。
比如CV_BGR2GRAY表示转换为灰度图,CV_BGR2HSV将图片从RGB空间转换为HSV空间。
常见的code模式有:CV_RGB2GRAY(彩色图像-灰度图像)CV_BGR2YCrCbCV_RGB2YCrCbCV_YCrCb2BGRCV_YCrCb2RGBCV_BGR2HSVCV_RGB2HSVCV_HSV2BGRCV_HSV2RGB(2)cvAbsDiff/absdiffOpenCV 中计算两个数组差的绝对值的函数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
% By lyqmath @ Matlab中文论坛clc; clear all; close all;avi = mmreader('samplevideo.avi');for i = 1 : avi.NumberOfFramesimg = read(avi, i);pixels(:, :, :, i) = img;figure(1); imshow(img, []);text(1, 15, sprintf('原视频:%d帧By lyqmath', i), 'FontWeight', 'Bold', 'Color', 'r'); endtracking(pixels);function d = tracking(video)if ischar(video)% 载入视频数据for i = 1 : avi.NumberOfFramesimg = read(avi, i);pixels(:, :, :, i) = img;endelsepixels = video;endnFrames = size(pixels, 4);rows = size(pixels, 1);cols = size(pixels, 2);% 转换成灰度图像for i = 1 : nFramespixel(:, :, i) = (rgb2gray(pixels(:,:,:,i)));endfor i = 2 : nFramesd(:, :, i) = (abs(pixel(:,:,i) - pixel(:,:,i-1)));bw(:, :, i) = im2bw(d(:, :, i), 0.2);% 寻找上下边界cou=1;for h = 1:rowsfor w = 1:colsif bw(h, w, i) > 0.5bottomEdge = h;if cou == 1topEdge = bottomEdge;endcou = cou+1;break;endendend% 寻找左右边界coun=1;for w = 1:colsfor h = 1:rowsif bw(h, w, i) > 0.5rightEdge = w;if coun == 1leftEdge = rightEdge;coun = coun+1;endbreak;endendend% 矩形框生成wd = rightEdge-leftEdge;hg = bottomEdge-topEdge;widt = wd/2;heit = hg/2;cenx = leftEdge+widt;ceny = topEdge+heit;% 显示并标记figure(1);imshow(pixels(:, :, :, i), []);hold onrectangle('Position',[leftEdge topEdge wd hg], 'EdgeColor', 'r', 'LineWidth', 2);plot(cenx, ceny, 'ko', 'MarkerFaceColor', 'y', 'MarkerSize', 20, 'LineWidth', 2);text(1, 15, sprintf('跟踪视频:%d帧By lyqmath', i), 'FontWeight', 'Bold', 'Color', 'r');hold offEnd另一段代码% By lyqmathclc; clear all; close all;% 原始视频targetavi = 'traffic.avi';% 检测结果视频resultavi = 'c:\\result.avi';%% 读取视频mov = mmreader(targetavi);fnum = mov.NumberOfFrames;%% 建立结果视频aviobj = avifile(resultavi);aviobj.Quality = 100;aviobj.Fps = 25;pression = 'Indeo5';%% 帧间差分法figure(1);for i = 2 : fnumx = read(mov, i-1);y = read(mov, i);subplot(1, 2, 1); imshow(x, []); title(sprintf('第%d帧视频,By lyqmath', i-1), 'FontWeight', 'Bold', 'Color', 'r');% 灰度化if ndims(x) == 3m = rgb2gray(x);elsem = x;endif ndims(y) == 3n = rgb2gray(y);elsen = y;end% 中值滤波m = medfilt2(m);n = medfilt2(n);% 数据类型转换q = im2double(n);w = im2double(m);% 差分c = q-w;% 阈值,此值可以调节t = 40/256;% 阈值分割c(abs(c)>=t)=255;c(abs(c)<t) = 0;c = logical(c);x1 = x(:, :, 1); x2 = x(:, :, 2); x3 = x(:, :, 3);x1(c) = 255; x2(c) = 0; x3(c) = 0;xc = cat(3, x1, x2, x3);subplot(1, 2, 2); imshow(xc, []); title(sprintf('第%d帧视频识别结果,By lyqmath', i-1), 'FontWeight', 'Bold', 'Color', 'r');f = getframe(gcf);f = frame2im(f);% 生成视频aviobj = addframe(aviobj, f);end%% 关闭视频句柄aviobj = close(aviobj);第三段代码mov=aviread('CIMG0003.AVI');temp=size(mov);fnum=temp(2);for i=1:fnum,strtemp=strcat(int2str(i),'.','JPG');imwrite(mov(i).cdata(:,:,:),strtemp);end%% 从视频中提出每一帧图像o=1;e='.jpg';for i=1:15u=o-1;v=o-2;m=int2str(o);n=int2str(u);h=int2str(v);s=strcat(m,e);%%把字符串b与m连接后在连接e得到图像文件存储的位置m=imread(s);%%从S处把图像读取出来m=rgb2gray(m);%%将图像M灰度化m=medfilt2(m,[3,3]);if(o>=3)s=strcat(n,e);n=imread(s);n=rgb2gray(n);s=strcat(h,e);h=imread(s);h=rgb2gray(h);n=medfilt2(n,[3,3]);h=medfilt2(h,[3,3]);q=im2double(m);%%将图像数组转换为double型w=im2double(n); g=im2double(h);c=q-w;j=w-g;th=10/255;k=find(abs(c)>=th);c(k)=1;k=find(abs(c)<th);c(k)=0;c=bwareaopen(c,15);se90=strel ('line',3,90);se0=strel ('line',3,0);c=bwmorph(c,'close'); %对上述图像进行形态学闭运算c=imdilate(c,[se90,se0]);c=bwmorph(c,'close');c=bwareaopen(c,50);k=find(abs(j)>=th);j(k)=1;k=find(abs(j)<th);j(k)=0;j=bwareaopen(j,15);j=bwmorph(j,'close'); %对上述图像进行形态学闭运算j=imdilate(j,[se90,se0]);j=bwmorph(j,'close');c=bwareaopen(c,50);c=c&j;c=imerode(c,[se90,se0]);figure,imshow(c);a=c;b=c; d=c;f=c;[m,n]=size(c);%%行扫描填充for i=1:mfor j=1:n-1if a(i,j)>0a(i,j+1)=1;endendendfor i=1:mfor j=n:-1:2if b(i,j)>0b(i,j-1)=1;endendendth=a&b;%%列扫描填充for i=1:nfor j=1:m-1if d(j,i)>0d(j+1,i)=1;endendendfor i=1:nfor j=m:-1:2if f(j,i)>0f(j-1,i)=1;endendendtd=d&f;c=th&td;endo=o+1;end。