Hello every one,
here is my function "optical_flow_using_schunck
". on line "imshow("frame1", frame1)
" it throws "Segmentation fault (Core dumped)" error.
Any idea?!
int optical_flow_using_schunck(char * video_url)
{
int iteration_count = 20 ;
double a = 0.001 ;
namedWindow("frame1" , CV_WINDOW_AUTOSIZE) ;
namedWindow("frame2" , CV_WINDOW_AUTOSIZE) ;
cout << "Analyzing motion using Schunck approach for approximating optical flow..." << endl ;
cout << "Reading video from " << video_url << endl ;
VideoCapture vid (video_url);
if(!vid.isOpened())
{
cout << "An error has been occured. The video can not be opened!" << endl ;
return -1 ;
}
Mat frame1, frame2 ;
vid >> frame1 ;
if(!frame1.empty())
vid >> frame2 ;
cvtColor(frame1 , frame1 , CV_BGR2GRAY) ;
cvtColor(frame2 , frame2 , CV_BGR2GRAY) ;
pyrDown(frame1, frame1, Size(frame1.cols/2, frame1.rows/2)) ;
pyrDown(frame2, frame2, Size(frame2.cols/2, frame2.rows/2)) ;
cout <<"initializing velocity to zero" << endl ;
int sz[] = {frame1.rows, frame1.cols};
Mat u(2, sz, CV_32FC1, Scalar::all(0));
Mat v(2, sz, CV_32FC1, Scalar::all(0));
Mat u_avg(2, sz, CV_32FC1, Scalar::all(0));
Mat v_avg(2, sz, CV_32FC1, Scalar::all(0));
Mat Ex(2, sz, CV_32FC1, Scalar::all(0));
Mat Ey(2, sz, CV_32FC1, Scalar::all(0));
Mat Et(2, sz, CV_32FC1, Scalar::all(0));
while(!frame2.empty())
{
cout << "calculating Ex derivative..." << endl ;
calculate_EX(frame1, frame2, &Ex) ;
cout << "calculating Ey derivative..." << endl ;
calculate_EY(frame1, frame2, &Ey) ;
cout << "calculating Et derivative..." << endl ;
calculate_ET(frame1, frame2, &Et) ;
if(frame1.empty())
cout << "WOW!" << endl ;
imshow("frame1" , frame1) ;
imshow("frame2" , frame2) ;
for(int iter = 0 ; iter < iteration_count ; iter ++)
{
cout << "iteration: " << iter << endl ;
for(int i = 0 ; i < u.rows ; i ++)
{
for(int j = 0 ; j < u.cols ; j++)
{
// cout << "i: " << i << ", j:" << j << endl;
double common_part = (Ex.at<double>(i,j)*u_avg.at<double>(i,j) + Ey.at<double>(i,j) * v_avg.at<double>(i,j) + Et.at<double>(i,j) ) / (pow(a,2) + pow(Ex.at<double>(i,j),2) + pow(Ey.at<double>(i,j),2) ) ;
double delta_u = ( Ex.at<double>(i,j) * common_part) ;
double delta_v = ( Ey.at<double>(i,j) * common_part) ;
u.at<double>(i,j) = u_avg.at<double>(i,j) - delta_u ;
v.at<double>(i,j) = u_avg.at<double>(i,j) - delta_v ;
}
}
// cout << "u_avg is being updated"<< endl ;
update_veloc_avg(u, &u_avg) ;
// cout << "u_avg has been updated"<< endl ;
update_veloc_avg(v, &v_avg) ;
// cout << "v_avg has been updated"<< endl ;
// imshow("U_veloc" , u) ;
// imshow("V_veloc" , v) ;
// waitKey(0) ;
}
cout << "6" << endl ;
frame2.copyTo(frame1(Rect(0, 0, frame2.cols, frame2.rows)));
cout << "7" << endl ;
vid >> frame2 ;
cout << "8" << endl ;
cvtColor(frame2 , frame2 , CV_BGR2GRAY) ;
cout << "9" << endl ;
pyrDown(frame2, frame2, Size(frame2.cols/2, frame2.rows/2)) ;
cout << "10" << endl ;
waitKey(0) ;
}
cout << "**************************************************\nSchunk ego motion estimation.\n\n\tTHE VIDEO FINISHED\n**************************************************\n" << endl ;
}
here are my other functions "calculate_Ex
", "calculate_Ey
" , "calculate_Et
" and "update_veloc_avg
" .
void calculate_EX(Mat frame1, Mat frame2, Mat *E)
{
for(int i = 0 ; i < E->rows ; i++)
{
for(int j = 0 ; j < E->cols ; j++)
{
double res = 0 - (frame1.at<double>(i,j) + frame2.at<double>(i,j)) ;
if(j < frame1.cols - 1)
res += frame1.at<double>(i,j+1) ;
if(j < frame1.cols - 1 && i < frame1.rows - 1)
res += frame1.at<double>(i+1,j+1) ;
if(i < frame1.rows - 1)
res -= frame1.at<double>(i+1,j) ;
if(j < frame2.cols - 1)
res += frame2.at<double>(i,j+1) ;
if(j < frame2.cols - 1 && i < frame2.rows - 1)
res += frame2.at<double>(i+1,j+1) ;
if(i < frame2.rows - 1)
res -= frame2.at<double>(i+1,j) ;
res *= 0.25 ;
E->at<double>(i,j) = res ;
}
}
}
void calculate_EY(Mat frame1, Mat frame2, Mat* E)
{
// int sz[] = {frame1.rows, frame1.cols};
// Mat E(2, sz, CV_32FC1, Scalar::all(0));
// Mat E = Mat::zeros(frame1.rows , frame1.cols , CV_32FC1) ;
for(int i = 0 ; i < E->rows ; i++)
{
for(int j = 0 ; j < E->cols ; j++)
{
// cout << "EY: " << i << ", " << j << " in " << frame1.rows << ", " << frame1.cols << endl ;
double res = 0 - (frame1.at<double>(i,j) + frame2.at<double>(i,j)) ;
if(i < frame1.rows - 1)
res += frame1.at<double>(i+1,j) ;
if(j < frame1.cols - 1 && i < frame1.rows - 1)
res += frame1.at<double>(i+1,j+1) ;
if(j < frame1.cols - 1)
res -= frame1.at<double>(i,j+1) ;
if(i < frame2.rows - 1)
res += frame2.at<double>(i+1,j) ;
if(j < frame2.cols - 1 && i < frame2.rows - 1)
res += frame2.at<double>(i+1,j+1) ;
if(j < frame2.cols - 1)
res -= frame2.at<double>(i,j+1) ;
res *= 0.25 ;
E->at<double>(i,j) = res ;
}
}
}
void calculate_ET(Mat frame1, Mat frame2, Mat* E)
{
// int sz[] = {frame1.rows, frame1.cols};
// Mat E(2, sz, CV_32FC1, Scalar::all(0));
// Mat E = Mat::zeros(frame1.rows , frame1.cols , CV_32FC1) ;
for(int i = 0 ; i < E->rows ; i++)
{
for(int j = 0 ; j < E->cols ; j++)
{
double res = frame2.at<double>(i,j) - frame1.at<double>(i,j) ;
if(i < frame2.rows - 1)
res += frame2.at<double>(i+1,j) - frame1.at<double>(i+1,j) ;
if(j < frame2.cols - 1)
res += frame2.at<double>(i,j+1) - frame1.at<double>(i,j+1) ;
if(j < frame2.cols - 1 && i < frame2.rows - 1)
res += frame2.at<double>(i+1,j+1) - frame1.at<double>(i+1,j+1) ;
res *= 0.25 ;
E->at<double>(i,j) = res ;
}
}
}
void update_veloc_avg(Mat v, Mat* v_avg)
{
// int sz[] = {v.rows, v.cols};
// Mat v_avg(2, sz, CV_32FC1, Scalar::all(0));
// Mat v_avg = Mat::zeros(v.rows, v.cols, CV_32FC1) ;
for(int i = 0 ; i < v_avg->rows ; i++)
{
for(int j = 0 ; j < v_avg->cols ; j++)
{
// cout << i << ", " << j << " in " << v.rows << ", " << v.cols << endl ;
double res = 0 - v.at<double>(i,j) ;
double res1 = 0 , res2 = 0 ;
if(i > 0)
res1 += v.at<double>(i-1,j) ;
if(j < v.cols - 1)
res1 += v.at<double>(i,j+1) ;
if(i < v.rows - 1)
res1 += v.at<double>(i+1,j) ;
if(j > 0)
res1 += v.at<double>(i,j-1) ;
if(i > 0 && j > 0)
res2 += v.at<double>(i-1,j-1) ;
if(i > 0 && j < v.cols - 1)
res2 += v.at<double>(i-1,j+1) ;
if((i < (v.rows -1)) && (j < (v.cols -1)))
res2 += v.at<double>(i+1,j+1) ;
if(i < v.rows -1 && j > 0)
res2 += v.at<double>(i+1,j-1) ;
res = res + ((double)1/6) * res1 + ((double)1/12) * res2 ;
v_avg->at<double>(i,j) = res ;
}
}