Hi @GaunterODim
You’re right, mapping those parameters to the parameters accepted by the search functions that Minos exports isn’t really obvious and requires a bit of explanation…
The first step is to be aware of what search functions there actually are in the MinosCVC.dll and which of the parameters from your screenshot apply to which of these functions (i’ll omit the unicode-variations):
Function |
Search Density |
Threshold |
OCR-Radius |
Locality |
ReadToken , ReadTokenFirst
|
X |
(X) |
X |
|
SearchAll |
X |
(X) |
|
X |
SearchFirst |
X |
(X) |
|
|
SearchOptimum , SubpixelOptimum
|
X |
(X) |
|
|
Now for the individual parameters:
Search Density
Mapping the search density is probably the easiest: Each of the search functions listed above accepts a long
parameter called density
. Acceptable values for this parameters range from 0
to 1000
(and are mapped to the more natural range 0.0
to 1.0
in the TeachBench).
The purpose of the density
parameter is to provide a means for subsampling to the caller/user of the Minos search functions. In many applications - particularly if large models are involved - you encounter the situation where an object located at position (x, y)
does yield quality/correspondence values high enough for object detection also at the positions nearby (x, y)
(you can actually visualize those in the TeachBench: Set density to 1.0
, threshold to a value like 0.5
to 0.6
and locality to 1
, then use the “Search All” button; you might find that around each “true” object position Minos detects there’s a more or less small cloud of additional results…). When working in such a situation, it’s not very economic to touch and investigate each and every pixel of the area of interest - instead one may use subsampling to speed the search process up significantly by touching only e.g. every other pixel in x and y direction (which would correspond to a density
call parameter of 500
).
Note that with some function calls subsampling won’t necessarily deteriorate result quality: When calling SearchOptimum
or SubpixelOptimum
with a reduced density, hill-climbing will be applied to still find the best possible result. However, please be aware that when reducing the search density below 1000
(or 1.0
) in a situation that won’t tolerate subsampling (e.g. because the classifier contains fairly small models) you’ll risk loosing valid results.
Hint: The next generation APIs CVB++, CVB.Net and CVBpy will support a double-valued parameter named density
in some of their Search
method overloads that accepts values ranging from 0.0
to 1.0
.
Threshold
The quality threshold isn’t actually a parameter of the Minos search functions - instead it’s a property of the classifier (that will actually be stored in the classifier file) that can be defined and queried with the function pair SetCLFThreshold
and GetCLFThreshold
. The threshold defined with these functions is a lower bar for the quality measure of the results reported by the Minos search functions: Any result below that threshold will be silently discarded by Minos.
One thing to be aware of is that Minos knows two ways of interpreting result quality: One is by using a accumulated unnormalized contrast sum over the features of a model, the other is a normalized grey scale correlation calculated over the features of a model. Which of these calculation models will be used depends on the setting accessible through SetCLFQualityType
and GetCLFQualityType
(the value Quality_Unnormalized
corresponds to the contrast based measurement whereas Quality_ReturnCorrelation
corresponds to the normalized correlation-based measurement). Classifiers generated by the TeachBench will automatically use the normalized method by default (in fact the other approach is no longer available in TeachBench because it offers only a negligible advantage in terms of speed these days which is outweighed by the disadvantage of using an unnormalized and therefore not globally applicable quality measure.
Hint: In the next generation APIs CVB++, CVB.Net and CVBpy, the Minos classifier object will have a double-valued property named Threshold
that accepts represents the currently set threshold value.
Locality
(I’ll spare OCR radius for the last item because it is the most difficult to understand…)
When working with the SearchAll
function which will return numerous results one sometimes struggles with false positives that are located close by some real results (imagine for example that you’ve been training Minos to recognize M’s and V’s - in an, ahem, not ideally trained classifier it might be possible that an M and a V are recognized at almost the same location). Typically the false positive has an at least slightly lower quality value, so one method of getting rid of them is by increasing the threshold (see previous paragraph).
If, however, the quality of the false positive is only slightly lower than that of the nearby good results, increasing the threshold might be undesirable and a different approach is needed, and the concept of locality offers that approach. “Locality” in this context means using the a-priori knowledge that there is a lower limit for how closely two objects may be located. For example if a classifier consists only of models of e.g. 40x40 pixels and larger, then the likelihood of finding two valid results within 20 or less pixels of each other is extremely low - which is why it makes sense to tell Minos via the Locality setting what the minimum distance between two good results should be (in the API this is mapped to the radius
parameter of the SearchAll
function).
The locality is being applied during the search process as follows:
- First of all,
SearchAll
generates a list of all encountered objects that pass the threshold criterion. These are put into a list which is then sorted by descending quality.
- Then the list is subject to a nested two-level loop: The outer level starts at index 0, the inner level starts at the starting index of the out level + 1; both iterations run to the end of the list.
- At each step the distance between the outer loop’s current element and the inner loop’s current element is calculated (using the L1 norm), and if this distance is lower than the
radius
parameter’s value, the inner loop’s current element will be erased.
Thus, at the end of the outer loop no two elements closer than radius
pixels will be left, and we can be sure that only the inferior-quality results have been discarded.
Hint: The next generation APIs CVB++, CVB.Net and CVBpy will support an integer-valued parameter named locality
in some of the SearchAll
method overloads.
OCR Radius
Now, this one’s a bit more tricky. First of all, it’s necessary to be aware how the ReadToken
family of functions works, which is actually explained in the documentation:
In other words: The Minos API uses the
ReadToken
parameter
translatedArea
to define the search area for each step (the green boxes in the sample image above). These areas are centered around the tip of the advance vectors (blue) and then searched for the next character. In the TeachBench, the
translatedArea
parameter has been mapped to a single integer value - which can be translated back to a
TArea
as follows:
int ocrRadius = 6;
TArea translatedArea;
translatedArea.X0 = -ocrRadius;
translatedArea.Y0 = -ocrRadius;
translatedArea.X1 = ocrRadius;
translatedArea.Y1 = translatedArea.Y0;
translatedArea.X2 = translatedArea.X0;
translatedArea.Y2 = ocrRadius;
Hint: In the next generation APIs CVB++, CVB.Net and CVBpy will also map the OCR Radius to an area structure, however it will be possible to generate this structure from a simple double value, e.g.
var results = myClassifier.Read(myImage.Plane[0], myImage.GetBounds(), 1.0, new Area2D(6));