基于opencv的c++图像处理(形态学处理)

前言

基于opencv的c++接口,实现常用的形态学处理方法,包括了腐蚀、膨胀、开运算、闭运算、梯度运算、顶帽运算以及黑帽运算。

相关的opencv接口解析

CV_EXPORTS_W Mat getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));

该函数用于构造并返回可以进一步传递给#erode、#dilate 或#morphologyEx 的结构元素。 但是您也可以自己构建任意二进制掩码并将其用作结构元素。
@param shape 可能是#MorphShapes 之一的元素形状
@param ksize 结构元素的大小。
@param anchor 元素内的锚点位置。 默认值 \fKaTeX parse error: Undefined control sequence: \f at position 9: (-1, -1)\̲f̲ 表示锚点位于中心。 请注意,只有十字形元素的形状取决于锚点位置。 在其他情况下,anchor 只是调节形态操作的结果移动了多少。

//! shape of the structuring element
enum MorphShapes {
    
    
    MORPH_RECT    = 0, //!< a rectangular structuring element:  \f[E_{ij}=1\f]
    MORPH_CROSS   = 1, //!< a cross-shaped structuring element:
                       //!< \f[E_{ij} = \begin{cases} 1 & \texttt{if } {i=\texttt{anchor.y } {or } {j=\texttt{anchor.x}}} \\0 & \texttt{otherwise} \end{cases}\f]
    MORPH_ELLIPSE = 2 //!< an elliptic structuring element, that is, a filled ellipse inscribed
                      //!< into the rectangle Rect(0, 0, esize.width, 0.esize.height)
};
CV_EXPORTS_W void erode( InputArray src, OutputArray dst, InputArray kernel,
                         Point anchor = Point(-1,-1), int iterations = 1,
                         int borderType = BORDER_CONSTANT,
                         const Scalar& borderValue = morphologyDefaultBorderValue() );

该函数使用指定的结构元素腐蚀源图像,该结构元素确定取最小值的像素邻域的形状:支持就地模式。侵蚀可以应用数次(迭代)。在多通道图像的情况下,每个通道都是独立处理的。
@param src 输入图像;通道数可以是任意的,但深度应该是 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F 之一。
@param dst 输出与 src 大小和类型相同的图像。
@param kernel 用于腐蚀的内核结构元素;如果 element=Mat(),则使用 3 x 3矩形结构元素。可以使用#getStructuringElement 创建内核。
@param anchor 在元素内的位置;默认值 (-1, -1) 表示锚点位于元素中心。
@param iterations 应用侵蚀的次数。
@param borderType 像素外推方法,参见#BorderTypes。不支持#BORDER_WRAP。
@param borderValue 边界值不变的情况下。

CV_EXPORTS_W void dilate( InputArray src, OutputArray dst, InputArray kernel,
                          Point anchor = Point(-1,-1), int iterations = 1,
                          int borderType = BORDER_CONSTANT,
                          const Scalar& borderValue = morphologyDefaultBorderValue() );

该函数使用指定的结构元素扩展源图像,该结构元素确定取最大值的像素邻域的形状:支持就地模式。膨胀可以应用数次(迭代)。在在多通道图像的情况下,每个通道都是独立处理的。
@param src 输入图像;通道数可以是任意的,但深度应该是 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F 之一。
@param dst 输出与 src 大小和类型相同的图像。
@param kernel 用于膨胀的内核结构元素;如果 elemenat=Mat(),则使用 3 x 3 矩形结构元素。可以使用#getStructuringElement 创建内核
@param anchor 在元素内的位置;默认值 (-1, -1) 表示锚点位于元素中心。
@param iterations 应用膨胀的次数。
@param borderType 像素外推方法,参见#BorderTypes。不支持#BORDER_WRAP。
@param borderValue 边界值不变的情况下

CV_EXPORTS_W void morphologyEx( InputArray src, OutputArray dst,
                                int op, InputArray kernel,
                                Point anchor = Point(-1,-1), int iterations = 1,
                                int borderType = BORDER_CONSTANT,
                                const Scalar& borderValue = morphologyDefaultBorderValue() );

函数 cv::morphologyEx 可以使用腐蚀和膨胀作为基本操作来执行高级形态变换。任何操作都可以就地完成。 在多通道图像的情况下,每个通道都是独立处理的。
@param src 源图像。 通道的数量可以是任意的。 深度应该是 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F 之一。
@param dst 与源图像大小和类型相同的目标图像。
@param op 形态学操作的类型,参见#MorphTypes
@param kernel 结构元素。 它可以使用#getStructuringElement 创建。
@param anchor 与内核锚定位置。 负值表示锚点位于内核中心。
@param iterations 应用腐蚀和膨胀的次数。
@param borderType 像素外推法,见#BorderTypes。 不支持#BORDER_WRAP。
@param borderValue 边界值在恒定边界的情况下。 默认值具有特殊含义。

