Block-matching Algorithm in OpenCV? [closed]
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?
This does seem to be exactly what the matchTemplate function does.
It will be significantly faster too.
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.
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.
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