vendor: OpenCV 5.0.0 snapshot at 755e50675d97db9b7d449d8bd6b09888646f6c6e
@@ -0,0 +1,76 @@
|
||||
Disparity map post-filtering {#tutorial_ximgproc_disparity_filtering}
|
||||
============================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
Stereo matching algorithms, especially highly-optimized ones that are intended for real-time processing
|
||||
on CPU, tend to make quite a few errors on challenging sequences. These errors are usually concentrated
|
||||
in uniform texture-less areas, half-occlusions and regions near depth discontinuities. One way of dealing
|
||||
with stereo-matching errors is to use various techniques of detecting potentially inaccurate disparity
|
||||
values and invalidate them, therefore making the disparity map semi-sparse. Several such techniques are
|
||||
already implemented in the StereoBM and StereoSGBM algorithms. Another way would be to use some kind of
|
||||
filtering procedure to align the disparity map edges with those of the source image and to propagate
|
||||
the disparity values from high- to low-confidence regions like half-occlusions. Recent advances in
|
||||
edge-aware filtering have enabled performing such post-filtering under the constraints of real-time
|
||||
processing on CPU.
|
||||
|
||||
In this tutorial you will learn how to use the disparity map post-filtering to improve the results
|
||||
of StereoBM and StereoSGBM algorithms.
|
||||
|
||||
Source Stereoscopic Image
|
||||
-------------------------
|
||||
|
||||

|
||||

|
||||
|
||||
Source Code
|
||||
-----------
|
||||
|
||||
We will be using snippets from the example application, that can be downloaded [here ](https://github.com/opencv/opencv_contrib/blob/master/modules/ximgproc/samples/disparity_filtering.cpp).
|
||||
|
||||
Explanation
|
||||
-----------
|
||||
|
||||
The provided example has several options that yield different trade-offs between the speed and
|
||||
the quality of the resulting disparity map. Both the speed and the quality are measured if the user
|
||||
has provided the ground-truth disparity map. In this tutorial we will take a detailed look at the
|
||||
default pipeline, that was designed to provide the best possible quality under the constraints of
|
||||
real-time processing on CPU.
|
||||
|
||||
-# **Load left and right views**
|
||||
@snippet ximgproc/samples/disparity_filtering.cpp load_views
|
||||
We start by loading the source stereopair. For this tutorial we will take a somewhat challenging
|
||||
example from the MPI-Sintel dataset with a lot of texture-less regions.
|
||||
|
||||
-# **Prepare the views for matching**
|
||||
@snippet ximgproc/samples/disparity_filtering.cpp downscale
|
||||
We perform downscaling of the views to speed-up the matching stage at the cost of minor
|
||||
quality degradation. To get the best possible quality downscaling should be avoided.
|
||||
|
||||
-# **Perform matching and create the filter instance**
|
||||
@snippet ximgproc/samples/disparity_filtering.cpp matching
|
||||
We are using StereoBM for faster processing. If speed is not critical, though,
|
||||
StereoSGBM would provide better quality. The filter instance is created by providing
|
||||
the StereoMatcher instance that we intend to use. Another matcher instance is
|
||||
returned by the createRightMatcher function. These two matcher instances are then
|
||||
used to compute disparity maps both for the left and right views, that are required
|
||||
by the filter.
|
||||
|
||||
-# **Perform filtering**
|
||||
@snippet ximgproc/samples/disparity_filtering.cpp filtering
|
||||
Disparity maps computed by the respective matcher instances, as well as the source left view
|
||||
are passed to the filter. Note that we are using the original non-downscaled view to guide the
|
||||
filtering process. The disparity map is automatically upscaled in an edge-aware fashion to match
|
||||
the original view resolution. The result is stored in filtered_disp.
|
||||
|
||||
-# **Visualize the disparity maps**
|
||||
@snippet ximgproc/samples/disparity_filtering.cpp visualization
|
||||
We use a convenience function getDisparityVis to visualize the disparity maps. The second parameter
|
||||
defines the contrast (all disparity values are scaled by this value in the visualization).
|
||||
|
||||
Results
|
||||
-------
|
||||
|
||||

|
||||

|
||||
|
After Width: | Height: | Size: 208 KiB |
|
After Width: | Height: | Size: 260 KiB |
|
After Width: | Height: | Size: 317 KiB |
|
After Width: | Height: | Size: 214 KiB |
|
After Width: | Height: | Size: 156 KiB |
|
After Width: | Height: | Size: 176 KiB |
|
After Width: | Height: | Size: 203 KiB |
|
After Width: | Height: | Size: 225 KiB |
|
After Width: | Height: | Size: 241 KiB |
|
After Width: | Height: | Size: 213 KiB |
|
After Width: | Height: | Size: 422 KiB |
|
After Width: | Height: | Size: 161 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 58 KiB |
@@ -0,0 +1,69 @@
|
||||
Structured forests for fast edge detection {#tutorial_ximgproc_prediction}
|
||||
==========================================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
In this tutorial you will learn how to use structured forests for the purpose of edge detection in
|
||||
an image.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
@note binarization techniques like Canny edge detector are applicable to edges produced by both
|
||||
algorithms (Sobel and StructuredEdgeDetection::detectEdges).
|
||||
|
||||
Source Code
|
||||
-----------
|
||||
|
||||
@includelineno ximgproc/samples/structured_edge_detection.cpp
|
||||
|
||||
Explanation
|
||||
-----------
|
||||
|
||||
-# **Load source color image**
|
||||
|
||||
@snippet ximgproc/samples/structured_edge_detection.cpp imread
|
||||
|
||||
-# **Convert source image to float [0;1] range**
|
||||
|
||||
@snippet ximgproc/samples/structured_edge_detection.cpp convert
|
||||
|
||||
-# **Run main algorithm**
|
||||
|
||||
@snippet ximgproc/samples/structured_edge_detection.cpp create
|
||||
@snippet ximgproc/samples/structured_edge_detection.cpp detect
|
||||
@snippet ximgproc/samples/structured_edge_detection.cpp nms
|
||||
|
||||
-# **Show results**
|
||||
|
||||
@snippet ximgproc/samples/structured_edge_detection.cpp imshow
|
||||
|
||||
Literature
|
||||
----------
|
||||
|
||||
For more information, refer to the following papers : @cite Dollar2013 @cite Lim2013
|
||||
@@ -0,0 +1,73 @@
|
||||
function modelConvert(model, outname)
|
||||
%% script for converting Piotr's matlab model into YAML format
|
||||
|
||||
outfile = fopen(outname, 'w');
|
||||
|
||||
fprintf(outfile, '%%YAML:1.0\n\n');
|
||||
|
||||
fprintf(outfile, ['options:\n'...
|
||||
' numberOfTrees: 8\n'...
|
||||
' numberOfTreesToEvaluate: 4\n'...
|
||||
' selfsimilarityGridSize: 5\n'...
|
||||
' stride: 2\n'...
|
||||
' shrinkNumber: 2\n'...
|
||||
' patchSize: 32\n'...
|
||||
' patchInnerSize: 16\n'...
|
||||
' numberOfGradientOrientations: 4\n'...
|
||||
' gradientSmoothingRadius: 0\n'...
|
||||
' regFeatureSmoothingRadius: 2\n'...
|
||||
' ssFeatureSmoothingRadius: 8\n'...
|
||||
' gradientNormalizationRadius: 4\n\n']);
|
||||
|
||||
fprintf(outfile, 'childs:\n');
|
||||
printToYML(outfile, model.child', 0);
|
||||
|
||||
fprintf(outfile, 'featureIds:\n');
|
||||
printToYML(outfile, model.fids', 0);
|
||||
|
||||
fprintf(outfile, 'thresholds:\n');
|
||||
printToYML(outfile, model.thrs', 0);
|
||||
|
||||
N = 1000;
|
||||
fprintf(outfile, 'edgeBoundaries:\n');
|
||||
printToYML(outfile, model.eBnds, N);
|
||||
|
||||
fprintf(outfile, 'edgeBins:\n');
|
||||
printToYML(outfile, model.eBins, N);
|
||||
|
||||
fclose(outfile);
|
||||
gzip(outname);
|
||||
|
||||
end
|
||||
|
||||
function printToYML(outfile, A, N)
|
||||
%% append matrix A to outfile as
|
||||
%% - [a11, a12, a13, a14, ..., a1n]
|
||||
%% - [a21, a22, a23, a24, ..., a2n]
|
||||
%% ...
|
||||
%%
|
||||
%% if size(A, 2) == 1, A is printed by N elemnent per row
|
||||
|
||||
if (length(size(A)) ~= 2)
|
||||
error('printToYML: second-argument matrix should have two dimensions');
|
||||
end
|
||||
|
||||
if (size(A,2) ~= 1)
|
||||
for i=1:size(A,1)
|
||||
fprintf(outfile, ' - [');
|
||||
fprintf(outfile, '%d,', A(i, 1:end-1));
|
||||
fprintf(outfile, '%d]\n', A(i, end));
|
||||
end
|
||||
else
|
||||
len = length(A);
|
||||
for i=1:ceil(len/N)
|
||||
first = (i-1)*N + 1;
|
||||
last = min(i*N, len) - 1;
|
||||
|
||||
fprintf(outfile, ' - [');
|
||||
fprintf(outfile, '%d,', A(first:last));
|
||||
fprintf(outfile, '%d]\n', A(last + 1));
|
||||
end
|
||||
end
|
||||
fprintf(outfile, '\n');
|
||||
end
|
||||
@@ -0,0 +1,115 @@
|
||||
Structured forest training {#tutorial_ximgproc_training}
|
||||
==========================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
In this tutorial we show how to train your own structured forest using author's initial Matlab
|
||||
implementation.
|
||||
|
||||
Training pipeline
|
||||
-----------------
|
||||
|
||||
-# Download "Piotr's Toolbox" from [link](http://vision.ucsd.edu/~pdollar/toolbox/doc/index.html)
|
||||
and put it into separate directory, e.g. PToolbox
|
||||
|
||||
-# Download BSDS500 dataset from
|
||||
link \<http://www.eecs.berkeley.edu/Research/Projects/CS/vision/grouping/BSR/\> and put it into
|
||||
separate directory named exactly BSR
|
||||
-# Add both directory and their subdirectories to Matlab path.
|
||||
|
||||
-# Download detector code from
|
||||
link \<http://research.microsoft.com/en-us/downloads/389109f6-b4e8-404c-84bf-239f7cbf4e3d/\> and
|
||||
put it into root directory. Now you should have :
|
||||
@code
|
||||
.
|
||||
BSR
|
||||
PToolbox
|
||||
models
|
||||
private
|
||||
Contents.m
|
||||
edgesChns.m
|
||||
edgesDemo.m
|
||||
edgesDemoRgbd.m
|
||||
edgesDetect.m
|
||||
edgesEval.m
|
||||
edgesEvalDir.m
|
||||
edgesEvalImg.m
|
||||
edgesEvalPlot.m
|
||||
edgesSweeps.m
|
||||
edgesTrain.m
|
||||
license.txt
|
||||
readme.txt
|
||||
@endcode
|
||||
|
||||
-# Rename models/forest/modelFinal.mat to models/forest/modelFinal.mat.backup
|
||||
|
||||
-# Open edgesChns.m and comment lines 26--41. Add after commented lines the following:
|
||||
@code{.cpp}
|
||||
shrink=opts.shrink;
|
||||
chns = single(getFeatures( im2double(I) ));
|
||||
@endcode
|
||||
|
||||
-# Now it is time to compile promised getFeatures. I do with the following code:
|
||||
@code{.cpp}
|
||||
#include <cv.h>
|
||||
#include <highgui.h>
|
||||
|
||||
#include <mat.h>
|
||||
#include <mex.h>
|
||||
|
||||
#include "MxArray.hpp" // https://github.com/kyamagu/mexopencv
|
||||
|
||||
class NewRFFeatureGetter : public cv::RFFeatureGetter
|
||||
{
|
||||
public:
|
||||
NewRFFeatureGetter() : name("NewRFFeatureGetter"){}
|
||||
|
||||
virtual void getFeatures(const cv::Mat &src, NChannelsMat &features,
|
||||
const int gnrmRad, const int gsmthRad,
|
||||
const int shrink, const int outNum, const int gradNum) const
|
||||
{
|
||||
// here your feature extraction code, the default one is:
|
||||
// resulting features Mat should be n-channels, floating point matrix
|
||||
}
|
||||
|
||||
protected:
|
||||
cv::String name;
|
||||
};
|
||||
|
||||
MEXFUNCTION_LINKAGE void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
||||
{
|
||||
if (nlhs != 1) mexErrMsgTxt("nlhs != 1");
|
||||
if (nrhs != 1) mexErrMsgTxt("nrhs != 1");
|
||||
|
||||
cv::Mat src = MxArray(prhs[0]).toMat();
|
||||
src.convertTo(src, cv::DataType<float>::type);
|
||||
|
||||
std::string modelFile = MxArray(prhs[1]).toString();
|
||||
NewRFFeatureGetter *pDollar = createNewRFFeatureGetter();
|
||||
|
||||
cv::Mat edges;
|
||||
pDollar->getFeatures(src, edges, 4, 0, 2, 13, 4);
|
||||
// you can use other numbers here
|
||||
|
||||
edges.convertTo(edges, cv::DataType<double>::type);
|
||||
|
||||
plhs[0] = MxArray(edges);
|
||||
}
|
||||
@endcode
|
||||
|
||||
-# Place compiled mex file into root dir and run edgesDemo. You will need to wait a couple of hours
|
||||
after that the new model will appear inside models/forest/.
|
||||
|
||||
-# The final step is converting trained model from Matlab binary format to YAML which you can use
|
||||
with our ocv::StructuredEdgeDetection. For this purpose run
|
||||
opencv_contrib/ximgproc/tutorials/scripts/modelConvert(model, "model.yml")
|
||||
|
||||
How to use your model
|
||||
---------------------
|
||||
|
||||
Just use expanded constructor with above defined class NewRFFeatureGetter
|
||||
@code{.cpp}
|
||||
cv::StructuredEdgeDetection pDollar
|
||||
= cv::createStructuredEdgeDetection( modelName, makePtr<NewRFFeatureGetter>() );
|
||||
@endcode
|
||||