//! type of morphological operation
enum MorphTypes{
    
    
    MORPH_ERODE    = 0, //!< see #erode
    MORPH_DILATE   = 1, //!< see #dilate
    MORPH_OPEN     = 2, //!< an opening operation
                        //!< \f[\texttt{dst} = \mathrm{open} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \mathrm{erode} ( \texttt{src} , \texttt{element} ))\f]
    MORPH_CLOSE    = 3, //!< a closing operation
                        //!< \f[\texttt{dst} = \mathrm{close} ( \texttt{src} , \texttt{element} )= \mathrm{erode} ( \mathrm{dilate} ( \texttt{src} , \texttt{element} ))\f]
    MORPH_GRADIENT = 4, //!< a morphological gradient
                        //!< \f[\texttt{dst} = \mathrm{morph\_grad} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \texttt{src} , \texttt{element} )- \mathrm{erode} ( \texttt{src} , \texttt{element} )\f]
    MORPH_TOPHAT   = 5, //!< "top hat"
                        //!< \f[\texttt{dst} = \mathrm{tophat} ( \texttt{src} , \texttt{element} )= \texttt{src} - \mathrm{open} ( \texttt{src} , \texttt{element} )\f]
    MORPH_BLACKHAT = 6, //!< "black hat"
                        //!< \f[\texttt{dst} = \mathrm{blackhat} ( \texttt{src} , \texttt{element} )= \mathrm{close} ( \texttt{src} , \texttt{element} )- \texttt{src}\f]
    MORPH_HITMISS  = 7  //!< "hit or miss"
                        //!<   .- Only supported for CV_8UC1 binary images. A tutorial can be found in the documentation
};

示例代码

morphological.h

#pragma once
#include <iostream>
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>

using namespace std;
using namespace cv;
#define PROCESS_IMG_SUCESS 0
#define PROCESS_IMG_FAIL 1


namespace ImgEnhance
{
    
    
	//形态学处理
	class MorphologicalProcess
	{
    
    
	public:
		MorphologicalProcess() {
    
     cout << "MorphologicalProcess is being created" << endl; } // 这是构造函数声明
		~MorphologicalProcess() {
    
     cout << "MorphologicalProcess is being deleted" << endl; } // 这是析构函数声明
		int ErodeProcess(cv::Mat srcImage, cv::Mat &dstImage, int elementSize);//腐蚀
		int DilateProcess(cv::Mat srcImage, cv::Mat &dstImage, int elementSize);//膨胀
		int OpenProcess(cv::Mat srcImage, cv::Mat &dstImage, int elementSize);//开运算
		int CloseProcess(cv::Mat srcImage, cv::Mat &dstImage, int elementSize);//闭运算
		int GradientProcess(cv::Mat srcImage, cv::Mat &dstImage, int elementSize);//梯度运算(计算膨胀与腐蚀之间算术差;或膨胀结果与原图算术差;或原图与腐蚀结果算术差)
		int TopHatProcess(cv::Mat srcImage, cv::Mat &dstImage, int elementSize);//顶帽运算(计算原图与开运算之间算术差)
		int BlackHatProcess(cv::Mat srcImage, cv::Mat &dstImage, int elementSize);//黑帽运算(计算闭运算与原图之间算术差)

	};
}

morphological.cpp

#include"morphological.h"

int ImgEnhance::MorphologicalProcess::ErodeProcess(cv::Mat srcImage, cv::Mat &dstImage, int elementSize)
{
    
    
	if (srcImage.empty())
	{
    
    
		printf("cannot load!!\n");
		return 1;
	}
	// 定义结构元素
	cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(elementSize, elementSize));
	// 腐蚀操作
	cv::erode(srcImage, dstImage, element);
	return 0;

}

int ImgEnhance::MorphologicalProcess::DilateProcess(cv::Mat srcImage, cv::Mat &dstImage, int elementSize)
{
    
    
	if (srcImage.empty())
	{
    
    
		printf("cannot load!!\n");
		return 1;
	}
	// 定义结构元素
	cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(elementSize, elementSize));
	// 膨胀操作
	cv::dilate(srcImage, dstImage, element);
	return 0;

}

int ImgEnhance::MorphologicalProcess::OpenProcess(cv::Mat srcImage, cv::Mat &dstImage, int elementSize)
{
    
    
	if (srcImage.empty())
	{
    
    
		printf("cannot load!!\n");
		return 1;
	}
	// 定义结构元素
	cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(elementSize, elementSize));
	// 形态学开操作 
	cv::morphologyEx(srcImage, dstImage, cv::MORPH_OPEN, element);
	return 0;

}

