1 | initial version |
To find an icon with feature matching, it should have enough and distinctive features to be able to be detected. I must say that there are icons that wont be easy to detect with this approach.
Since your icon is not rotating or being distorted by perspective/affine projection, template matching seems me the best option for you. OpenCV has the matchTemplate function, which computes a similarity score for every pixel of the image, given a template. There is a good tutorial about this in the Tutorials section in this link.
If the icon size varies, you should try a multi-scale approach, that is, try to small templates, and increase its size until find a good detection score.
2 | No.2 Revision |
To find an icon with feature matching, it should have enough and distinctive features to be able to be detected. I must say that there are icons that wont be easy to detect with this approach.
Since your icon is not rotating or being distorted by perspective/affine projection, template matching seems me the best option for you. OpenCV has the matchTemplate function, which computes a similarity score for every pixel of the image, given a template. There is a good tutorial about this in the Tutorials section in this link.
If the icon size varies, you should try a multi-scale approach, that is, try to small templates, and increase its size until find a good detection score.
-----------POST-COMMENTARY--------------
Well, sadly I cannot provide you working code for this, but I'll try to explain you the ideia. In fact if you intend to do anything serious in OpenCV, you should familiarize yourself with its basic structures (Point, Mat, Vec...).
Indeed, the example provided always detect something, even if it is not the most adequate match. A more robust solution, would be instead get the most likely region, get a set of most likely matches. That is, for the returned matrix "result" in the code of the tutorial, instead get the maximum value of the matrix (CV_TM_CCORR, CV_TM_CCORR_NORMED, CV_TM_CCOEFF, CV_TM_CCOEFF_NORMED) or the minimum value of the matrix (CV_TM_SQDIFF, CV_TM_SQDIFF_NORMED), you should scan the "result" for the N highest/lowest values on the result matrix. You can cut some off of such candidates by using some threshold.
This will give you a set of candidates. There is a reasonable way to identify if it is a good match or not. What you can do next is try to compute the photometric parameters for each candidate. Lets, say that this template has its pixel intensities multiplied by constant factor A, and a constant "background" brightness added B in the scene. That is, every pixel of the patch/template T on the scene S will have this form:
A(T[x,y]) + B = S[u,v]
Where (x,y) is the point of template T mapped to the point (u,v) in S. At first, a good candidate would be the one where A is closest to 1.0 and B closest to 0. Positive values of A and B means a shaded template (A < 1.0 -> darker, A > 1.0 -> brighter), where A and B < 0 means are meaningless, thus a false match. Take into consideration that there can be some numerical errors due floating point representation in PCs, so A = 0.9998 and B=-0.01 still means a good match.
So, you must find the best value of A and B for each location candidate assembling a linear system using the template and the scene data. Note that, with the data from the images, this is a overdetermined system. Use Linear Least Squares in order to solve it. OpenCV provides a linear system solver with cv::solve, so you can use it to compute A and B for each candidate. If you are using a template with alpha channel, you should use a weighted variant (look for Weighted Least Squares), which OpenCV does not implement... you must do it yourself.
Now, for different sized templates, you have to try to match the templates scaled for the expected sizes. Lets, say that the default size of icons in a system are 32x32, 64x64, 128x128. You will have to compute the template matching for each of these sizes. Of course, if its size varies too much, it becomes very expensive computationally. In this case, you should rely in feature matching approaches instead template matching or combine a slower detection algorithm based in template matching followed by faster tracking algorithms or use some form of parallel execution such as multi-threading or GPU processing.
3 | No.3 Revision |
To find an icon with feature matching, it should have enough and distinctive features to be able to be detected. I must say that there are icons that wont be easy to detect with this approach.
Since your icon is not rotating or being distorted by perspective/affine projection, template matching seems me the best option for you. OpenCV has the matchTemplate function, which computes a similarity score for every pixel of the image, given a template. There is a good tutorial about this in the Tutorials section in this link.
If the icon size varies, you should try a multi-scale approach, that is, try to small templates, and increase its size until find a good detection score.
-----------POST-COMMENTARY--------------
Well, sadly I cannot provide you working code for this, but I'll try to explain you the ideia. In fact if you intend to do anything serious in OpenCV, you should familiarize yourself with its basic structures (Point, Mat, Vec...).
Indeed, the example provided always detect something, even if it is not the most adequate match. A more robust solution, would be instead get the most likely region, get a set of most likely matches. That is, for the returned matrix "result" in the code of the tutorial, instead get the maximum value of the matrix (CV_TM_CCORR, CV_TM_CCORR_NORMED, CV_TM_CCOEFF, CV_TM_CCOEFF_NORMED) or the minimum value of the matrix (CV_TM_SQDIFF, CV_TM_SQDIFF_NORMED), you should scan the "result" for the N highest/lowest values on the result matrix. You can cut some off of such candidates by using some threshold.
This will give you a set of candidates. There is a reasonable way to identify if it is a good match or not. What you can do next is try to compute the photometric parameters for each candidate. Lets, say that this template has its pixel intensities multiplied by constant factor A, and a constant "background" brightness added B in the scene. That is, every pixel of the patch/template T on the scene S will have this form:
A(T[x,y]) + B = S[u,v]
Where (x,y) is the point of template T mapped to the point (u,v) in S. At first, a good candidate would be the one where A is closest to 1.0 and B closest to 0. Positive values of A and B means a shaded template (A < 1.0 -> darker, A > 1.0 -> brighter), where A and B < 0 means are meaningless, thus a false match. Take into consideration that there can be some numerical errors due floating point representation in PCs, so A = 0.9998 and B=-0.01 still means a good match.
So, you must find the best value of A and B for each location candidate assembling a linear system using the template and the scene data. Note that, with the data from the images, this is a overdetermined system. Use Linear Least Squares in order to solve it. OpenCV provides a linear system solver with cv::solve, so you can use it to compute A and B for each candidate. If you are using a template with alpha channel, you should use a weighted variant (look for Weighted Least Squares), which OpenCV does not implement... you must do it yourself.
Now, for different sized templates, you have to try to match the templates scaled for the expected sizes. Lets, say that the default size of icons in a system are 32x32, 64x64, 128x128. You will have to compute the template matching for each of these sizes. Of course, if its size varies too much, it becomes very expensive computationally. In this case, you should rely in feature matching approaches instead template matching or combine a slower detection algorithm based in template matching followed by faster tracking algorithms or use some form of parallel execution such as multi-threading or GPU processing.