5

I am trying to find an easy solution to implement the OCR algorithm from OPenCV. I am very new to Image Processing ! I am playing a video that is decoded with specific codec using RLE algorithm.

What I would like to do is that for each decoded frame, I would like to compare it with the previous one and store the pixels that have changed between the two frames.

Most of the existing solutions gives a difference between the two frames but I would like to just keep the new pixels that have changed and store it in a table and then be able to analyze every group of pixels that have changed instead of analyzing the whole image each time.

I planned to use the "blobs detection" algoritm mais I'm stuck before being able to implement it.

Today, I'm trying this:

char *prevFrame;
char *curFrame;
QVector DiffPixel<LONG>;

//for each frame
DiffPixel.push_back(curFrame-prevFrame);

enter image description here

I really want to have the "Only changed pixel result" solution. Could anyone give me some tips or correct me if I'm going to a wrong way ?

EDIT:

New question, what if there are multiple areas of changed pixels ? Will it be possible to have one table per blocs of changed pixels or will it be only one unique table ? Take the example below:

Multiple Areas Pixels

The best thing as a result would be to have 2 mat matrices. The first matrix with the first orange square and the second matrix with the second orange square. This way, it avoids having to "scan" almost the entire frame if we store the result in one matrix only with a resolution being almost the same as the full frame.

The main goal here is to minimize the area (aka the resolution) to analyze to find text.

Robert Jones
  • 587
  • 7
  • 25

1 Answers1

9

After loading your images:

img1

enter image description here

img2

enter image description here

you can apply XOR operation to get the differences. The result has the same number of channels of the input images:

XOR

enter image description here

You can then create a binary mask OR-ing all channels:

mask

enter image description here

The you can copy the values of img2 that correspond to non-zero elements in the mask to a white image:

diff

enter image description here


UPDATE

If you have multiple areas where pixel changed, like this:

enter image description here

You'll find a difference mask (after binarization all non-zero pixels are set to 255) like:

enter image description here

You can then extract connected components and draw each connected component on a new black-initialized mask:

enter image description here

Then, as before, you can copy the values of img2 that correspond to non-zero elements in each mask to a white image.

enter image description here

The complete code for reference. Note that this is the code for the updated version of the answer. You can find the original code in the revision history.

#include <opencv2\opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;

int main()
{
    // Load the images
    Mat img1 = imread("path_to_img1");
    Mat img2 = imread("path_to_img2");

    imshow("Img1", img1);
    imshow("Img2", img2);

    // Apply XOR operation, results in a N = img1.channels() image
    Mat maskNch = (img1 ^ img2);

    imshow("XOR", maskNch);

    // Create a binary mask

    // Split each channel
    vector<Mat1b> masks;
    split(maskNch, masks);

    // Create a black mask
    Mat1b mask(maskNch.rows, maskNch.cols, uchar(0));

    // OR with each channel of the N channels mask
    for (int i = 0; i < masks.size(); ++i)
    {
        mask |= masks[i];
    }

    // Binarize mask
    mask = mask > 0;

    imshow("Mask", mask);

    // Find connected components
    vector<vector<Point>> contours;
    findContours(mask.clone(), contours, RETR_LIST, CHAIN_APPROX_SIMPLE);

    for (int i = 0; i < contours.size(); ++i)
    {
        // Create a black mask
        Mat1b mask_i(mask.rows, mask.cols, uchar(0));
        // Draw the i-th connected component
        drawContours(mask_i, contours, i, Scalar(255), CV_FILLED);

        // Create a black image
        Mat diff_i(img2.rows, img2.cols, img2.type());
        diff_i.setTo(255);

        // Copy into diff only different pixels
        img2.copyTo(diff_i, mask_i);

        imshow("Mask " + to_string(i), mask_i);
        imshow("Diff " + to_string(i), diff_i);
    }

    waitKey();
    return 0;
}
Miki
  • 40,887
  • 13
  • 123
  • 202
  • This is great. I still have a question though. What if there are multiple areas where pixels have changed ? Take a look to my EDIT in the original post. Thank you for this complete answer – Robert Jones Dec 02 '15 at 08:20
  • @DylanAlvaro updated the answer. Please let me know if it's ok for you. – Miki Dec 02 '15 at 12:02
  • The idea is very good and this is approximately what I wanted to do. The only difference is that if I apply this scheme on high resolution image with very rich content, there will be lots of difference and the contour tab will be huge. I have to find a way to limit this. Thank you very much for your help though – Robert Jones Dec 07 '15 at 16:14
  • @DylanAlvaro well, this answer your question which is not about high resolution images. You can post another question posting the actual images you're using to get specific answer. Please remember to accept / upvote this if it answers your original question. – Miki Dec 07 '15 at 16:18