前几天一直在研究形态学在图像处理中的应用,查了很多资料。首先关于图像形态学的具体理论知识,课参考如下博客:
http://www.cnblogs.com/slysky/archive/2011/10/16/2214015.html
http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html
形态学操作及其公式小结:
上述操作是对二值图像进行操作的,当腐蚀、膨胀是最基本的操作,其他操作是基于这两个操作和集合论的组合。对于灰度图像来说,腐蚀和膨胀也是基本其他操作的基础,但是灰度图像腐蚀和膨胀不同于二值图像的腐蚀和膨胀。
灰度图像的腐蚀和膨胀定义如下:
(1)腐蚀:当结构元素b的原点位于(x,y)处时,用b对图像f进行腐蚀,是查找f中与结构元素b重合区域灰度级别最小的值,然后把最小的灰度值赋值给点(x,y):
(2)膨胀:当结构元素b的原点位于(x,y)处时,用b的反射(-b)对图像f进行腐蚀,是查找f中与结构元素b的反射重合区域灰度级别最大的值,然后把最大的灰度值赋值给点(x,y):
关于灰度图像的应用有:
(1)形态学梯度:
(2)顶帽变换:
(3)底帽变换:
具体代码如下:
#include<opencv.hpp>
#include<highgui.h>
#include<imgproc.hpp>
using namespace cv;
//把灰度图像转化为二值图像
Mat changeToBinaryImage(Mat grayImage)
{
Mat binaryImage(grayImage.rows, grayImage.cols, CV_8UC1, Scalar(0));
//转化为二值图像
for (int i = 0; i < grayImage.rows; i++)
{
for (int j = 0; j < grayImage.cols; j++)
{
if (grayImage.data[i*grayImage.step + j]>100)
{
binaryImage.data[i*grayImage.step + j] = 255;
}
else
{
binaryImage.data[i*grayImage.step + j] = 0;
}
}
}
imshow("binaryImage", binaryImage);
return binaryImage;
}
//创建结构元素
//一般结构元素 关于原点对称
//Mat createSE()
//{
// int a[3][3]={ 0,1,0,
// 1,1,1,
// 0,1,0};
// Mat structureElement(3, 3, CV_8UC1, a);
//}
//二值图像腐蚀操作
Mat binaryErosion(Mat binaryImage, Mat se)
{
//二值图像移动
Mat window(se.rows, se.cols, CV_8UC1);
//定义一个矩阵,存储腐蚀后的图像
Mat binaryErosionImage(binaryImage.rows, binaryImage.cols, CV_8UC1, Scalar(0));
for (int i = (se.rows-1)/2; i < binaryImage.rows-(se.rows-1)/2; i++)
{
for (int j = (se.cols - 1) / 2; j < binaryImage.cols - (se.cols - 1) / 2; j++)
{
//先设置第i行第j列像素值为255,即白色
binaryErosionImage.data[i*binaryImage.step + j] = 255;
for (int row = 0; row < se.rows; row++)
{