OpenCV代码提取:dilate函数的实现

来源:互联网 发布:美工刀片厚 编辑:程序博客网 时间:2024/06/06 12:51

Morphological Operations: A set of operations that process images based on shapes.Morphological operations apply a structuring element to an input image and generate an output image.

The most basic morphological operations are two: Erosion and Dilation. They have a wide array of uses, i.e.:

(1)、Removing noise.

(2)、Isolation of individual elements and joining disparate elements in an image.

(3)、Finding of intensity bumps or holes in an image.

数学形态学可以理解为一种滤波行为,因此也称为形态学滤波。滤波中用到的滤波器(kernal),在形态学中称为结构元素。结构元素往往是由一个特殊的形状构成,如线条、矩形、圆等。

OpenCV中的dilate函数支持多通道,各个通道膨胀处理过程独立。膨胀针对白色部分(高亮部分)。膨胀即是求局部最大值的操作,图像A与核B作卷积运算,计算核B覆盖区域的像素点的最大值,并把这个值赋值给锚点(anchor point)指定的像素。

Dilation:

(1)、This operations consists of convoluting an image A with some kernel(B), which can have any shape or size, usually a square or circle.

(2)、The kernel B has a defined anchor point, usually being the center of the kernel.

(3)、As the kernel B is scanned over the image, we compute the maximal pixel value overlapped by B and replace the image pixel in the anchor point position with that maximal value. As you can deduce, this maximizing operation causes bright regions within an image to “grow” (therefore the name dilation).


目前fbc_cv库中支持uchar和float两种数据类型,经测试,与OpenCV3.1结果完全一致。

实现代码dilate.cpp:

// fbc_cv is free software and uses the same licence as OpenCV// Email: fengbingchun@163.com#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-channelstemplate<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 || floatif (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 elementrowFilter = 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_8UborderValue_ = Scalar::all(0.);else // CV_32FborderValue_ = 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_

测试代码test_dilate.cpp:

