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();
}