形态学滤波

erode

#ifndef FBC_CV_ERODE_HPP_  
#define FBC_CV_ERODE_HPP_  

/* reference: include/opencv2/imgproc.hpp 
              modules/imgproc/src/morph.cpp 
*/  

#include   
#include "core/mat.hpp"  
#include "imgproc.hpp"  
#include "filterengine.hpp"  
#include "core/core.hpp"  
#include "morph.hpp"  

namespace fbc {  

// Erodes an image by using a specific structuring element  
// \f[\texttt{ dst } (x, y) = \min _{ (x',y') : \, \texttt{ element } (x',y') \ne0 } \texttt{ src } (x + x',y+y')\f]  
// In case of multi - channel images, each channel is processed independently.  
// Erosion can be applied several ( iterations ) times.  
// support type: uchar/float, multi-channels  
template<typename _Tp, int chs>  
int erode(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst, Mat_1>& kernel,  
    Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar& borderValue = Scalar::all(DBL_MAX))  
{  
    FBC_Assert(typeid(uchar).name() == typeid(_Tp).name() || typeid(float).name() == typeid(_Tp).name()); // uchar || float  
    if (dst.empty()) {  
        dst = Mat_<_Tp, chs>(src.rows, src.cols);  
    } else {  
        FBC_Assert(src.rows == dst.rows && src.cols == dst.cols);  
    }  

    Size ksize = !kernel.empty() ? kernel.size() : Size(3, 3);  
    anchor = normalizeAnchor(anchor, ksize);  

    if (iterations == 0 || kernel.rows * kernel.cols == 1) {  
        src.copyTo(dst);  
        return 0;  
    }  

    if (kernel.empty()) {  
        kernel = Mat_1>(1 + iterations * 2, 1 + iterations * 2);  
        getStructuringElement(kernel, MORPH_RECT, Size(1 + iterations * 2, 1 + iterations * 2));  
        anchor = Point(iterations, iterations);  
        iterations = 1;  
    } else if (iterations > 1 && countNonZero(kernel) == kernel.rows * kernel.cols) {  
        anchor = Point(anchor.x*iterations, anchor.y*iterations);  
        kernel = Mat_1>(ksize.height + (iterations - 1)*(ksize.height - 1), ksize.width + (iterations - 1)*(ksize.width - 1));  
        getStructuringElement(kernel, MORPH_RECT,  
            Size(ksize.width + (iterations - 1)*(ksize.width - 1), ksize.height + (iterations - 1)*(ksize.height - 1)), anchor);  
        iterations = 1;  
    }  

    anchor = normalizeAnchor(anchor, kernel.size());  

    Ptr rowFilter;  
    Ptr columnFilter;  
    Ptr filter2D;  

    if (countNonZero(kernel) == kernel.rows*kernel.cols) {  
        // rectangular structuring element  
        rowFilter = getMorphologyRowFilter<_Tp, chs>(0, kernel.cols, anchor.x);  
        columnFilter = getMorphologyColumnFilter<_Tp, chs>(0, kernel.rows, anchor.y);  
    } else {  
        filter2D = getMorphologyFilter<_Tp, chs>(0, kernel, anchor);  
    }  

    Scalar borderValue_ = borderValue;  
    if (borderType == BORDER_CONSTANT && borderValue_ == Scalar::all(DBL_MAX)) {  
        if (sizeof(_Tp) == 1) // CV_8U  
            borderValue_ = Scalar::all((double)UCHAR_MAX);  
        else // CV_32F  
            borderValue_ = Scalar::all((double)FLT_MAX);  
    }  

    Ptr> f = makePtr>(filter2D, rowFilter, columnFilter, borderType, borderType, borderValue_);  
    f->apply(src, dst);  
    for (int i = 1; i < iterations; i++)  
        f->apply(dst, dst);  

    return 0;  
}  

} // namespace fbc  

#endif // FBC_CV_ERODE_HPP_  

dilate

#ifndef FBC_CV_DILATE_HPP_  
#define FBC_CV_DILATE_HPP_  

/* reference: include/opencv2/imgproc.hpp 
              modules/imgproc/src/morph.cpp 
*/  

#include <typeinfo>  
#include "core/mat.hpp"  
#include "imgproc.hpp"  
#include "filterengine.hpp"  
#include "core/core.hpp"  
#include "morph.hpp"  

namespace fbc {  

// Dilates an image by using a specific structuring element  
// \f[\texttt{dst} (x,y) =  \max _{(x',y'):  \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\f]  
// In case of multi - channel images, each channel is processed independently.  
// support type: uchar/float, multi-channels  
template<typename _Tp, int chs>  
int dilate(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst, Mat_<uchar, 1>& kernel,  
    Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar& borderValue = Scalar::all(DBL_MAX))  
{  
    FBC_Assert(typeid(uchar).name() == typeid(_Tp).name() || typeid(float).name() == typeid(_Tp).name()); // uchar || float  
    if (dst.empty()) {  
        dst = Mat_<_Tp, chs>(src.rows, src.cols);  
    } else {  
        FBC_Assert(src.rows == dst.rows && src.cols == dst.cols);  
    }  

    Size ksize = !kernel.empty() ? kernel.size() : Size(3, 3);  
    anchor = normalizeAnchor(anchor, ksize);  

    if (iterations == 0 || kernel.rows * kernel.cols == 1) {  
        src.copyTo(dst);  
        return 0;  
    }  

    if (kernel.empty()) {  
        kernel = Mat_<uchar, 1>(1 + iterations * 2, 1 + iterations * 2);  
        getStructuringElement(kernel, MORPH_RECT, Size(1 + iterations * 2, 1 + iterations * 2));  
        anchor = Point(iterations, iterations);  
        iterations = 1;  
    } else if (iterations > 1 && countNonZero(kernel) == kernel.rows * kernel.cols) {  
        anchor = Point(anchor.x*iterations, anchor.y*iterations);  
        kernel = Mat_<uchar, 1>(ksize.height + (iterations - 1)*(ksize.height - 1), ksize.width + (iterations - 1)*(ksize.width - 1));  
        getStructuringElement(kernel, MORPH_RECT,  
            Size(ksize.width + (iterations - 1)*(ksize.width - 1), ksize.height + (iterations - 1)*(ksize.height - 1)), anchor);  
        iterations = 1;  
    }  

    anchor = normalizeAnchor(anchor, kernel.size());  

    Ptr<BaseRowFilter> rowFilter;  
    Ptr<BaseColumnFilter> columnFilter;  
    Ptr<BaseFilter> filter2D;  

    if (countNonZero(kernel) == kernel.rows*kernel.cols) {  
        // rectangular structuring element  
        rowFilter = getMorphologyRowFilter<_Tp, chs>(1, kernel.cols, anchor.x);  
        columnFilter = getMorphologyColumnFilter<_Tp, chs>(1, kernel.rows, anchor.y);  
    } else {  
        filter2D = getMorphologyFilter<_Tp, chs>(1, kernel, anchor);  
    }  

    Scalar borderValue_ = borderValue;  
    if (borderType == BORDER_CONSTANT && borderValue_ == Scalar::all(DBL_MAX)) {  
        if (sizeof(_Tp) == 1) // CV_8U  
            borderValue_ = Scalar::all(0.);  
        else // CV_32F  
            borderValue_ = Scalar::all(-FLT_MAX);  
    }  

    Ptr<FilterEngine<_Tp, _Tp, _Tp, chs, chs, chs>> f = makePtr<FilterEngine<_Tp, _Tp, _Tp, chs, chs, chs>>(filter2D, rowFilter, columnFilter, borderType, borderType, borderValue_);  
    f->apply(src, dst);  
    for (int i = 1; i < iterations; i++)  
        f->apply(dst, dst);  

    return 0;  
}  

} // namespace fbc  

#endif // FBC_CV_DILATE_HPP_  

morphologyEx

#ifndef FBC_CV_MORPHOLOGYEX_HPP_  
#define FBC_CV_MORPHOLOGYEX_HPP_  

/* reference: include/opencv2/imgproc.hpp 
              modules/imgproc/src/morph.cpp 
*/  

#include   
#include "erode.hpp"  
#include "dilate.hpp"  