#include "test_dilate.hpp"#include <assert.h>#include <dilate.hpp>#include <opencv2/opencv.hpp>int test_getStructuringElement(){for (int elem = 0; elem < 3; elem++) {for (int size = 0; size < 10; size++) {int type;if (elem == 0){ type = fbc::MORPH_RECT; }else if (elem == 1){ type = fbc::MORPH_CROSS; }else if (elem == 2) { type = fbc::MORPH_ELLIPSE; }fbc::Mat_<uchar, 1> element(2*size+1, 2*size+1);fbc::getStructuringElement(element, type, fbc::Size(2 * size + 1, 2 * size + 1), fbc::Point(size, size));int type_;if (elem == 0){ type_ = cv::MORPH_RECT; }else if (elem == 1){ type_ = cv::MORPH_CROSS; }else if (elem == 2) { type_ = cv::MORPH_ELLIPSE; }cv::Mat element_ = cv::getStructuringElement(type_, cv::Size(2 * size + 1, 2 * size + 1), cv::Point(size, size));assert(element.rows == element_.rows && element.cols == element.cols && element.step == element_.step);for (int y = 0; y < element.rows; y++) {const fbc::uchar* p1 = element.ptr(y);const uchar* p2 = element_.ptr(y);for (int x = 0; x < element.step; x++) {assert(p1[x] == p2[x]);if (size == 5)fprintf(stderr, "%d  ", p1[x]);}if (size == 5)fprintf(stderr, "\n");}if (size == 5)fprintf(stderr, "\n");}}return 0;}int test_dilate_uchar(){cv::Mat matSrc = cv::imread("E:/GitCode/OpenCV_Test/test_images/lena.png", 1);if (!matSrc.data) {std::cout << "read image fail" << std::endl;return -1;}int width = matSrc.cols;int height = matSrc.rows;for (int elem = 0; elem < 3; elem++) {for (int size = 0; size < 10; size++) {for (int iterations = 1; iterations < 5; iterations++) {int type;if (elem == 0){ type = fbc::MORPH_RECT; }else if (elem == 1){ type = fbc::MORPH_CROSS; }else if (elem == 2) { type = fbc::MORPH_ELLIPSE; }fbc::Mat_<uchar, 1> element(2 * size + 1, 2 * size + 1);fbc::getStructuringElement(element, type, fbc::Size(2 * size + 1, 2 * size + 1), fbc::Point(size, size));int type_;if (elem == 0){ type_ = cv::MORPH_RECT; }else if (elem == 1){ type_ = cv::MORPH_CROSS; }else if (elem == 2) { type_ = cv::MORPH_ELLIPSE; }cv::Mat element_ = cv::getStructuringElement(type_, cv::Size(2 * size + 1, 2 * size + 1), cv::Point(size, size));assert(element.rows == element_.rows && element.cols == element.cols && element.step == element_.step);for (int y = 0; y < element.rows; y++) {const fbc::uchar* p1 = element.ptr(y);const uchar* p2 = element_.ptr(y);for (int x = 0; x < element.step; x++) {assert(p1[x] == p2[x]);}}fbc::Mat3BGR mat1(height, width, matSrc.data);fbc::Mat3BGR mat2(height, width);fbc::dilate(mat1, mat2, element, fbc::Point(-1, -1), iterations, 0, fbc::Scalar::all(128));cv::Mat mat1_(height, width, CV_8UC3, matSrc.data);cv::Mat mat2_;cv::dilate(mat1_, mat2_, element_, cv::Point(-1, -1), iterations, 0, cv::Scalar::all(128));assert(mat2.rows == mat2_.rows && mat2.cols == mat2_.cols && mat2.step == mat2_.step);for (int y = 0; y < mat2.rows; y++) {const fbc::uchar* p1 = mat2.ptr(y);const uchar* p2 = mat2_.ptr(y);for (int x = 0; x < mat2.step; x++) {assert(p1[x] == p2[x]);}}}}}return 0;}int test_dilate_float(){cv::Mat matSrc = cv::imread("E:/GitCode/OpenCV_Test/test_images/lena.png", 1);if (!matSrc.data) {std::cout << "read image fail" << std::endl;return -1;}cv::cvtColor(matSrc, matSrc, CV_BGR2GRAY);matSrc.convertTo(matSrc, CV_32FC1);int width = matSrc.cols;int height = matSrc.rows;for (int elem = 0; elem < 3; elem++) {for (int size = 0; size < 10; size++) {for (int iterations = 1; iterations < 5; iterations++) {int type;if (elem == 0){ type = fbc::MORPH_RECT; }else if (elem == 1){ type = fbc::MORPH_CROSS; }else if (elem == 2) { type = fbc::MORPH_ELLIPSE; }fbc::Mat_<uchar, 1> element(2 * size + 1, 2 * size + 1);fbc::getStructuringElement(element, type, fbc::Size(2 * size + 1, 2 * size + 1), fbc::Point(size, size));int type_;if (elem == 0){ type_ = cv::MORPH_RECT; }else if (elem == 1){ type_ = cv::MORPH_CROSS; }else if (elem == 2) { type_ = cv::MORPH_ELLIPSE; }cv::Mat element_ = cv::getStructuringElement(type_, cv::Size(2 * size + 1, 2 * size + 1), cv::Point(size, size));assert(element.rows == element_.rows && element.cols == element.cols && element.step == element_.step);for (int y = 0; y < element.rows; y++) {const fbc::uchar* p1 = element.ptr(y);const uchar* p2 = element_.ptr(y);for (int x = 0; x < element.step; x++) {assert(p1[x] == p2[x]);}}fbc::Mat_<float, 1> mat1(height, width, matSrc.data);fbc::Mat_<float, 1> mat2(height, width);fbc::dilate(mat1, mat2, element, fbc::Point(-1, -1), iterations, 0, fbc::Scalar::all(128));cv::Mat mat1_(height, width, CV_32FC1, matSrc.data);cv::Mat mat2_;cv::dilate(mat1_, mat2_, element_, cv::Point(-1, -1), iterations, 0, cv::Scalar::all(128));assert(mat2.rows == mat2_.rows && mat2.cols == mat2_.cols && mat2.step == mat2_.step);for (int y = 0; y < mat2.rows; y++) {const fbc::uchar* p1 = mat2.ptr(y);const uchar* p2 = mat2_.ptr(y);for (int x = 0; x < mat2.step; x++) {assert(p1[x] == p2[x]);}}}}}return 0;}

GitHub:https://github.com/fengbingchun/OpenCV_Test

0 0