Comparing Images for similarity - opencv

I want to compare two images (number plate images). I already separated each character from number plate using ROI command. Now, I want to compare this with the stored templates or characters to recognize the character. I want to know how to compare their similarity.I am new to openCV. I am using the standard number plates.

Opencv implements the template matching function. Here is the prototype:
void matchTemplate(const Mat& image, const Mat& templ, Mat& result, int method);
Methods of comparison are mostly based on sum of squared differences with differents normalization terms.
In case of colored images each sum in the denominator is done over all of the channels (and separate mean values are used for each channel).
Use the OpenCV function minMaxLoc to find the maximum and minimum values.

try cvMatchTemplate
void cvMatchTemplate(const CvArr* image, const CvArr* templ, CvArr* result, int method);
http://opencv.willowgarage.com/documentation/c/object_detection.html

Related

Undocumented groupRectangles variants in OpenCV

In cascadedetect.cpp in OpenCV, there are several variants of groupRectangles function:
void groupRectangles(std::vector<Rect>& rectList, int groupThreshold, double eps);
void groupRectangles(std::vector<Rect>& rectList, std::vector<int>& weights, int groupThreshold, double eps);
void groupRectangles(std::vector<Rect>& rectList, std::vector<int>& rejectLevels, std::vector<double>& levelWeights, int groupThreshold, double eps);
But in the OpenCV document, only the first variant is documented clearly, the second variant is mentioned but the weights argument is not explained. The third isn't even mentioned.
Can anyone explain the meanings of weights, rejectLevels, and levelWeights?
I read the groupRectangles source code and understood the meanings of these parameters to some degree.
groupRectangles is defined in cascadedetect.cpp, which is used by traincascade project in OpenCV. This project uses viola-jones's cascaded adaboost framework to detect objects, thus it has several cascade stages, and each of them is a strong classifier. The cascade classifier by default outputs positive only if the input sample passed every stage, but you can also set it to output the index of stage at which the sample is rejected if you want to plot a ROC curve.
So rejectLevels means the index of stage at which the rectangle is rejected. According to source code, the effect of weight is same as rejectLevels.
The above two parameters may not be very practical for us, but levelWeights is sometimes useful. It's originally the score of the rectangle outputted by the stage which rejects it, but we can use it for a more general purpose. If every rectangle has a score(no matter where it comes from), and we want to get the scores of grouped rectangles, the documented variant of groupRectangles won't help us. We must use the third one, with rejectLevels set to zeros:
vector<int> levels(wins.size(), 0);
groupRectangles(wins, levels, scores, groupThreshold, eps);
In which scores is the scores of wins. They have same size.

opencv kmeans doesn't classify data in some classes

I'm trying to implement Scalable Recognition with a Vocabulary Tree
and I'm using opencv kmeans function to cluster feature vectors so I put all my vectors in one Mat object and pass it to the function like this:
TermCriteria criteria;
criteria.epsilon = 0.1;
int attempts = 1;
int flags = KMEANS_RANDOM_CENTERS;
int K = 10;
Mat Centers;
Mat Labels;
kmeans(descriptors, K, Labels, criteria, attempts, flags, Centers);
So in the function fills "Centers" and "Labels" Mat objects like this:
Centers has K rows, 64 columns (I'm using SURF features) and one channel
Labels has as many rows as "descriptors", one column and one channel and it's values are in the range of [0 K-1]
These are the things I have checked. After I do this to all the vectors I copy vectors with the same label to a new Mat and pass it to the function again.
My problem is that sometimes one of the values in the range [0 k-1] is missing in "Label" so none of the feature vectors is classified in that cluster. I've checked it for different K's and It usually happens at least once at some level (never in the first call though). Even for K = 3.
I assume at those times the data I pass to the function is not right. So my question is that when could this happen? What things should I check on the data that I pass to the function to make sure they are valid?
Also if you have a link of any good implementations of the paper I would really appreciate it if you post it here.
It turned out that some times some clusters have less than K number of members in them so in the next level the function returns an error. Though I still haven't figured out why sometimes a cluster is empty.

How to display an image represented by three matrices in OpenCV

I have 3 matrices (R G B) in double precision format, so all I need is OpenCV version of matlab cat function to display image. If you have any sources or references please post, I would be grateful.
There is merge() for such tasks. I'm assuming that you're using C++ for the following example code, but this function is available for C and Python too (see docs).
// Suppose you have 3 matrices (instances of class cv::Mat)
// named channelR, channelG and channelB that hold your data
std::vector<cv::Mat> channels;
channels.push_back(channelR);
channels.push_back(channelG);
channels.push_back(channelB);
cv::Mat outputImage;
merge(channels, outputImage);

Clustering and kmeans have unclear documentation

I have to use kmeans in my future work, I know it is available in OpenCV as they have a documentation page on it.
I cannot make sense of the format displayed, it has also not been explained in the given details below (it appears to be details related to OpenCV 1.1). I mean, with the C++ line:
double kmeans(InputArray data, int K, InputOutputArray bestLabels, TermCriteria criteria, int attempts, int flags, OutputArray centers=noArray() )
what datatype is data, vector or matrix? which is the input matrix, which will be the output?
I am used to reading documentation like this where it is clearly stated which is the input/output/flag etc and what data types they are.
C++: void FeatureDetector::detect(const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const
I would really appreciate if someone could give a short example of kmeans being used.
P.S. the input matrix I have ready to be used for kmeans is the one produces by DescriptorExtractor::compute
Thank you
You can find examples of using most of OpenCV's functions in folder samples. In your situation take a look at these two:
kmeans.cpp
matcher_simple.cpp

How to use flann based matcher, or generally flann in opencv?

http://opencv.willowgarage.com/documentation/cpp/features2d_common_interfaces_of_descriptor_matchers.html#flannbasedmatcher
Please can somebody show me sample code or tell me how to use this class and methods.
I just want to match SURF's from a query image to those with an image set by applying Flann. I have seen many image match code in the samples but what still eludes me is a metric to quantify how similar an image is to other. Any help will be much appreciated.
Here's untested sample code
using namespace std;
using namespace cv;
Mat query; //the query image
vector<Mat> images; //set of images in your db
/* ... get the images from somewhere ... */
vector<vector<KeyPoint> > dbKeypoints;
vector<Mat> dbDescriptors;
vector<KeyPoint> queryKeypoints;
Mat queryDescriptors;
/* ... Extract the descriptors ... */
FlannBasedMatcher flannmatcher;
//train with descriptors from your db
flannmatcher.add(dbDescriptors);
flannmatcher.train();
vector<DMatch > matches;
flannmatcher.match(queryDescriptors, matches);
/* for kk=0 to matches.size()
the best match for queryKeypoints[matches[kk].queryIdx].pt
is dbKeypoints[matches[kk].imgIdx][matches[kk].trainIdx].pt
*/
Finding the most 'similar' image to the query image depends on your application. Perhaps the number of matched keypoints is adequate. Or you may need a more complex measure of similarity.
To reduce the number of false positives, you can compare the first most nearest neighbor to the second most nearest neighbor by taking the ratio of there distances.
distance(query,mostnearestneighbor)/distance(query,secondnearestneighbor) < T, the smaller the ratio is, the higher the distance of the second nearest neighbor to the query descriptor. This thus is a translation of high distinctiveness. Used in many computer vision papers that envision registration.

Resources