形态学操作就是基于形状的一系列图像处理操作。通过将 结构元素 作用于输入图像来产生输出图像。
最基本的形态学操作有二:腐蚀与膨胀(Erosion 与 Dilation)。
腐蚀和膨胀是对白色部分(高亮部分)而言的,不是黑色部分。膨胀就是图像中的高亮部分进行膨胀,“领域扩张”,效果图拥有比原图更大的高亮区域。腐蚀就是原图中的高亮部分被腐蚀,“领域被蚕食”,效果图拥有比原图更小的高亮区域。
一般操作之前会先用getStructuringElement取得指定形状核尺寸的内核矩阵的结构元素。核的形状可以自定义,可以是矩形、十字形、椭圆形。
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} = \fork{1}{if i=\texttt{anchor.y} or j=\texttt{anchor.x}}{0}{otherwise}\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)
};
膨胀与腐蚀可实现多种功能,如下:
膨胀就是求局部区域最大值,输入图与内核做卷积,计算出核覆盖的区域的像素点最大值,然后把这个最大值赋值给指定的像素,这一最大化操作将会导致图像中的亮区开始”扩展” ,即是膨胀效果。
公式:
函数原型:
void cv::dilate ( InputArray src,
OutputArray dst,
InputArray kernel,
Point anchor = Point(-1,-1),
int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar & borderValue = morphologyDefaultBorderValue() )
参数说明:
src 输入图像
dst 输出图像
kernel 膨胀操作的核,为NULL时,默认采用参考点位于中心的3x3的核。
anchor 锚点
iterations 膨胀操作的次数,默认为1次
borderType 用于推断图像外部的某种边界
borderValue 边界为常数时的边界值
代码:
// 全局变量
Mat srcImage, erosion_dst, dilation_dst;
int erosion_size = 0;
int dilation_elem = 0;
int dilation_size = 0;
ErosionDilation::ErosionDilation(QWidget *parent) :
QWidget(parent),
ui(new Ui::ErosionDilation)
{
ui->setupUi(this);
srcImage = imread("F:/work/opencv/morph/sss.jpg");
erosion_dst = srcImage.clone();
dilation_dst = srcImage.clone();
connect(ui->horizontalSlider,&QSlider::valueChanged,[=](int value)
{
int k_size = 2*value+1;
ui->label_2->setText(QString("内核大小:%1").arg(k_size));
//Erosion(value);
Dilation(value);
});
bgrMat2Image(srcImage);
ui->radioButton_1->setChecked(true);
}
ErosionDilation::~ErosionDilation()
{
delete ui;
}
void ErosionDilation::bgrMat2Image(cv::Mat &mat)
{
cv::Mat rgb = mat.clone();
if(mat.channels() == 3)
{
cv::cvtColor(rgb, rgb, CV_BGR2RGB);
mImage = QImage((const uchar*)(rgb.data),rgb.cols,rgb.rows,rgb.cols*rgb.channels(),QImage::Format_RGB888);
}
else if(mat.channels() == 4)
{
cv::cvtColor(mat, mat, CV_BGRA2RGBA);
mImage = QImage((const uchar*)(mat.data),mat.cols,mat.rows,QImage::Format_ARGB32);
}
else
{
cv::cvtColor(mat, mat, CV_GRAY2RGB);
mImage = QImage((const uchar*)mat.data,mat.cols,mat.rows,QImage::Format_Indexed8);
}
mImage.bits();
//QLabel显示
ui->label->setPixmap(QPixmap::fromImage(mImage));
}
void ErosionDilation::Dilation(int value)
{
int dilation_type;
if(ui->radioButton_1->isCheckable())
{
dilation_type = MORPH_RECT;
}
else if(ui->radioButton_2->isCheckable())
{
dilation_type = MORPH_CROSS;
}
else if(ui->radioButton_3->isCheckable())
{
dilation_type = MORPH_ELLIPSE;
}
dilation_size = value;
Mat element = getStructuringElement( dilation_type,
Size( 2*dilation_size + 1, 2*dilation_size+1 ),
Point( dilation_size, dilation_size ) );
// 膨胀操作
dilate( srcImage, dilation_dst, element );
// 显示
bgrMat2Image(dilation_dst);
}
效果展示:
腐蚀提取的是覆盖下的相素最小值。
进行腐蚀操作时,输入图与内核做卷积,计算出核覆盖的区域的像素点最小值,然后把这个最小值赋值给指定的像素,并代替锚点位置的相素。
公式:
函数原型:
void erode( InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
参数说明:
src 输入图像
dst 输出图像
kernel 膨胀操作的核,为NULL时,默认采用参考点位于中心的3x3的核。
anchor 锚点
iterations 膨胀操作的次数,默认为1次
borderType 用于推断图像外部的某种边界
borderValue 边界为常数时的边界值
测试代码:
void ErosionDilation::Erosion(int value)
{
int erosion_type;
if(ui->radioButton_1->isCheckable() )
{
erosion_type = MORPH_RECT;
}
else if(ui->radioButton_2->isCheckable())
{
erosion_type = MORPH_CROSS;
}
else if(ui->radioButton_3->isCheckable())
{
erosion_type = MORPH_ELLIPSE;
}
erosion_size = value;
Mat element = getStructuringElement( erosion_type,
Size( 2*erosion_size + 1, 2*erosion_size+1 ),
Point( erosion_size, erosion_size ) );
// 腐蚀操作
erode( srcImage, erosion_dst, element );
// 显示
bgrMat2Image(erosion_dst);
}
效果展示:
作者:费码程序猿
欢迎技术交流:QQ:255895056
转载请注明出处,如有不当欢迎指正