Alpha-Dependent Template Matching
I have a couple of pics that are either 8UC3 or 8UC4 and I would like to template match them almost exactly. I have done this in my code, and I would like to learn if there are better methods to optimize and simplify the code? In also know that it is currently done with block methods and fft, and also I have read about phase based matching. (CUDA's next, but this will do for now). I think I have moved everything out of the loop that is possible. Breaking during GDB sessions usually end up on the multiply or the merge in the loop. I also haven't guarded against all possible values of different types and perhaps there are better ways to guard against different types? (I think my code will fail for graychannel with alpha). Last, what is the best way to guard against matching against a black patch since everything will be 0.
I have also referred to these codes, but I developed my own:
Thanks
alpha-dependent template matching
opencv template matching and transparency
Mat templ = _templ.getMat();
Mat img = _img.getMat();
const double UCHARMAX = 255;
const double UCHARMAXINV = 1./UCHARMAX;
Mat templRed(templ.size(), CV_8UC1);
Mat templGreen(templ.size(), CV_8UC1);
Mat templBlue(templ.size(), CV_8UC1);
Mat templAlpha(templ.size(), CV_8UC1);
Mat imgRed(img.size(), CV_8UC1);
Mat imgGreen(img.size(), CV_8UC1);
Mat imgBlue(img.size(), CV_8UC1);
Mat imgAlpha(img.size(), CV_8UC1);
if(templ.depth() == CV_8U && img.depth() == CV_8U &&
(img.type() == CV_8UC3 || img.type() == CV_8UC4) &&
(templ.type() == CV_8UC3 || templ.type() == CV_8UC4)){
if(templ.type() == CV_8UC3){
templAlpha = Scalar(UCHARMAX);
cvSplit(&templ, &templRed, &templGreen, &templBlue, NULL);
}
else if(templ.type() == CV_8UC4){
cvSplit(&templ, &templBlue, &templGreen, &templRed, &templAlpha);
}
if(img.type() == CV_8UC3){
imgAlpha = Scalar(UCHARMAX);
cvSplit(&img, &imgRed, &imgGreen, &imgBlue, NULL);
}
else if(templ.type() == CV_8UC4){
cvSplit(&img, &imgBlue, &imgGreen, &imgRed, &imgAlpha);
}
Size corrSize(img.cols - templ.cols + 1, img.rows - templ.rows + 1);
_result.create(corrSize, CV_32F);
Mat result = _result.getMat();
Mat tempRed=templRed.clone();
Mat tempBlue=templBlue.clone();
Mat tempGreen=templGreen.clone();
multiply(tempRed, templAlpha, tempRed, UCHARMAXINV);
multiply(tempGreen, templAlpha, tempGreen, UCHARMAXINV);
multiply(tempBlue, templAlpha, tempBlue, UCHARMAXINV);
multiply(imgRed, imgAlpha, imgRed, UCHARMAXINV);
multiply(imgGreen, imgAlpha, imgGreen, UCHARMAXINV);
multiply(imgBlue, imgAlpha, imgBlue, UCHARMAXINV);
Mat temp(templ.size(), CV_8UC3);
cvMerge(&tempBlue, &tempGreen, &tempRed, NULL, &temp);
const double tempsum2 = norm(temp);
Mat ROI(templ.size(), CV_8UC3);
for(int i=0; i<img.rows-templ.rows; i++){
for(int j=0; j<img.cols-templ.cols; j++){
const Rect rect = Rect(j, i, templ.cols, templ.rows);
Mat ROItempRed(imgRed, rect);
Mat ROItempGreen(imgGreen, rect);
Mat ROItempBlue(imgBlue, rect);
Mat ROIRed = ROItempRed.clone();
Mat ROIBlue = ROItempBlue.clone();
Mat ROIGreen = ROItempGreen.clone();
multiply(ROIRed, templAlpha, ROIRed, UCHARMAXINV);
multiply(ROIGreen, templAlpha, ROIGreen, UCHARMAXINV);
multiply(ROIBlue, templAlpha, ROIBlue, UCHARMAXINV);
cvMerge(&ROIBlue, &ROIGreen, &ROIRed, NULL, &ROI);
Mat corr(result, Rect(j, i, 1, 1));
crossCorr( ROI, temp, corr, corr.size(), corr.type(), Point(0,0), 0, 0);
const double normalization = norm(ROI)*tempsum2;
if(normalization != 0)
corr /= normalization;
else
corr = 0.; //How should black be matched?
}
}
}
//... else ...
Would you mind also posting the crossCorr function that you used? I attempted to replace it and the for loops by MatchTemplate, but the result is innacurate. Thanks!
Nevermind, I got it to work with MatchTemplate. I was experiencing problems because the images I am matching are black and white, and I wanted to mask the white regions. As a result, the alpha channel would generate a completely black image. I just had to invert my images before applying the mask.
@LadyZayin Apologize for the late response, I didn't notice any notification on the comment. The crossCorr function I used is the same one in OpenCV, but glad that you solved the problem.
No problem, thanks anyway! :)
@awu@LadyZayin Hi awu, LadyZayin, can you send a pull request to OpenCV Github repo to add these source codes to OpenCV? Alexander has raised a feature request here: http://code.opencv.org/issues/3639. Thanks!
please change cvSplit and cvMerge to cv::split and cv::merge, since the old c-api functions won't survive the port to opencv3.0