图像形态学操作之腐蚀

note

// 腐蚀

// 输入图像一般为二值图像

// 二行二列腐蚀矩阵的原点:(0,0)

// 三行三列腐蚀矩阵的原点:(1,1)

// 膨胀过程中,腐蚀矩阵的原点所在位置为锚点

// 腐蚀原理:操作过程中,若腐蚀因子是重合区域的子集,则锚点位置不腐蚀,否则为腐蚀

code

// 腐蚀
// 输入图像一般为二值图像
// 二行二列腐蚀矩阵的原点:(0,0)
// 三行三列腐蚀矩阵的原点:(1,1)
// 膨胀过程中,腐蚀矩阵的原点所在位置为锚点
// 腐蚀原理:操作过程中,若腐蚀因子是重合区域的子集,则锚点位置不腐蚀,否则为腐蚀
void MyMyErodeHorizon(Mat& src, Mat& res, uchar threshold = 255) {
	src.copyTo(res);
	Mat kernel = (Mat_<uchar>(1,3) << 255,255,255);
	int anchor = kernel.cols / 2;
	for (int i = 0; i+kernel.rows <= src.rows; i=i+kernel.rows) {
		for (int j = 0; j+kernel.cols < src.cols; j=j+kernel.cols) {
			for (int k = 0; k < kernel.cols; ++k) {
				if (src.at<uchar>(i,j+k) < threshold) {
					res.at<uchar>(i,j+anchor) = 0;
					break;
				}
			}
		}
	}
}
void MyMyErodeVertic(Mat& src, Mat& res, uchar threshold = 255) {
	Mat kernel = (Mat_<uchar>(3,1) << 255,255,255);
	src.copyTo(res);
	int anchor = kernel.rows / 2;
	for (int i = 0; i+kernel.rows <= src.rows; i=i+kernel.rows) {
		for (int j = 0; j+kernel.cols < src.cols; j=j+kernel.cols) {
			for (int k = 0; k < kernel.rows; ++k) {
				if (src.at<uchar>(i+k,j) < threshold) {
					res.at<uchar>(i+anchor,j) = 0;
					break;
				}
			}
		}
	}
}
void MyMyErodeRectangle(Mat& src, Mat& res, uchar threshold = 255) {
	Mat kernel = (Mat_<uchar>(3,3) << 255,255,255,255,255,255,255,255,255);
	src.copyTo(res);
	int anchor = kernel.rows / 2;
	bool flag = false;
	for (int r = 0; r+kernel.rows <= src.rows; r=r+kernel.rows) {
		for (int c = 0; c+kernel.cols <= src.cols; c=c+kernel.cols) {
			flag = false;
			for (int i = 0; i < kernel.rows; ++i) {
				for (int j = 0; j < kernel.cols; ++j) {
					if (src.at<uchar>(r+i,j+c) < threshold) {
						flag = true;
						break;
					}
				}
				if (flag) {
					res.at<uchar>(r+anchor,c+anchor) = 0;
					break;
				}
			}
		}
	}
}
void MyMyErodeCross(Mat& src, Mat& res, uchar threshold = 255) {
	Mat kernel = (Mat_<uchar>(3,3) << 0,255,0,255,255,255,0,255,0);
	src.copyTo(res);
	int anchor = kernel.rows / 2;
	bool flag = false;
	for (int r = 0; r+kernel.rows <= src.rows; r=r+kernel.rows) {
		for (int c = 0; c+kernel.cols <= src.cols; c=c+kernel.cols) {
			flag = false;
			for (int i = 0; i < kernel.rows; ++i) {
				for (int j = 0; j < kernel.cols; ++j) {
					if ((kernel.at<uchar>(i,j) == 255) && (src.at<uchar>(r+i,j+c) < threshold)) {
						flag = true;
						break;
					}
				}
				if (flag) {
					res.at<uchar>(r+anchor,c+anchor) = 0;
					break;
				}
			}
		}
	}
}
void MyErode(my_erode_t type, Mat& src, Mat& res) {
	Mat kernel;
	switch (type) {
		case MY_ERODE_HORIZON:
			MyMyErodeHorizon(src, res, 255);
			break;
		case MY_ERODE_VERTIC:
			MyMyErodeVertic(src, res, 255);
			break;
		case MY_ERODE_RECTANGLE:
			MyMyErodeRectangle(src, res, 255);
			break;
		case MY_ERODE_CROSS:
			MyMyErodeCross(src, res, 255);
			break;
		default:
			break;
	}
}
void MyErodeTest(void) {
	Mat src = imread("../source/LinuxLogo.jpg", IMREAD_GRAYSCALE);
	if (src.empty()) {
		return;
	}
	Mat res;

	namedWindow("src", WINDOW_NORMAL);
	namedWindow("res", WINDOW_NORMAL);

	threshold(src, src, 0, 255, THRESH_BINARY|THRESH_OTSU);
	MyErode(MY_ERODE_CROSS, src, res);

	imshow("src", src);
	imshow("res", res);

	MyWait();
	destroyAllWindows();
}

test

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值