Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

you can avoid frame3=frame1.clone();. Be careful because if your mats are unsigned type like CV_8UC3, pixel difference can gives negative values that will be saturated to 0... so that 250-230=20 but 230-250=0!! to solve this you have to define the result as signed type like CV_16SC3:

frame3 = Mat(frame1.size(),CV_16SC3)
frame3 = frame1 - frame2;  //here 230-250=-20 and 250-230=20

if you dont need of sign you can use absdiff

frame3 = Mat(frame1.size(),frame1.type())
absDiff(frame1,frame2,frame3); //here 230-250=20 and 250-230=20

you can avoid frame3=frame1.clone();. Be careful because if your mats are unsigned type like CV_8UC3, pixel difference can gives negative values that will be saturated to 0... so that 250-230=20 but 230-250=0!! to solve this you have to define the result as signed type like CV_16SC3:!!

frame3 = Mat(frame1.size(),CV_16SC3)
frame3 = frame1 - frame2;  //here 230-250=-20 and 250-230=20

if you dont need of sign you can use absdiff

frame3 = Mat(frame1.size(),frame1.type())
absDiff(frame1,frame2,frame3); //here 230-250=20 and 250-230=20

you can avoid frame3=frame1.clone();. Be careful because if your mats are unsigned type like CV_8UC3, pixel difference can gives negative values that will be saturated to 0... so that 250-230=20 but 230-250=0!!

if

  • If you dont have need of sign you can use absdiffcv::absdiff
  • if you have need of sign you have to prepare a signed Mat to store the result and use cv::subtract
  • at the end if you want just to know which pixel has changed you can use bitwise-xor that should be fast

Here is the code on how to get different types of difference available in opencv and how you can take them between 2 consecutive frames, let me change your var name...

frame3 //declare mats
cv::Mat frameCurrent, framePrev;
cv::Mat badDiff,frameAbsDiff, frameDif, frameChangeMask;
//prepare Mats
cap >> frameCurrent;
framePrev = Mat(frame1.size(),frame1.type())
absDiff(frame1,frame2,frame3); cv::Mat::zeros(frameCurrent.size(), frameCurrent.type()); // prev frame as black
//signed 16bit mat to receive signed difference
if (frameCurrent.channels() == 1)
    frameDif = cv::Mat(frameCurrent.size(), CV_16SC1);
if (frameCurrent.channels() == 3)
    frameDif = cv::Mat(frameCurrent.size(), CV_16SC3);
if (frameCurrent.channels() == 4)
    frameDif = cv::Mat(frameCurrent.size(), CV_16SC4);
while (1)
{
    if (frameCurrent.empty()) {
        std::cout << "Frame1Message->End of sequence" << std::endl;
        break;
    }
    // WARNING!!! here 250-230=20 but 230-250=0
    badDiff = frameCurrent - framePrev;
    //here 230-250=20 and 250-230=20
    cv::absdiff(frameCurrent, framePrev, frameAbsDiff);
    //here 230-250=-20 and 250-230=+20
    cv::subtract(frameCurrent, framePrev, frameDif, cv::Mat(), frameDif.type());
    // this is a changing mask that is frame1(x,y) != frame2(x,y)
    cv::bitwise_xor(frameCurrent, framePrev, frameChangeMask); 

    imshow("frameCurrent", frameCurrent);
    imshow("frameAbsDiff", frameAbsDiff);
    //To show 16 signed Mat, scale it and shift in 8bit unsigned
    //-255..-1 => 0..127 and 0..255 => 128..255;
    cv::Mat frameDiff8UC;
    frameDif.convertTo(frameDiff8UC, CV_8UC3, 0.5, 128);
    imshow("frameDif", frameDiff8UC);
    imshow("frameChangeMask", frameChangeMask);

    if (waitKey(90) == 27)
        break;

    frameCurrent.copyTo(framePrev);
    cap >> frameCurrent;
}

Be careful because if your mats are unsigned type like CV_8UC3, pixel difference can gives negative values that will be saturated to 0... so that 250-230=20 but 230-250=0!!

  • If you dont don't have need of sign you can use cv::absdiff
  • if you have need of sign you have to prepare a signed Mat to store the result and use cv::subtract
  • at the end if you want just to know which pixel has changed pixels had changed, you can use bitwise-xorcompare that should be fastor checkRange

Here is the code on how to get different types of difference available in opencv and how you can take them between 2 consecutive frames, let me change your var name...

//declare mats
cv::Mat frameCurrent, framePrev;
cv::Mat badDiff,frameAbsDiff, frameDif, frameChangeMask;
//prepare Mats
cap >> frameCurrent;
framePrev = cv::Mat::zeros(frameCurrent.size(), frameCurrent.type()); // prev frame as black
//signed 16bit mat to receive signed difference
if (frameCurrent.channels() == 1)
    frameDif = cv::Mat(frameCurrent.size(), CV_16SC1);
if (frameCurrent.channels() == 3)
    frameDif = cv::Mat(frameCurrent.size(), CV_16SC3);
if (frameCurrent.channels() == 4)
    frameDif = cv::Mat(frameCurrent.size(), CV_16SC4);
while (1)
{
    if (frameCurrent.empty()) {
        std::cout << "Frame1Message->End of sequence" << std::endl;
        break;
    }
    // WARNING!!! here 250-230=20 but 230-250=0
    badDiff = frameCurrent - framePrev;
    //here 230-250=20 and 250-230=20
    cv::absdiff(frameCurrent, framePrev, frameAbsDiff);
    //here 230-250=-20 and 250-230=+20
    cv::subtract(frameCurrent, framePrev, frameDif, cv::Mat(), frameDif.type());
    // this is a changing mask that is same as frame1(x,y) != frame2(x,y)
    cv::bitwise_xor(frameCurrent, cv::compare(frameCurrent, framePrev, frameChangeMask); 
theDiff, cv::CMP_NE);

    imshow("frameCurrent", frameCurrent);
    imshow("frameAbsDiff", frameAbsDiff);
    //To show 16 signed Mat, scale it and shift in 8bit unsigned
    //-255..-1 => 0..127 and 0..255 => 128..255;
    cv::Mat frameDiff8UC;
    frameDif.convertTo(frameDiff8UC, CV_8UC3, 0.5, 128);
    imshow("frameDif", frameDiff8UC);
    imshow("frameChangeMask", frameChangeMask);

    if (waitKey(90) == 27)
        break;

    frameCurrent.copyTo(framePrev);
    cap >> frameCurrent;
}