问题描述
- opencv视频边界检测,哪个大神知道这是什么算法啊啊啊,好急
-
#include "cv.h"
#include "highgui.h"
#include
#include
#include
using namespace std;int window=15;
float LimenValue(float *comhist,int num)//阈值
{
float mean = 0;
float sum = 0;
float T;
float max;
float min;
float mmax = 0;
float mmin = 0;
float summin = 0;
float summax = 0;
float mincount = 0;
float maxcount = 0;
float median;
float factor = 4;
int i = 0;
max = comhist [num];
min = comhist [num];for( i = 0;i<window;i++) { sum +=comhist[num+i]; if(comhist[num+i]>max) { max = comhist[num+i]; } if(comhist[num+i]<min) { min = comhist[num+i]; } } mean = sum / window; median = (max +min) / 2; //计算大小两集合均值 for (i = 0;i< window;i++) { if (comhist[num+i] <= median) { summin +=comhist[num+i]; mincount++; } else { summax +=comhist[num+i]; maxcount++; } } mmin = summin / mincount; mmax = summax / maxcount; //计算是否有突变,返回阈值 if(fabs(mmax-mmin)>(factor*mean)) //如果 |mmax - mmin | > (Factor*mean)为真 T = (mmin+mmax * 2) / 3; //T = (mmin + mmax * 2) / 3作为阈值 else T = max + 10; return T;
}
float LimenValue2(float * comhist, int num1, int num2)
{
float avervalue = 0; //均值
float variance = 0; //方差
float sum = 0; //和
float squaresum = 0; //差值平方的和x
float limen;
int num = num2 - num1 + 1;
for(int i = num1; i<= num2; i++)
{
sum += comhist[i];
squaresum += comhist[i] * comhist[i];
}
avervalue = sum / num;
variance = squaresum / num - avervalue*avervalue;
limen = avervalue + 30*variance;
return limen;
}int main(int argc, char** argv)
{
CvCapture * capture = NULL; //设置读取视频数据的指针IplImage * Frame = NULL; IplImage * preFrame = NULL; //前一帧 IplImage * frame1 = NULL; IplImage * frame2 =NULL; int HistogramBins = 256; float HistogramRange1[2] = {0,255}; float * HistogramRange[1] = {&HistogramRange1[0]}; char * aviname = "F://视频//2.MP4"; //输入视频 char filename[3000]; //保存图片时用的变量 int totalFrmNum; //总帧数 int nFrmNum = 0; float * pCompareHist; //存放所有相邻帧间直方图差值的指针 int * sceneframe; //镜头突变处,后一镜头第一帧表示//int * keyframe; float fLimenValue; //阈值 float fLimenValue2; int scenecount = 0; cvNamedWindow("新闻视频",CV_WINDOW_AUTOSIZE);//读入视频 capture = cvCaptureFromAVI(aviname); totalFrmNum =(int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT)-1; if(!capture) { fprintf(stderr,"Could not initialize capturing...n"); return -1; } while(Frame = cvQueryFrame( capture)) { sprintf(filename,"allframe/%d.jpg",nFrmNum); cvSaveImage(filename, Frame); nFrmNum++; cvShowImage("新闻视频",Frame); cvWaitKey(5) ; } cvReleaseCapture(&capture); cvDestroyWindow("新闻视频"); //创建直方图 CvHistogram*Histogram=cvCreateHist(1,&HistogramBins,CV_HIST_ARRAY,HistogramRange); CvHistogram*Histogram2=cvCreateHist(1,&HistogramBins,CV_HIST_ARRAY,HistogramRange);
//计算相邻帧间直方图差值
pCompareHist = new float [totalFrmNum];
float CompareHist = 0;
pCompareHist[0] = 0;capture = cvCaptureFromAVI(aviname); nFrmNum = 0; while (Frame = cvQueryFrame(capture)) { if (nFrmNum==0) { frame1 = cvCreateImage(cvSize(Frame->width,Frame->height),IPL_DEPTH_8U,1); frame2 = cvCreateImage(cvSize(Frame->width,Frame->height),IPL_DEPTH_8U,1); } else if(nFrmNum > 1) { cvCvtColor(Frame,frame1,CV_BGR2GRAY); cvCvtColor(preFrame,frame2,CV_BGR2GRAY); cvCalcHist(&frame1,Histogram,0,0);//计算当前帧的直方图 cvCalcHist(&frame2,Histogram2,0,0);//计算前一帧的直方图 //直方图归一化 cvNormalizeHist(Histogram,1); cvNormalizeHist(Histogram2,1); //计算当前帧与前一帧的直方图差 CompareHist = (float)cvCompareHist(Histogram,Histogram2,CV_COMP_CHISQR); pCompareHist[nFrmNum-1] = CompareHist; } preFrame = cvCloneImage(Frame); nFrmNum++; } //释放图像和矩阵 cvReleaseCapture(&capture); cvReleaseImage(&Frame); cvReleaseImage(&frame1); cvReleaseImage(&frame2); cvReleaseHist(&Histogram); cvReleaseHist(&Histogram2); printf("镜头突变处帧:n"); sceneframe = new int[totalFrmNum]; //计算突变帧 for (int i = 0; i < (totalFrmNum - (totalFrmNum%window));) { fLimenValue = LimenValue(pCompareHist,1); for (int j = 0; j < window; j++) { if (pCompareHist[i+j] > fLimenValue) { printf("%d,",i+j+1); /*cvNamedWindow("突变帧",CV_WINDOW_AUTOSIZE); cvShowImage("突变帧",sceneframe); cvDestroyWindow("突变帧"); cvReleaseImage;*/ sceneframe[scenecount] = i+j+1; scenecount++; } } i +=window; } scenecount++; //保存pCompareHist数组到CompareHist.txt文件中 //保存sceneframe数组到SceneFrame.txt文件中 fstream out1; out1.open("CompareHist.txt",ios::out); if (!out1) { cerr<<"CompareHist.txt can not open.n"; abort(); } for (int i = 0; i < totalFrmNum; i++) { out1<<pCompareHist[i]; out1<<"n"; } out1.close(); out1.open("ScenceFrame.txt",ios::out); if (!out1) { cerr<<"ScenceFrame.txt can not open.n"; abort(); } for (int i = 0; i < scenecount-1; i++) { out1<<sceneframe[i]; out1<<"n"; } out1.close(); //保存突变帧 int count = 0; nFrmNum = 0; capture = cvCreateFileCapture(aviname); while (Frame = cvQueryFrame( capture)) { if (nFrmNum == sceneframe[count]) { sprintf(filename,"sceneframe/%d.jpg",nFrmNum); cvSaveImage(filename, Frame); count++; } nFrmNum++; } cvReleaseCapture(&capture);
解决方案
这个就是通过灰度直方图判断两个图片(相邻的帧)的差异,差异大说明切换了。