Ask Your Question
3

Why OpenCV matchTemplate API not detect all occurrence of image?

asked 2018-03-19 02:32:56 -0600

Kailash gravatar image

updated 2018-03-21 09:45:33 -0600

I am not able detect all occurrence of template image from source image. Please look attache below file and code for the same.

source Image: C:\fakepath\source.JPG

Template Image: C:\fakepath\target.jpg

In the source image there are 3 occurrence of template but matchTemplate API give only two( first and third). The second occurrence not found with 0.98 threshold. I can found the second occurrence with 0.8 threshold.

Can you help me what the wrong with below code?

How detect with all 3 occurrence with 0.98 threshold?

    cv::Mat ref = cv::imread("source.JPG");
    cv::Mat tpl = cv::imread("template.jpg")

    cv::Mat gref, gtpl;
    cv::cvtColor(ref, gref, CV_BGR2GRAY);
    cv::cvtColor(tpl, gtpl, CV_BGR2GRAY);

    cv::Mat res(ref.rows - tpl.rows + 1, ref.cols - tpl.cols + 1, CV_32FC1);
    cv::matchTemplate(gref, gtpl, res, CV_TM_CCOEFF_NORMED);    

    double THRESHOLD = 0.98;

    while (true)
    {
        double minval, maxval;
        cv::Point minloc, maxloc;
        cv::minMaxLoc(res, &minval, &maxval, &minloc, &maxloc);

        if (maxval >= THRESHOLD)
        {
            cv::rectangle(ref,maxloc,cv::Point(maxloc.x + tpl.cols, maxloc.y + tpl.rows),CV_RGB(0, 255, 0), 2);
            cv::floodFill(res, maxloc, cv::Scalar(0), 0, cv::Scalar(.1), cv::Scalar(1.));               
        }
        else
            break;
    }

    cv::imshow("result", ref);
    cv::waitKey();
  • Thanks

Case 1- I am using method CV_TM_CCORR_NORMED, which is working fine with most of the examples. But not working in few. using match-percentage/threshold 99%. see below screen, finding folder img, but it also gives false images.

source img - C:\fakepath\Capture.PNG target img - C:\fakepath\target.png output - C:\fakepath\folderSearch.JPG

Case 2-

Not finding the target img if source img is 75% of original img. using CV_TM_CCORR_NORMED, img open mode is IMREAD_COLOR. code using same that i posted, threshold is 95%.

source img - C:\fakepath\inflow75.PNG target img - C:\fakepath\target.png

output - 20180321.2011 - C:\fakepath\BergersAlgo.PNG

I tried the recent code posted here. Target was not found, I attached the screen.

edit retag flag offensive close merge delete

1 answer

Sort by » oldest newest most voted
3

answered 2018-03-19 03:24:39 -0600

LBerger gravatar image

updated 2018-05-14 03:41:45 -0600

Ok there is a problem but I don't think it is in your code. I have already post a solution. Now CV_TM_CCOEFF_NORMED should give you, good results but I have some doubt. I normalise signal before matchTemplate : that's only difference with your code. It shouldn't be necessary with CV_TM_CCOEFF_NORMED but may be a bug ? If you read doc w and h for image T and I shouldn't be equal. Normalisation is done before match template then TM_CCORR_NORMED is the good flag You can work in color to improve results

int main(void) {
    Mat img = imread("capture.png", IMREAD_COLOR);
    Mat pen = imread("folder.png", IMREAD_COLOR);
    Mat black(3, 3, CV_8UC1, Scalar(255));
    Mat result;
    Mat penF, imgF;
    vector<Mat>imgPlane;
    vector<Mat>tplPlane;
    split(pen, tplPlane);
    split(img, imgPlane);
    for (int i = 0; i < min(tplPlane.size(), imgPlane.size()); i++)
    {
        Mat r;
        imgPlane[i].convertTo(imgF, CV_32F, 1,-mean(imgPlane[i])[0]);
        tplPlane[i].convertTo(penF, CV_32F,1, -mean(imgPlane[i])[0]);
        matchTemplate(imgF, penF, r, TM_CCORR_NORMED);
        if (result.empty())
            result = (r.clone());
        else
            result = result + (r);
   }
   imshow("result", result);
   double minf, maxf;
   minMaxLoc(result, &minf, &maxf);
    Mat plus = result > 0.99*maxf ;// why 0.92? try and test
    Mat mask;
    dilate(plus, mask, black);
    img = imread("capture.png", IMREAD_COLOR);
    img(Rect(pen.cols / 2, pen.rows / 2, plus.cols, plus.rows)).setTo(Vec3b(255, 0, 255), mask);
    imshow("plus", img);
    waitKey(0);
    return 0;
}

