03.05 「计算机视觉C++」图像的膨胀与腐蚀

1. 膨胀与腐蚀的原理

膨胀与腐蚀是数学形态学在图像处理中最基础的操作。对于图像的每个像素,取其一定的邻域,计算最大值/最小值作为新图像对应像素位置的像素值。其中,取最大值就是膨胀,取最小值就是腐蚀。

2. 膨胀的实现

1) OpenCV实现

在OpenCV中实现了图像膨胀的函数dilate(),可以直接调用:

<code>Mat img = imread(imagename, IMREAD_GRAYSCALE);
if (img.empty())
{
fprintf(stderr, "Can not load image %s\\n", imagename);
return -1;
}
//OpenCV方法
Mat dilated_cv;
dilate(img, dilated_cv, Mat());/<code>

dilate()函数第一个参数表示输入影像,第二个参数表示输出影像,第三个表示一个默认的核,在3X3的范围内寻找最大值。

2) C++实现

在一般的图像处理时,图像读写是由专门的组件进行读取的。这这里仍然使用OpenCV进行读取,以免增加复杂性。而在CV::Mat类中,提供了at()函数访问某一行某一列的像素值,可以通过at()函数去访问每一个像素的领域。

与之前OpenCV实现的一样,对于每一个像素,遍历以其像素位置为中心的3X3邻域,取最大值作为新图像对应位置的像素值。其具体实现如下:

<code>//从文件中读取成灰度图像
const char* imagename = "lena.jpg";

Mat img = imread(imagename, IMREAD_GRAYSCALE);
if (img.empty())
{
fprintf(stderr, "Can not load image %s\\n", imagename);
return -1;
}
//自定义方法
Mat dilated_my;
dilated_my.create(img.rows, img.cols, CV_8UC1);
for (int i = 0; i < img.rows; ++i)
{
for (int j = 0; j < img.cols; ++j)
{
//uchar minV = 255;
uchar maxV = 0;

//遍历周围最大像素值
for (int yi = i-1; yi <= i+1; yi++)
{
for (int xi = j-1; xi <= j+1; xi++)
{
if (xi<0||xi>= img.cols|| yi<0 || yi >= img.rows)
{
continue;
}
//minV = (std::min<uchar>)(minV, img.at<uchar>(yi, xi));
maxV = (std::max<uchar>)(maxV, img.at<uchar>(yi, xi));
}
}
dilated_my.at<uchar>(i, j) = maxV;
}
} /<uchar>/<uchar>/<uchar>/<uchar>/<uchar>/<code>

3) 验证

为了验证自己的算法是否正确,可以通过把两者膨胀的结果通过compare()函数进行比较。compare()函数会逐个比较两者的像素值,如果相同就会返回255(白色),如果不相同就会返回0(黑色)。整个过程的具体实现如下:

<code>#include <iostream>
#include <algorithm>
#include <opencv2>


using namespace cv;
using namespace std;

int main()
{
//从文件中读取成灰度图像
const char* imagename = "lena.jpg";
Mat img = imread(imagename, IMREAD_GRAYSCALE);
if (img.empty())
{
fprintf(stderr, "Can not load image %s\\n", imagename);
return -1;
}

//OpenCV方法
Mat dilated_cv;
dilate(img, dilated_cv, Mat());

//自定义方法
Mat dilated_my;
dilated_my.create(img.rows, img.cols, CV_8UC1);
for (int i = 0; i < img.rows; ++i)
{
for (int j = 0; j < img.cols; ++j)
{
//uchar minV = 255;
uchar maxV = 0;

//遍历周围最大像素值
for (int yi = i-1; yi <= i+1; yi++)
{
for (int xi = j-1; xi <= j+1; xi++)
{
if (xi<0||xi>= img.cols|| yi<0 || yi >= img.rows)
{
continue;
}
//minV = (std::min<uchar>)(minV, img.at<uchar>(yi, xi));
maxV = (std::max<uchar>)(maxV, img.at<uchar>(yi, xi));
}
}
dilated_my.at<uchar>(i, j) = maxV;
}
}
//比较两者的结果
Mat c;

compare(dilated_cv, dilated_my, c, CMP_EQ);

//显示
imshow("原始", img);
imshow("膨胀_cv", dilated_cv);
imshow("膨胀_my", dilated_my);
imshow("比较结果", c);
waitKey();
return 0;
}/<uchar>/<uchar>/<uchar>/<uchar>/<uchar>/<opencv2>/<algorithm>/<iostream>/<code>

其运行结果如下所示。可以发现最后的比较结果是一张白色的图像,说明自己实现的算法是正确的。

「计算机视觉C++」图像的膨胀与腐蚀


分享到:


相關文章: