Great refactoring, Thanks!

I have a note:

Unfortunately, these CV_OUT parameters don't allow to run in asynchronous mode, because we need to completely wait results here.

Possible decisions:

1) Allow to pass UMat(OutputArray) into CV_OUT parameters. Results wait will be 'added autimatically' on the `UMat.getMat(...)` call.
But it is not very clear to end-users that type of objects Mat is CV_32SC4, Rect is more usefull.

2) Separate input parameters pushing into algorithm and getting results. Something like this:

```
enum CCMode {
    CC_OBJECTS = (1 << 0), // "std::vector<Rect>& objects" result is accessible only
    CC_DETECTIONS = (1 << 1), // should not be used standalone, only with CC_OBJECTS
    CC_OBJECTS_AND_DETECTIONS = CC_OBJECTS + CC_DETECTIONS, // "std::vector<Rect>& objects" and "std::vector<int>& numDetections" results will be provided
    CC_REJECT_LEVELS = (1 << 2),
    CC_LEVEL_WEIGHTS = (1 << 3),
    CC_OBJECTS_REJECT_LEVELS_LEVEL_WEIGHTS = CC_OBJECTS | CC_REJECT_LEVELS | CC_LEVEL_WEIGHTS, // ...
}

// Only one declaration of detectMultiScale
virtual void detectMultiScale( InputArray image, CCMode = CC_OBJECTS,
                                     double scaleFactor = 1.1,
                                     int minNeighbors = 3, int flags = 0,
                                     Size minSize = Size(),
                                     Size maxSize = Size(),
                                     bool outputRejectLevels = false );

// result's getters that will be called when results are really required
virtual void getResultObjects(CV_OUT std::vector<Rect>& objects);
virtual void getResultNumDetections(CV_OUT std::vector<Rect>& objects); // call should fail if (last mode & CC_DETECTIONS) == 0
virtual void getResultRejectLevels(CV_OUT std::vector<Rect>& rejectLevels); // call should fail if last (last mode & CC_REJECT_LEVELS) == 0
...
// Or we can return a set of results at single call
virtual void getResult(
        CV_OUT std::vector<Rect>& objects,
        CV_OUT std::vector<int>& rejectLevels,
        CV_OUT std::vector<double>& levelWeights); // required mode == CC_OBJECTS_REJECT_LEVELS_LEVEL_WEIGHTS
```

3) Return an wrapper over results:

```
virtual Ptr<Objects> detectMultiScaleObjects( ... )
virtual Ptr<ObjectsWithNumDetections> detectMultiScaleObjectsWithNumDetections( ... )
virtual Ptr<ObjectsWithRejectLevels> detectMultiScaleObjectsWithRejectLevels( ... )

// And results declarations
class Objects : AlgorithmResult
{
public:
virtual void getObjects(CV_OUT std::vector<Rect>& objects) const;
// or like an iterator
virtual uint size() const;
virtual getObject(CV_IN uint index, CV_OUT Rect& object) const;
inline inline Rect getObject(CV_IN uint index) const { Rect result; getObject(index, result); return result; }
// or create a real iterator (with begin()/end()) where Type is Rect (for this result type) or a struct { Rect, int } for ObjectsWithNumDetections, etc
};
```

IMHO, 3rd variant looks better than 2nd.

===
1) We can save possibility to use old synchronous calls to users: create same non-virtual functions that call async implementation and get results into output parameters.
2) I believe you know better names for functions/classes.
3) ... I'm not sure that we currently have a time for this activity