已经看过以下帖子:
“Don't care” elements in kernel used for binary morphological tree pruning, MATLAB
Structuring Element (Image Thinning)
我正在尝试实现细化算法(在C ++中),如here所示。 明确指出,图1中的结构元素(在链接中)将用于细化:
在每次迭代时,图像首先由左手结构元素稀释,然后由右手结构化,然后是两个元素的剩余六个90°旋转。
(图1:链接中描述的结构元素。)
所以我已经实现了结构元素,如下图所示。 (由于代码包含基本代码,因此我不在此处包含它)。例如, seLeft0 表示 s 在左上删除 e ,旋转 0 度。
(图2:在我的代码中实现的结构元素。)
为了使用该结构元素,我首先加载源文件。
// Read original image
Mat src = imread("maze.jpg",IMREAD_GRAYSCALE);
然后我声明另一个Mat文件,它将成为二进制文件中的目标文件(dst_bin)
Mat dst_bin(src.size(), src.type());
之后,我使用adaptiveThreshold函数将原始图像转换为二进制。
// Convert into binary using Adaptive th.
adaptiveThreshold(src, dst_bin, 1, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 95, -2);
到此为止我一切按预期工作。使用这段代码(因为dst_bin中的值是0或1,我将Mat文件与255相乘以便我可以看到该图。)
imshow("Maze after bin. th. ", dst_bin*255);
我得到以下迷宫:
现在繁琐的部分来了。
我应用如下结构元素: (因为应用结构化元素会导致值大于1,所以在每个filter2D之后达到阈值。)
Mat dum = dst_bin.clone();
filter2D(dst_bin, dum, dst_bin.depth(), seLeft0);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight0);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seLeft90);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight90);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seLeft180);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight180);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seLeft270);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight270);
threshold(dum, dum, 1, 1, THRESH_BINARY);
imshow("1st iteration", dum * 255);
for (int iii = 0; iii < 10; iii++)
{
filter2D(dum, dum, dst_bin.depth(), seLeft0);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight0);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seLeft90);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight90);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seLeft180);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight180);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seLeft270);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight270);
threshold(dum, dum, 1, 1, THRESH_BINARY);
}
imshow("10th iteration", dum * 255);
但不是像这里所示那样变薄:
第一次迭代后我得到以下结果:
这是第10次迭代:
正如您所看到的那样,结果不是预期的,因为我一直关注的link中对此进行了解释。
那么请你告诉我我做错了什么?
我能想到的第一件事是关于结构元素。如图1所示, DO NOT CARE 项目。我已将它们实现为零(如图2所示)。那么如何在C ++ / OpenCV中的结构元素中实现 DO NOT CARE 项呢?我应该把它们归零还是一些?或者是否有另一种方法(比如以某种方式组合它们)。
第二件事是我在OpenCV 3.x.x中使用 filter2D 。这是正确的方法吗?
总而言之,我如何实现我一直关注的链接中描述的细化算法。
您诚挚的......
PS:你可以在附录中找到代码。
-------- --------附录
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>
#include <vector>
#include <array>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
// Read original image
Mat src = imread("maze.png",IMREAD_GRAYSCALE);
Mat dst_bin(src.size(), src.type());
//if fail to read the image
if (!src.data)
{
cout << "Error loading the image" << endl;
return -1;
}
// Convert into binary using Adaptive th.
adaptiveThreshold(src, dst_bin, 1, CV_ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, 95, -2);
// now dst_bin e^x = {0,1}
imshow("Maze after bin. th. ", dst_bin*255);
double minVal;
double maxVal;
minMaxLoc(dst_bin, &minVal, &maxVal); cout << "dst_bin [" << minVal << ", " << maxVal << "]" << endl;
// seLeft0
Mat seLeft0 = getStructuringElement(MORPH_RECT, Size(3, 3));
array<array<uchar, 3>, 3> data = { { { 0, 0, 0 },{ 0, 1, 0 },{ 1, 1, 1 } } };
seLeft0 = Mat(3, 3, CV_8UC1, &data);
cout << "seLeft0 = " << endl << " " << seLeft0 << endl << endl;
// seLeft90
Mat seLeft90 = getStructuringElement(MORPH_RECT, Size(3, 3));
data = { { { 1, 0, 0 },{ 1, 1, 0 },{ 1, 0, 0 } } };
seLeft90 = Mat(3, 3, CV_8UC1, &data);
cout << "seLeft90 = " << endl << " " << seLeft90 << endl << endl;
// seLeft180
Mat seLeft180 = getStructuringElement(MORPH_RECT, Size(3, 3));
data = { { { 1, 1, 1 },{ 0, 1, 0 },{ 0, 0, 0 } } };
seLeft180 = Mat(3, 3, CV_8UC1, &data);
cout << "seLeft180 = " << endl << " " << seLeft180 << endl << endl;
// seLeft270
Mat seLeft270 = getStructuringElement(MORPH_RECT, Size(3, 3));
data = { { { 0, 0, 1 },{ 0, 1, 1 },{ 0, 0, 1 } } };
seLeft270 = Mat(3, 3, CV_8UC1, &data);
cout << "seLeft270 = " << endl << " " << seLeft270 << endl << endl;
// seRight0
Mat seRight0 = getStructuringElement(MORPH_RECT, Size(3, 3));
data = { { { 0, 0, 0 },{ 1, 1, 0 },{ 0, 1, 0 } } };
seRight0 = Mat(3, 3, CV_8UC1, &data);
cout << "seRight0 = " << endl << " " << seRight0 << endl << endl;
// seRight90
Mat seRight90 = getStructuringElement(MORPH_RECT, Size(3, 3));
data = { { { 0, 1, 0 },{ 1, 1, 0 },{ 0, 0, 0 } } };
seRight90 = Mat(3, 3, CV_8UC1, &data);
cout << "seRight90 = " << endl << " " << seRight90 << endl << endl;
// seRight180
Mat seRight180 = getStructuringElement(MORPH_RECT, Size(3, 3));
data = { { { 0, 1, 0 },{ 0, 1, 1 },{ 0, 0, 0 } } };
seRight180 = Mat(3, 3, CV_8UC1, &data);
cout << "seRight180 = " << endl << " " << seRight180 << endl << endl;
// seRight270
Mat seRight270 = getStructuringElement(MORPH_RECT, Size(3, 3));
data = { { { 0, 0, 0 },{ 0, 1, 1 },{ 0, 1, 0 } } };
seRight270 = Mat(3, 3, CV_8UC1, &data);
cout << "seRight270 = " << endl << " " << seRight270 << endl << endl;
Mat dum = dst_bin.clone();
filter2D(dst_bin, dum, dst_bin.depth(), seLeft0);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight0);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seLeft90);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight90);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seLeft180);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight180);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seLeft270);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight270);
threshold(dum, dum, 1, 1, THRESH_BINARY);
imshow("1st iteration", dum * 255);
for (int iii = 0; iii < 10; iii++)
{
filter2D(dum, dum, dst_bin.depth(), seLeft0);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight0);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seLeft90);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight90);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seLeft180);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight180);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seLeft270);
threshold(dum, dum, 1, 1, THRESH_BINARY);
filter2D(dum, dum, dst_bin.depth(), seRight270);
threshold(dum, dum, 1, 1, THRESH_BINARY);
}
imshow("10th iteration", dum * 255);
minMaxLoc(dum, &minVal, &maxVal); cout << "dum [" << minVal << ", " << maxVal << "]" << endl;
cout << endl;
waitKey();
return 0;
}