He is researching to find meaningful scene in endoscopic video.
His one of approach is using optical flow.
refer to this page.
http://study.marearts.com/2015/01/the-method-to-check-that-camera-is.html
Dense optical flow can know how much video moving.
The source code of reference page checked camera move or not by the percentage of movement.
There are 2 threshold values.
Count number of moved pixels, this is counted when pixels moved over than threshold-1 value.
And check whether the counted pixels is over than threshold-2 percent or not in all pixels.
By the way, he ask me to separate video moving by big, middle, small using k-means clustering algorithm without threshold.
In past, I introduced the usage of k-mean algorithm using openCV.
See this page.
http://study.marearts.com/search/label/K-means
This work is separated by 3 steps.
Step 1 is to calculate movement rate in video using optical flow.
And save fame and movement rate information to txt file.
Step 2 is clustering by 3 class degree movement using k-means.
read step 1 file and write clustering information to txt file.
Step 3 is for display.
read step 3 txt file and display moving rate on the video.
refer to these source code.
Thank you.
Step 1.
Getting movement rate of frames.
moving rate is calculated.
...
#include < stdio.h>  
#include < opencv2\opencv.hpp>  
#include < opencv2/core/core.hpp>  
#include < opencv2/highgui/highgui.hpp>  
#include < opencv2\gpu\gpu.hpp>  
#include < opencv2\nonfree\features2d.hpp >      
#ifdef _DEBUG          
#pragma comment(lib, "opencv_core249d.lib")  
#pragma comment(lib, "opencv_imgproc249d.lib")   //MAT processing  
#pragma comment(lib, "opencv_objdetect249d.lib") //HOGDescriptor  
#pragma comment(lib, "opencv_gpu249d.lib")  
#pragma comment(lib, "opencv_features2d249d.lib")  
#pragma comment(lib, "opencv_highgui249d.lib")  
#else  
#pragma comment(lib, "opencv_core249.lib")  
#pragma comment(lib, "opencv_imgproc249.lib")  
#pragma comment(lib, "opencv_objdetect249.lib")  
#pragma comment(lib, "opencv_gpu249.lib")  
#pragma comment(lib, "opencv_features2d249.lib")  
#pragma comment(lib, "opencv_highgui249.lib")  
#endif   
using namespace std;  
using namespace cv;  
#define WIDTH_DENSE (80)  
#define HEIGHT_DENSE (60)  
#define DENSE_DRAW 0 //dense optical flow arrow drawing or not  
#define GLOBAL_MOTION_TH1 1  
#define GLOBAL_MOTION_TH2 70  
float drawOptFlowMap_gpu (const Mat& flow_x, const Mat& flow_y, Mat& cflowmap, int step, float scaleX, float scaleY, int drawOnOff);  
int main()  
{  
 //stream /////////////////////////////////////////////////  
 VideoCapture stream1("M:\\____videoSample____\\medical\\HUV-03-14.wmv");
 //variables /////////////////////////////////////////////  
 Mat O_Img; //Mat  
 gpu::GpuMat O_Img_gpu; //GPU  
 gpu::GpuMat R_Img_gpu_dense; //gpu dense resize  
 gpu::GpuMat R_Img_gpu_dense_gray_pre; //gpu dense resize gray  
 gpu::GpuMat R_Img_gpu_dense_gray; //gpu dense resize gray  
 gpu::GpuMat flow_x_gpu, flow_y_gpu;  
 Mat flow_x, flow_y;  
 //algorithm *************************************  
 //dense optical flow  
 gpu::FarnebackOpticalFlow fbOF;  
 //running once //////////////////////////////////////////  
 if(!(stream1.read(O_Img))) //get one frame form video  
 {  
  printf("Open Fail !!\n");  
  return 0;   
 }  
 //for rate calucation  
 float scaleX, scaleY;  
 scaleX = O_Img.cols/WIDTH_DENSE;  
 scaleY = O_Img.rows/HEIGHT_DENSE;  
 O_Img_gpu.upload(O_Img);   
 gpu::resize(O_Img_gpu, R_Img_gpu_dense, Size(WIDTH_DENSE, HEIGHT_DENSE));  
 gpu::cvtColor(R_Img_gpu_dense, R_Img_gpu_dense_gray_pre, CV_BGR2GRAY);  
 //////////////////////////////////////////////////////////
 FILE *fp = fopen("DataOutput.txt","w");
 //unconditional loop   ///////////////////////////////////  
 int frame=0;
 int untilFrame=1000;
 while (true) {  
  frame++;
  if(frame>untilFrame)  //stop point.
   break;
  //reading  
  if( stream1.read(O_Img) == 0) //get one frame form video     
   break;  
  // ---------------------------------------------------  
  //upload cou mat to gpu mat  
  O_Img_gpu.upload(O_Img);   
  //resize  
  gpu::resize(O_Img_gpu, R_Img_gpu_dense, Size(WIDTH_DENSE, HEIGHT_DENSE));  
  //color to gray  
  gpu::cvtColor(R_Img_gpu_dense, R_Img_gpu_dense_gray, CV_BGR2GRAY);  
  //calculate dense optical flow using GPU version  
  fbOF.operator()(R_Img_gpu_dense_gray_pre, R_Img_gpu_dense_gray, flow_x_gpu, flow_y_gpu);  
  flow_x_gpu.download( flow_x );  
  flow_y_gpu.download( flow_y );  
  //calculate motion rate in whole image  
  float motionRate = drawOptFlowMap_gpu(flow_x, flow_y, O_Img, 1, scaleX, scaleY, DENSE_DRAW);  
  //update pre image  
  R_Img_gpu_dense_gray_pre = R_Img_gpu_dense_gray.clone();  
  //display "moving rate (0~100%)" and save to txt with frame
  char TestStr[100];  
  sprintf(TestStr, "%.2lf %% moving", motionRate);
  putText(O_Img, TestStr, Point(30,60), CV_FONT_NORMAL, 1, Scalar(255,255,255),2,2); //OutImg is Mat class;     
  
  //output "frame, motionRate" to txt
  fprintf(fp,"%d %.2lf\n", frame, motionRate);
  // show image ----------------------------------------  
  imshow("Origin", O_Img);     
  // wait key  
  if( cv::waitKey(100) > 30)  
   break;  
 }  
 fclose(fp);
}  
float drawOptFlowMap_gpu (const Mat& flow_x, const Mat& flow_y, Mat& cflowmap, int step, float scaleX, float scaleY, int drawOnOff)  
{  
 double count=0;  
 float countOverTh1 = 0;  
 int sx,sy;  
 for(int y = 0; y < HEIGHT_DENSE; y += step)  
 {  
  for(int x = 0; x < WIDTH_DENSE; x += step)  
  {  
   if(drawOnOff)  
   {  
    Point2f fxy;      
    fxy.x = cvRound( flow_x.at< float >(y, x)*scaleX + x*scaleX );     
    fxy.y = cvRound( flow_y.at< float >(y, x)*scaleY + y*scaleY );     
    line(cflowmap, Point(x*scaleX,y*scaleY), Point(fxy.x, fxy.y), CV_RGB(0, 255, 0));     
    circle(cflowmap, Point(fxy.x, fxy.y), 1, CV_RGB(0, 255, 0), -1);     
   }  
   float xx = fabs(flow_x.at< float >(y, x) );  
   float yy = fabs(flow_y.at< float >(y, x) );  
   float xxyy = sqrt(xx*xx + yy*yy);  
   if( xxyy > GLOBAL_MOTION_TH1 )  
    countOverTh1 = countOverTh1 +1;  
   count=count+1;  
  }  
 }  
 return (countOverTh1 / count) * 100;  
}  
...step 2. clustering movement rate to 3 classes.
The movement rates are clustered by 3 values
Frames and class ID
...
#include <  stdio.h>     
#include <  iostream>     
#include <  opencv2\opencv.hpp>     
#ifdef _DEBUG             
#pragma comment(lib, "opencv_core249d.lib")     
#pragma comment(lib, "opencv_imgproc249d.lib")   //MAT processing     
#pragma comment(lib, "opencv_highgui249d.lib")     
#else     
#pragma comment(lib, "opencv_core249.lib")     
#pragma comment(lib, "opencv_imgproc249.lib")     
#pragma comment(lib, "opencv_highgui249.lib")     
#endif    
using namespace cv;  
using namespace std;  
void main()  
{  
 //read data
 FILE* fp = fopen("DataOutput.txt","r");
 vector< float > readDataV;
 int frames;
 double movingRate;
 while(fscanf(fp,"%d %lf", &frames, &movingRate) != EOF )
 {
  readDataV.push_back( movingRate );
  //printf("%d %lf \n", frames, movingRate);
 }
 fclose(fp);
 
 //preparing variables for kmeans
 Mat samples(readDataV.size(), 1, CV_32F);  
 //copy vector to mat
 memcpy(samples.data, readDataV.data(), readDataV.size()*sizeof(float) );
 //kmean
 int clusterCount = 3;
 Mat labels;
 int attempts = 10;
 Mat centers;
 kmeans(samples, clusterCount, labels, 
  TermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 10, 1.0), 
  attempts, KMEANS_RANDOM_CENTERS, centers );
 //result out
 //frames, class index
 for(int i=0; i< clusterCount; ++i)
 {
  printf("%d class center %lf\n",  i, centers.at< float>(i,0) );
 }
 printf("\n");
 
 
 FILE* fp2 = fopen("ResultKmeans.txt", "w");
 for(int i=0; i< readDataV.size(); ++i)
 {
  //printf("%d %d\n", i, labels.at< int>(i,0) );
  fprintf(fp2, "%d %d\n", i+1, labels.at< int>(i,0) );
 }
 fclose(fp2);
}  
...step 3. display movement labels on the video.
display 3 type of movement category(big, middle, small).
#include < time.h>
#include < opencv2\opencv.hpp>
#include < string>
#include < stdio.h>
#ifdef _DEBUG        
#pragma comment(lib, "opencv_core249d.lib")
#pragma comment(lib, "opencv_imgproc249d.lib")   //MAT processing
#pragma comment(lib, "opencv_highgui249d.lib")
#else
#pragma comment(lib, "opencv_core249.lib")
#pragma comment(lib, "opencv_imgproc249.lib")
#pragma comment(lib, "opencv_highgui249.lib")
#endif   
using namespace std;
using namespace cv;
int main()
{
 /////////////////////////////////////////////////////////////////////////
 //read file
 FILE* fp = fopen("ResultKmeans.txt","r");
 vector< int > readDataV;
 int frames;
 int labels;
 while(fscanf(fp,"%d %d", &frames, &labels) != EOF )
 {
  readDataV.push_back( labels );
  //printf("%d %d \n", frames, labels);
 }
 fclose(fp);
 //Load avi file 
 VideoCapture stream1("M:\\____videoSample____\\medical\\HUV-03-14.wmv");
 /////////////////////////////////////////////////////////////////////////
 //Mat and GpuMat
 Mat o_frame; 
 //capture
 stream1 >> o_frame;
 if( o_frame.empty() )
   return 0; 
 //////////////////////////////////////////////////////////////////////////
 int frame=0;
 int untilFrame=1000;
 while(1)
 {
  frame++;
  if(frame>untilFrame)  //stop point.
   break;
  /////////////////////////////////////////////////////////////////////////
  stream1 >> o_frame;
  if( o_frame.empty() )
   return 0;
  char TestStr[100];    
  if(readDataV[frame-1] == 0)  
   sprintf(TestStr, "Big moving");   
  else if(readDataV[frame-1] == 1)
   sprintf(TestStr, "middle moving");
  else
   sprintf(TestStr, "small moving");
  putText(o_frame, TestStr, Point(30,60), CV_FONT_NORMAL, 1, Scalar(255,255,255),2,2); //OutImg is Mat class;     
  //Display   
  imshow("origin", o_frame);  
  /////////////////////////////////////////////////////////////////////////
  if( waitKey(10) > 0)
   break;
 }
 return 0;
}
... 
 
 
 
 
No comments:
Post a Comment