#include "stdafx.h"
#include
#include "opencv2/core/core.hpp"
#include
#include
using namespace std;
using namespace cv;
void RGBtoHSV(float b,float g,float r,float &h,float &s,float &v)//将RGB值转化为HSV值
{
float max = (((r > b) ? r : b) > g) ? ((r > b) ? r : b) : g ;
float min = (((r > b) ? b : r) > g) ? g : ((r > b) ? b : r);
if (max == min)
{
h = 0; s = 0; v = max / 255;
}
else if (g >= b)
{
h = (max - r + g - min + b - min) / (max - min) * 60;
s = 1 - min / max;
v = max / 255;
}
else if (g < b)
{
h = 360 - (max - r + g - min + b - min) / (max - min) * 60;
s = 1 - min / max;
v = max / 255;
}
}
//以HSV总量作为特征量提取关键帧
int HSV(Mat img)
{
// IplImage * ipl_img = NULL;
// * ipl_img =img;//将Mat类型转化为IplImage
float B, G, R, H=0, S=0, V=0;
int nr = img.rows; // number of rows
int nc = img.cols; // number of cols
float sumH = 0, sumS = 0, sumV = 0;
CvScalar cs;
//将Mat类型转化为IplImage
IplImage *ipl_img = cvCreateImage(cvSize(nr, nc), 8, 3);
ipl_img->imageData = (char *)img.data;
for (int j = 0; j<nr; j++) {
for (int i = 0; i<nc; i++) {
cs =cvGet2D(ipl_img, i, j);
B = cs.val[0];
G = cs.val[1];
R = cs.val[2];
RGBtoHSV(B, G, R, H, S, V);
sumH = sumH + H;
sumS = sumS + S;
sumV = sumV + V;
}
}
float aveH = sumH / (nc*nr);
float aveS = sumS / (nc*nr);
float aveV = sumV / (nc*nr);
float totalHSV = 9 * aveH + 3 * aveS + aveV;//totalHSV为特征量
return totalHSV;
}
int main()
{
VideoCapture cap;
cap.open("E:\\1.avi");
Mat frame[5000];
Mat keyframe[5000];
int keycount=0;
int frmNum = 0;
float curhsv, lathsv;//当前帧的hsv值与后一帧的hsv值
if (!cap.isOpened())
{
cout << "无法打开视频!" << endl;
return -1;
}
int th=2;//提取关键帧的阈值
// cout << "输入阈值提取关键帧(大于1):";
// cin >> th;
for (;;)
{
frmNum++;
cap >> frame[frmNum];
if (frame[frmNum].empty())
{
cout << "读取视频完毕 !" << endl;
break;
}
keyframe[0] = frame[1];
if (frmNum > 1)
{
curhsv = HSV(frame[frmNum - 1]);
lathsv = HSV(frame[frmNum]);
if (abs(curhsv - lathsv) > 2)//设定阈值th提取关键帧
{
keycount++;
keyframe[keycount] = frame[frmNum];
}
}
}
cout << "该视频总共有" << frmNum << "帧" << endl;
cout << "在阈值为"<<th<<"时提取了" << keycount+1 << " 个关键帧!" << endl;
for (int i = 0; i < keycount + 1; i++)
{
imshow("关键帧", keyframe[i]);//展示所有提取的关键帧
waitKey(1);
}
return 0;
}
参考文章:任利平《视频中关键帧提取技术的研究》