Ask Your Question
0

function works on video frames and images differently

asked 2018-09-04 14:47:35 -0500

Aiyyaa gravatar image

I want to fuse two videos and record fused video. Two videos have different frames per second, one video has 25 fps and another video has 10 fps and different widths and heights. And I have function, where an input is two Mat objects and an output is fused image. My problem is what sometimes my function returns totally black image, through if I save two image which produce totally black image and call this functon out of while(1) loop, I get correct(not black) image. here's my main() function:

    //TWO VIDEOS, different fps and lenghts
    VideoCapture video1("test1.mp4"); 
    VideoCapture video2("test2.mp4");

    bool v1end = false;
    bool v2end = false;
    bool even = true;
    int frames_counter = 0;

    float width = video2.get(CAP_PROP_FRAME_WIDTH);  
    float height = video2.get(CAP_PROP_FRAME_HEIGHT); 
    Mat frame1;  
    Mat frame2;

    VideoWriter video("outcpp.avi",VideoWriter::fourcc('M','J','P','G'),24, Size(width, height));

    while(1){
    //here's logic for manipulating videos with different fps
    if (!v1end) {
        if (frames_counter == 0 ){
            video1 >> frame1;
            cvtColor(frame1, frame1, COLOR_RGB2GRAY); 
        }

        if (frame1.empty()){
            v1end = true;
            video1.release();
            destroyWindow( "Frame1" );
        }
        else { 
            resize(frame1, frame1, cv::Size(width, height), 0, 0 , cv::INTER_NEAREST);
            imshow( "Frame1", frame1);
        }
    }
    if (!v2end) {
        frames_counter++;
        if (frames_counter == 3 && even == false){
            frames_counter = 0;
            even = true;
        }
        if (frames_counter == 2 && even == true){
            frames_counter = 0;
            even = false;
        }
        video2 >> frame2;  
        //cvtColor(frame, frame, CV_RGB2GRAY); 
        if (frame2.empty()){
            video2.release();
            destroyWindow( "Frame2" );
            v2end = true;
        }
        else{ 
            imshow( "Frame2", frame2);
        }
    }

    if (!v1end){
        cvtColor(frame2, frame2, COLOR_RGB2GRAY );
        //HERE IS  A FUNCTION CALL 
        Mat temp = fusion(frame1, frame2);   
        cvtColor(temp, temp, COLOR_GRAY2RGB);
        imshow( "Frame ", temp); 
        //recording a fused image
        video.write(temp);
    }
    else {
    break;
    }


    char c = (char)waitKey(1);
    if( c == 27 )     
    break;
    }

and here's my function for fusing images

Mat fusion(Mat img1, Mat img2){ 
    //Here I check for input images, img1 and img2 always are correct pictures, so, pixel values are correct
    imshow("img1",img1);
    imshow("img2",img2);

    //Logic for fusion algorithm
    int all_pixels = img1.cols*img1.rows;     
    Mat_<float> samples;
    int sum1 = 0;
    int sum2 = 0;
    samples.create(all_pixels, 2);
    int counter = 0;
    for(int i = 0; i < img1.rows; i++){
        for(int j = 0; j < img1.cols; j++){
            samples.at<float>(0,counter) = (img1.at<uchar>(i,j));
            samples.at<float>(1,counter) = (img1.at<uchar>(i,j));
            counter++;
        }
    }

    Mat cov, mu;
    cv::calcCovarMatrix(samples, cov, mu, COVAR_NORMAL | COVAR_ROWS);

    cov = cov / (samples.rows - 1);
    // If fused image is black, here is usually all are "nans"     
    cout << "cov: " << endl;
    cout << cov << endl;

    /* cout << "mu: " << endl;
    cout << mu << endl;*/

    Mat eigenvalues, eigenvectors;
    cv::eigen(cov, eigenvalues, eigenvectors);

    /* cout << "eigenvalues: " << endl;
    cout << eigenvalues << endl;*/

    /* cout << "eigenvectors: " << endl;
    cout << eigenvectors << endl;*/
    float av1 = mu.at<double>(0);
    float av2 = mu.at<double>(1);
    Mat finalImg;
    finalImg.create(img1.rows, img1.cols, CV_8UC1);

    float p1 = eigenvectors.at<double>(0,0);
    float p2 = eigenvectors.at<double>(0,1);

    for(int i = 0; i < img1.rows; i++){
        for(int j = 0; j < img1.cols; j++){
            float tmp ...
(more)
edit retag flag offensive close merge delete

Comments

2

... still the same samples.at<float>(0,counter) bug from your last post ...

berak gravatar imageberak ( 2018-09-05 00:48:32 -0500 )edit

I changed a way to copy data, instead I used the way you proposed earlier. And the problem described in this post is gone. Thank you.

Aiyyaa gravatar imageAiyyaa ( 2018-09-06 15:17:35 -0500 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2018-09-06 23:58:54 -0500

berak gravatar image

updated 2018-09-07 02:12:30 -0500

try to use more high-level opencv functionality. don't write for-loops, and use the builtin PCA:

// assumes: im1.channels() == im2.channels() &&
//          im1.size() == im2.size() 
Mat fuse_pca(const Mat &im1, const Mat &im2)
{
    Mat c1 = im1.reshape(1, im1.total() * im1.channels());
    Mat c2 = im2.reshape(1, im2.total() * im2.channels());

    Mat dat;
    hconcat(c1,c2,dat);
    dat.convertTo(dat,CV_32F);

    PCA pca(dat, noArray(), 0, 1); // keep 1 largest ev. only
    Mat_<double> ev = pca.eigenvectors;
    Mat_<double> mu = pca.mean;

    Mat fusion;
    addWeighted(c1-mu(0,0), ev(0,0), c2-mu(0,1), ev(0,1), 0, fusion);
    return fusion.reshape(im1.channels(), im1.rows);
}

mri pet pca

edit flag offensive delete link more
Login/Signup to Answer

Question Tools

1 follower

Stats

Asked: 2018-09-04 14:47:35 -0500

Seen: 73 times

Last updated: Sep 07 '18