-
The basic idea is to read galleries incrementally, but there are some complications especially related to progress counting--if we don't read a gallery we don't know how many templates are stored in it since gallery formats aren't nice enough to provide headers with that information. One solution to the progress counting problem is to measure progress based on the position of a file pointer in the gallery file (i.e. measure the current position in the gallery file, divide by the total size of the gallery file). This is supported by expanding the Gallery API to include a totalSize method indicating the total size of the gallery file (or total number of templates if that is known), and then as templates are read, their position is stored in metadata (using the "p" key). Several galleries are updated to respect readBlockSize, and also to store position data in read templates. Support for filtering out already enrolled templates in read-mode was maintained by making the filtering an online process (part of the enrollment pipeline) rather than a batch process done before enrollment-proper starts.
-
This avoids warnings about project(file,file) shadowing project(template,template).
-
Introduces MetadataTransform and UntrainableMetadataTransform, which provide a project(file,file) interface for defining operations that only affect metadata, and do not touch matrices. Modify a number of transforms to inherit from these interfaces instead of UntrainableTransform or UntrainableMetaTransform
-
If we are doing nonsense like composing algorithms in memory, checking for a NULL parent is not a viable way to detect when smartCopy has returned a loose transform. This is because root transforms created through algorithmCore or whatever also have NULL parents, but actually they will be deleted via QSharedPointers, so adding them to a parent chain is dangerous, and they can show up as child transforms if we say attach them as children of a stream or distribute transform as part of a parallelization scheme. So, instead we add an output parameter to smartCopy indicating if the returned pointer is a newly allocated transform, that is not already set up to be deleted.
-
When setting up the stream in enroll, use the Stream interface's staging logic on the input algorithm. Making this happen is slightly complex when we don't particularly have header files, but on the plus side algorithms incorporating something like Show (e.g. ShowFaceDetection) will not be used as a single threaded stage in the process.
-
The primary addition is ProcessWrapperTransform, which takes a transform as a child, and creates a worker process that runs that transform. The main point of this is to handle cases where we interface with non-threadsafe code, and need to isolate transforms in their own processes if we want to use multiple copies of them. Inter-process communication is handled using QLocalServer/QLocalSocket, the actual worker processes are additional instance of br, which does mean this bleeds out to the public API to an unfortunate extent. Initial trvial tests seem promising, but generally we can expect performance to degrade if larger amounts of data are transfered, ideally we should do ProcessWrapper(Open+FeatureExtraction), so the data transfered to the worker is an image name, and the data transfered from the worker is a feature vector.
-
Since copies are only actually made in calls to distribute, we don't need to be initialized to set up the TimeInvariantWrapperTransform, and can do it in the constructor. This means subclasses don't need to explicitly call TimeVaryingTransform::init, although it depends quite strongly on Resource having a particular behavior.
-
Add a TimeInvariantWrapperTransform member of TimeVaryingTransform, and use that in TimeVaryingTransform::project for thread safety. This is the strategy previously used in Distribute, but putting the alias on TimeVaryingTransform gives us more safety if Distribute is not in fact the top level transform. Note: copies are only made off of calls to project, so having the alias on every TimeVaryingTransform is not too wasteful.
-
For non-leaf transforms, add a separate train method that takes QList<TemplateList> as arguments, where the separate list items correspond to the separate calls to project that would be made by parent transforms during enrollment. This is basically to deal with the effects of distribute on untrainable meta transforms such as flatten, we have to maintain a consistent grouping with project, otherwise the intermediate projection results used during training won't be consistent with what they would be during enrollment.
-
Conflicts: openbr/plugins/algorithms.cpp
-
Remove variables related to subsampling training data from Transform, move them to a new transform called DownsampleTraining, and perform subsampling in that transform, rather than as part of IndependentTransform (which depended on the subsampling variables in Transform). The prior approach was incompatible with using explicit class variable names, rather than assuming a fixed label variable. This is because the actual downsampling was carried out as part of IndependentTransform, which is not a visible part of the algorithm grammar. Removing this logic from Independent/Transform is generally desirable if only to avoid cluttering Transform with member variables that are only used some of the time, and used in a (fairly) restrictive way. The current approach of makring DownsampleTraining as an indepent transform is still limited since the downsample logic (still) cannot be applied without the split used in Independent, and also DownsampleTraining can only be implemented as a wrapper for another transform (because the argument to train is const, and performing the donwsample logic in project would also impact the testing case (since we have no way to exclude a transform used in training from use in testing, for a fixed algorithm)).
-
When doing a const project, using the default CompositeTransform implementation (with time-varying child transforms), don't make twice as many copies of things as necessary. Also, allow stream to use the CompositeTransform const project method.
-
Move TimeInvariantTransformWrapper to openbr_internal.h, add a default way for composite transforms to handle const project calls when they have time-varying child transforms.
-
Move CompositeTransform, and several other categorical abstract transform types to a new file, openbr_internal.h. Adjust files in plugins to include the new file rather than incldue openbr_plugin.h directly.