原理:

腐蚀膨胀算法的基本原理很简单,与图像卷积的方法类似,给定一个窗口或者是一个特定形状的卷积核,卷积核中的值全部为1。

处理前,先将图像二值化。

如果是腐蚀操作,那么在进行卷积的操作过程当中,让卷积核与卷积核所覆盖的的图像区域的取“与”运算操作(如果图像像素值不为空就当成1处理)。如果卷积核中的所有值都是1,那么就将卷积核的锚点设置成1。

以上为腐蚀运算。

同样,在膨胀运算的过程中使用“与”运算,如果卷积核当中有一个值是1,那么就将锚点设置成1。

“卷积核”的形状及大小,在opencv程序当中可以使用getStructElement函数来获取,有三种,分别是矩形、椭圆以及十字形状。

可以在OpenCV源码当中看到其中的实现过程。

山寨代码:

下面程序只使用了矩形的卷积操作,卷积核大小3×3

void Binary(const Mat &src,Mat &dst,int threshold)
{
	CV_Assert(src.channels() == 1);
	dst.create(Size(src.cols, src.rows), src.type());
	uchar *ps = src.data;
	uchar *pd = dst.data;

	for (int row = 0; row < src.rows; row++)
	{
		for (int col = 0; col < src.cols; col++)
		{
			if (ps[(row*src.cols) + col]>threshold)
				pd[(row*src.cols) + col] = 255;
			else
				pd[(row*src.cols) + col] = 0;
		}
	}
}


void MyErosion(const Mat &src, Mat &dst)//仅使用矩形element
{
	int kernel[3][3];
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
			kernel[i][j] = 1;
	}
	CV_Assert(src.channels() == 1);
	dst.create(Size(src.cols, src.rows), src.type());
	
	uchar *ps = src.data;
	uchar *pd = dst.data;
	for (int row = 1; row < src.rows-1; row++)
	{
		for (int col = 1; col < src.cols-1; col++)
		{
			int cnt = 0;
			for (int i = -1; i <= 1; i++)
			{
				for (int j = -1; j <= 1; j++)
				{
					if (kernel[(1 + i) * 3 + j + 1] &&
						ps[(row + i)*src.cols + col + j] > 0
						)
					{
						cnt++;
					}
				}
			}
			if (cnt == 9)
				pd[(row*src.cols) + col] = 255;
			else
				pd[(row*src.cols) + col] = 0;
		}
	}
	for (int col = 0; col < src.cols; col++)
	{
		pd[col] = ps[col];
		pd[(src.rows - 1)*src.cols + col] = ps[(src.rows - 1)*src.cols + col];
	}
	for (int row = 0; row < src.rows; row++)//列
	{
		pd[row*src.cols] = ps[row*src.cols];
		pd[row*src.cols + src.cols - 1] = ps[row*src.cols + src.cols - 1];
	}
}

void MyDilate(const Mat &src, Mat &dst)
{
	int kernel[3][3];
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
			kernel[i][j] = 1;
	}
	CV_Assert(src.channels() == 1);
	dst.create(Size(src.cols, src.rows), src.type());

	uchar *ps = src.data;
	uchar *pd = dst.data;
	for (int row = 1; row < src.rows - 1; row++)
	{
		for (int col = 1; col < src.cols - 1; col++)
		{
			int cnt = 0;
			for (int i = -1; i <= 1; i++)
			{
				for (int j = -1; j <= 1; j++)
				{
					if (kernel[(1 + i) * 3 + j + 1] &&
						ps[(row + i)*src.cols + col + j] > 0
						)
					{
						cnt++;
					}
				}
			}
			if (cnt > 0)
				pd[(row*src.cols) + col] = 255;
			else
				pd[(row*src.cols) + col] = 0;
		}
	}
	for (int col = 0; col < src.cols; col++)
	{
		pd[col] = ps[col];
		pd[(src.rows - 1)*src.cols + col] = ps[(src.rows - 1)*src.cols + col];
	}
	for (int row = 0; row < src.rows; row++)//列
	{
		pd[row*src.cols] = ps[row*src.cols];
		pd[row*src.cols + src.cols - 1] = ps[row*src.cols + src.cols - 1];
	}
}
int main()
{
	ios::sync_with_stdio(false);

	Mat src = imread("src.jpg",0),gary;
	Mat dst,tmp;
	Binary(src, dst, 100);
	MyDilate(dst, tmp);
	imshow("src", src);
	imshow("tmp", tmp);
	imshow("dst", dst);
	waitKey();
	
	system("pause");
	
	return 0;
}

先读入一个灰度图,使用Binary函数二值化,然后可以调用腐蚀或者膨胀算法来实现形态学运算。

结果如下

原图是一张漂亮的东德牧羊犬
图像的腐蚀与膨胀

腐蚀
图像的腐蚀与膨胀

膨胀
图像的腐蚀与膨胀

相关文章:

  • 2021-04-12
  • 2021-04-21
  • 2022-01-02
  • 2022-03-01
猜你喜欢
  • 2021-05-04
  • 2022-12-23
  • 2021-07-21
  • 2021-12-06
  • 2022-01-06
相关资源
相似解决方案