Block-matching Algorithm in OpenCV? [closed]

asked 2016-01-09 15:36:11 -0600

Cabezon667 gravatar image

updated 2016-01-10 15:25:57 -0600

Hi everyone, I have a question if its possible to find a Block Matching Compensation Algorithm in OpenCV, or if exits a more easy method to implement it.

I tried to implement it, witout success.

#include "opencv2/opencv.hpp"
#include <iostream>
#include <stdio.h>
#include <iomanip>  // for controlling float print precision
#include <sstream>  // string to number conversion


using namespace cv;
using namespace std;
typedef Point_<int> Point2i;

int main()
{

Mat prueba, Ycrcb, I1,I2;
std::vector<cv::Mat> lum1;
std::vector<cv::Mat> lum2;
Mat lumI1,lumI2;
int blocksize = 16;
std::vector<cv::Mat> blocks[blocksize*blocksize];
Mat A = imread("/home/eduardo/Documents/PROJECT DIP/project/A.jpg");
Mat B = imread("/home/eduardo/Documents/PROJECT DIP/project/B.jpg");
int rows = A.rows;
int cols = A.cols;
cout << "rows = " << rows << endl;
cout << "cols = " << cols << endl;
cvtColor(A, A, CV_BGR2YCrCb);
cvtColor(B, B, CV_BGR2YCrCb);
split(A,lum1);
split(B,lum2);
lumI1 = lum1[0];
lumI2 = lum2[0];

//method to cut the images <---- IMPORTANT!
cv::Size macroblock(blocksize,blocksize);
std::vector<Mat> smallImages;

for (int y = 0; y < rows; y += macroblock.height)
{
    for (int x = 0; x < cols; x += macroblock.width)
{
    cv::Rect rect =  cv::Rect(x,y, macroblock.width, macroblock.height);
    smallImages.push_back(cv::Mat(lumI2, rect));
}
}

//arr[ 0*cols +0 ] = .... Para el futuro.

int bRows = rows/blocksize;
int bCols = cols/blocksize;
int x =bRows; int y = bCols;
cout << "bRows = " << bRows << endl;
cout << "bCols = " << bCols << endl;
int position = (x-1)*bCols + (y-1);
cout << "position = " << position << endl;

Everything ok until here, But when i try to implement the algorithm, the result are not good. In big words, Im using Rect() to evaluate one block with another in a range of [-search:search] and when i found the minimun error, I stored at a matrix x and y. Then, I plan to fullfill the blocks into a big image, but my result of X and Y doesnt make sense.

Mat block,B2;
int TE;
int E = 255*pow(blocksize,2);
Mat Err = Mat::zeros(bRows, bCols, CV_8U);
Mat xp = Mat::zeros(bRows, bCols, CV_8U);
Mat yp = Mat::zeros(bRows, bCols, CV_8U);
for (int r =1; r<=bRows;r++)
{
    //cout <<"begining = " << varE << endl;
for (int c =1; c<=bCols;c++)
{
    int rb=r*blocksize;
    int cb=c*blocksize;
    int search=blocksize*1.5;

    for(int dr = -search; dr<=search;dr++)
    {
        for(int dc = -search; dc<=search;dc++)
        {

            if(rb+dr-blocksize>0 && rb+dr<=rows && cb+dc-blocksize>0 && cb+dc<=cols)
            {
                int x1 = cb+dc-blocksize;
                int y1 = rb+dr-blocksize;
                block = lumI1( Rect(x1, y1,16,16) );
                position = (r-1)*bCols + (c-1);
                B2 = smallImages[position];
                TE= sum(cv::abs(block - B2))[0];
                if(TE<E)
                {
                    Err.at<int>(r,c) = TE;  //store the error
                    xp.at<int>(r,c) = x1;
                    yp.at<int>(r,c) = y1;
                    E=TE;
                }
            }
        }
    }
    E = 255*pow(blocksize,2);
}
}

I will appreciate any help. The algorithm runs but the results are not good. Thank you!

UPDATED: Template Matching function could help me in this situation?

edit retag flag offensive reopen merge delete

Closed for the following reason the question is answered, right answer was accepted by Cabezon667
close date 2016-01-11 19:53:12.681224

Comments

2

This does seem to be exactly what the matchTemplate function does.

It will be significantly faster too.

Tetragramm gravatar imageTetragramm ( 2016-01-10 18:08:15 -0600 )edit

I know!, actually im working in that now and it seems nice. But anyway, I want to know what Im doing wrong in my project. Thanks again for the help.

Cabezon667 gravatar imageCabezon667 ( 2016-01-10 18:12:21 -0600 )edit

If I understand this right, you're trying to store the error of the 16x16 block with the minimum error at that location? And of course, which block and which location?

If so, shouldn't you read E from the Err matrix, rather than re-using one variable for every comparison? I would think that would replace a couple of pixels then pretty much stop, replacing a scattered few. Which would be a strange set of results.

Tetragramm gravatar imageTetragramm ( 2016-01-11 18:15:32 -0600 )edit

I will give a look. Actually, now I made it using matchTemplate technique, thanks to you. So I suposse I'll close the question. Thanks again @Tetragramm

Cabezon667 gravatar imageCabezon667 ( 2016-01-11 18:29:13 -0600 )edit