int ImgEnhance::MorphologicalProcess::CloseProcess(cv::Mat srcImage, cv::Mat &dstImage, int elementSize)
{
    
    
	if (srcImage.empty())
	{
    
    
		printf("cannot load!!\n");
		return 1;
	}
	// 定义结构元素
	cv::Mat element = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(elementSize, elementSize));
	// 形态学闭操作 
	cv::morphologyEx(srcImage, dstImage, cv::MORPH_CLOSE, element);
	return 0;

}

int ImgEnhance::MorphologicalProcess::GradientProcess(cv::Mat srcImage, cv::Mat &dstImage, int elementSize)
{
    
    
	if (srcImage.empty())
	{
    
    
		printf("cannot load!!\n");
		return 1;
	}
	// 定义结构元素
	cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(elementSize, elementSize));
	// 形态学梯度
	cv::morphologyEx(srcImage, dstImage, cv::MORPH_GRADIENT, element);
	return 0;

}

int ImgEnhance::MorphologicalProcess::TopHatProcess(cv::Mat srcImage, cv::Mat &dstImage, int elementSize)
{
    
    
	if (srcImage.empty())
	{
    
    
		printf("cannot load!!\n");
		return 1;
	}
	// 定义结构元素
	cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(elementSize, elementSize));
	// 形态学Top-Hat 顶帽
	cv::morphologyEx(srcImage, dstImage, cv::MORPH_TOPHAT, element);
	return 0;

}

int ImgEnhance::MorphologicalProcess::BlackHatProcess(cv::Mat srcImage, cv::Mat &dstImage, int elementSize)
{
    
    
	if (srcImage.empty())
	{
    
    
		printf("cannot load!!\n");
		return 1;
	}
	// 定义结构元素
	cv::Mat element = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(elementSize, elementSize));
	// 形态学Black-Hat 黑帽
	cv::morphologyEx(srcImage, dstImage, cv::MORPH_BLACKHAT, element);
	return 0;

}

test.cpp

#include"morphological.h"

ImgEnhance::MorphologicalProcess ImgM;//形态学处理

int main()
{
    
    
	// 读取源图像及判断
	cv::Mat srcImage = cv::imread("circle.jpg");
	if (!srcImage.data)
	{
    
    
		return 1;
	}
	/*cv::namedWindow("原始图", 0);
	cv::imshow("原始图", srcImage);*/
	// 转化为灰度图像
	cv::Mat srcGray;
	if (srcImage.channels() == 3)
	{
    
    
		cv::cvtColor(srcImage, srcGray, COLOR_RGB2GRAY);
	}
	else
	{
    
    
		srcGray = srcImage.clone();
	}
	cv::namedWindow("灰度图", 0);
	cv::imshow("灰度图", srcGray);

	// 分通道二值化
	Mat segDst;
	cv::inRange(srcGray, cv::Scalar(0, 0, 100), cv::Scalar(40, 30, 255), segDst);


	Mat erodeImage;
	腐蚀
	ImgM.ErodeProcess(segDst, erodeImage, 5);
	cv::namedWindow("腐蚀结果图", 0);
	cv::imshow("腐蚀结果图", erodeImage);

	Mat dialateImage;
	膨胀
	ImgM.DilateProcess(segDst, dialateImage, 5);
	cv::namedWindow("膨胀结果图", 0);
	cv::imshow("膨胀结果图", dialateImage);

	Mat openImage;
	开运算
	ImgM.OpenProcess(segDst, openImage, 5);
	cv::namedWindow("开运算结果图", 0);
	cv::imshow("开运算结果图", openImage);

	Mat closeImage;
	闭运算
	ImgM.CloseProcess(segDst, closeImage, 5);
	cv::namedWindow("闭运算结果图", 0);
	cv::imshow("闭运算结果图", closeImage);

	Mat gradientImage;
	梯度运算
	ImgM.GradientProcess(srcGray, gradientImage, 3);
	cv::namedWindow("梯度运算结果图", 0);
	cv::imshow("梯度运算结果图", gradientImage);

	Mat tophatImage;
	顶帽运算
	ImgM.TopHatProcess(srcGray, tophatImage, 15);
	cv::namedWindow("顶帽运算结果图", 0);
	cv::imshow("顶帽运算结果图", tophatImage);

	Mat blockhatImage;
	黑帽运算
	ImgM.BlackHatProcess(srcGray, blockhatImage, 15);
	cv::namedWindow("黑帽运算结果图", 0);
	cv::imshow("黑帽运算结果图", blockhatImage);



	cv::waitKey(0);

	return 0;

}

结果展示

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_40118285/article/details/127004932