namespace fbc {  

// perform advanced morphological transformations using an erosion and dilation as basic operations  
// In case of multi - channel images, each channel is processed independently.  
// morphologyEx can be applied several ( iterations ) times.  
// op ==> enum MorphTypes  
// support type: uchar/float, multi-channels  
template<typename _Tp, int chs>  
int morphologyEx(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst, int op, const Mat_1>& kernel,  
    Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar& borderValue = Scalar::all(DBL_MAX))  
{  
    FBC_Assert(typeid(uchar).name() == typeid(_Tp).name() || typeid(float).name() == typeid(_Tp).name()); // uchar || float  
    if (dst.empty()) {  
        dst = Mat_<_Tp, chs>(src.rows, src.cols);  
    } else {  
        FBC_Assert(src.rows == dst.rows && src.cols == dst.cols);  
    }  

    Mat_1> kernel_ = kernel;  
    if (kernel_.empty()) {  
        kernel_ = Mat_1>(3, 3);  
        getStructuringElement(kernel_, MORPH_RECT, Size(3, 3), Point(1, 1));  
    }  

    switch (op) {  
        case MORPH_ERODE: {  
            erode(src, dst, kernel_, anchor, iterations, borderType, borderValue);  
            break;  
        }  
        case MORPH_DILATE: {  
            dilate(src, dst, kernel_, anchor, iterations, borderType, borderValue);  
            break;  
        }  
        case MORPH_OPEN: {  
            erode(src, dst, kernel_, anchor, iterations, borderType, borderValue);  
            dilate(dst, dst, kernel_, anchor, iterations, borderType, borderValue);  
            break;  
        }  
        case CV_MOP_CLOSE: {  
            dilate(src, dst, kernel_, anchor, iterations, borderType, borderValue);  
            erode(dst, dst, kernel_, anchor, iterations, borderType, borderValue);  
            break;  
        }  
        case CV_MOP_GRADIENT: {  
            Mat_<_Tp, chs> temp(src.rows, src.cols);  
            erode(src, temp, kernel_, anchor, iterations, borderType, borderValue);  
            dilate(src, dst, kernel_, anchor, iterations, borderType, borderValue);  
            dst -= temp;  
            break;  
        }  
        case CV_MOP_TOPHAT: {  
            Mat_<_Tp, chs> temp(src.rows, src.cols);  
            if (src.data != dst.data)  
                temp = dst;  
            erode(src, temp, kernel_, anchor, iterations, borderType, borderValue);  
            dilate(temp, temp, kernel_, anchor, iterations, borderType, borderValue);  
            dst = src - temp;  
            break;  
        }  
        case CV_MOP_BLACKHAT: {  
            Mat_<_Tp, chs> temp(src.rows, src.cols);  
            if (src.data != dst.data)  
                temp = dst;  
            dilate(src, temp, kernel_, anchor, iterations, borderType, borderValue);  
            erode(temp, temp, kernel_, anchor, iterations, borderType, borderValue);  
            dst = temp - src;  
            break;  
        }  
        case MORPH_HITMISS: {  
            FBC_Assert(typeid(uchar).name() == typeid(_Tp).name() && chs == 1);  
            Mat_1> k1 = (kernel_ == Mat_1>(kernel_.rows, kernel_.cols, Scalar::all(1)));  
            Mat_1> k2 = (kernel_ == Mat_<int, 1>(kernel_.rows, kernel_.cols, Scalar::all(-1)));  
            Mat_<_Tp, chs> e1, e2;  

            if (countNonZero(k1) <= 0)  
                e1 = src;  
            else  
                erode(src, e1, k1, anchor, iterations, borderType, borderValue);  
            if (countNonZero(k2) <= 0) {  
                e2 = src;  
            } else {  
                Mat_<_Tp, chs> src_complement;  
                bitwise_not(src, src_complement);  
                erode(src_complement, e2, k2, anchor, iterations, borderType, borderValue);  
            }  
            bitwise_and(e1, e2, dst);  
            break;  
        }  
        default:  
            FBC_Assert("unknown morphological operation");  
    }  

    return 0;  
}  

} // namespace fbc  

#endif // FBC_CV_MORPHOLOGYEX_HPP_  

你可能感兴趣的:(opencv学习笔记)