opencv 基於內容的視訊關鍵幀提取(以HSV總量為特徵量)
阿新 • • 發佈:2018-12-14
參考文章:任利平《視訊中關鍵幀提取技術的研究》 點選開啟連結#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; }