Why thereshold is not equal for all pens : as your image is in jpeg may be compression change pen shape and you have three pens in board image

try with https://github.com/LaurentBerger/Colo...

Now there is some limitation in this method and I think it can be improved color image is a 2D quaternion image and to solve this problem using matchtemplate method : Sangwine, S. J. and Ell, T. A.,“Hypercomplex Fourier Transforms of Color Images” and example in COLOR IMAGE REGISTRATION AND TEMPLATE MATCHING USING QUATERNION PHASE CORRELATION

edit flag offensive delete link more

Comments

I update the question at end, Pls suggest on Folder img search example.

Kailash gravatar imageKailash ( 2018-03-19 08:53:27 -0600 )edit

try in color : check new answer

LBerger gravatar imageLBerger ( 2018-03-19 09:59:54 -0600 )edit

Thanks Laurent, One case I found in which target img not found. please find "Case 2", I posted in question block.

Kailash gravatar imageKailash ( 2018-03-20 02:43:40 -0600 )edit

First one error it was not max but min for. second I think we must substract same mean values for template and image

LBerger gravatar imageLBerger ( 2018-03-20 09:32:20 -0600 )edit

I tried this code, also updates. Running on Case 2, but not able to find the target images. also cv::split function is crashing on using vector. I tried array, it is running fine. please suggest why it is crashing on split. below is code section, I changed -

    Mat imgPlane[3];

Mat tplPlane[3];

cv::split(pen, tplPlane);

cv::split(img, imgPlane);
Kailash gravatar imageKailash ( 2018-03-20 10:00:40 -0600 )edit

"crashing on using vector" error message? opencv version ? platform?

LBerger gravatar imageLBerger ( 2018-03-20 10:42:21 -0600 )edit

crashing on using vector on this line (cv::split(pen, tplPlane);) If changed to Mat array, it works.

Error - Exception thrown at 0x0F289FD0 (opencv_core330.dll) in Automation.ImageAlgorithmEXE.exe: 0xC0000005: Access violation writing location 0x61532E75.

version - 3.3.0

platform - windows 10

Kailash gravatar imageKailash ( 2018-03-21 00:17:01 -0600 )edit

I don't think there is a problem with split and vector<mat> : this old example use vector<mat> and split. If you can give a small program with same problem you can post a new question or an issue.

Automation.xxxx.exe Are you really use official opencv lib or an opencv wrapper?

You should update your code to opencv 3.4.1 (deep learning module,..)

LBerger gravatar imageLBerger ( 2018-03-21 02:35:08 -0600 )edit

Same error - Exception thrown at 0x02B00F73 (opencv_core341.dll) in Automation.ImageAlgorithmEXE.exe: 0xC0000005: Access violation writing location 0xFDFDFDFD

I upgraded to opencv 3.4.1. I am using opencv official code and compiled it myself for libs and dlls.

here is my code -

    Mat img = imread("D:\\train9\\Capture 150.PNG", IMREAD_COLOR);  
    Mat pen = imread("D:\\train9\\target2.png", IMREAD_COLOR);
    Mat black(3, 3, CV_8UC1, Scalar(255));
Mat result;
Mat penF, imgF;
std::vector<cv::Mat>imgPlane;
std::vector<cv::Mat>tplPlane;

cv::split(pen, tplPlane);   // <- **crashing**
cv::split(img, imgPlane);
for (int i = 0; i < max(3, 3); i++)
{
    Mat r;
    imgPlane[i].convertTo(imgF, CV_32F, 1, -mean(imgPlane[i])[0]);
    tplPlane[i].convertTo(penF, CV_32F, 1, -mean
Kailash gravatar imageKailash ( 2018-03-21 06:41:42 -0600 )edit

Are you trying linking release lib in debug mode?

LBerger gravatar imageLBerger ( 2018-03-21 07:57:13 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2018-03-19 02:32:56 -0600

Seen: 1,878 times

Last updated: May 14 '18