我目前正在努力用C制作3D Sobel边缘检测器(我还很陌生)。它不能完全按预期工作(突出显示实体3D对象中的非边缘),我希望有人可以看到我出了问题的地方。 (对不起,这篇文章中的空格不多)
首先,im
是已复制到tm
的输入图像,每边的边界均为1像素。
我遍历图像:
for (z = im.zlo; z <= im.zhi; z++) {
for (y = im.ylo; y <= im.yhi; y++) {
for (x = im.xlo; x <= im.xhi; x++) {
我制作了一个数组,该数组将容纳x
,y
和z
方向的更改,并循环通过3x3x3立方体:
int dxdydz[3] = {0, 0, 0};
for (a = -1; a < 2; a++) {
for (b = -1; b < 2; b++) {
for (c = -1; c < 2; c++) {
现在是这里的肉,有点棘手。我正在对我的Sobel运算符进行加权,以便如果您想象内核的一个2D表面,则该表面将是{{1,2,1},{2,4,2},{1,2,1}}。换句话说,核心像素的权重与其到中心像素的4连通度有关。
为此,我将e
定义为3-(| a | + | b | + | c |),以使其为0、1或2。内核将按3加权。每个像素处的^ e。
内核像素的符号将仅由a
,b
或c
的符号确定。
int e = 3 - (abs(a) + abs(b) + abs(c));
现在,我通过将a
,b
和c
打包成一个数组并从0-1-2循环来遍历。例如,当a
为0时,我们不想向x
添加任何值,因此我们使用if语句(深度为8级!)来排除该值。
int abc[3] = {a, b, c};
for (i = 0; i < 3; i++) {
if (abc[i] != 0) {
要添加的值应仅为该像素处的图像值乘以该像素处的内核值。 abc[i]
仅为-1或1,而(int)pow(3, e)
是接近中心的权重。
dxdydz[i] += abc[i]*(int)pow(3, e)*tm.u[z+a][y+b][x+c];
}
}
}
}
}
最后获取x
,y
和z
中平方变化之和的平方根。
int mag2 = 0;
for (i = 0; i < 3; i++) {
mag2 += (int)pow(dxdydz[i], 2);
}
im.u[z][y][x] = (int)sqrt(mag2);
}
}
}
当然,我可以遍历图像并将3x3x3立方体乘以3D内核:
int kx[3][3][3] = {{{-1,-2,-1},{0,0,0},{1,2,1}},
{{-2,-4,-2},{0,0,0},{2,4,2}},
{{-1,-2,-1},{0,0,0},{1,2,1}}};
int ky[3][3][3] = {{{-1,-2,-1},{-2,-4,-2},{-1,-2,-1}},
{{0,0,0},{0,0,0},{0,0,0}},
{{1,2,1},{2,4,2},{1,2,1}}};
int kz[3][3][3] = {{{-1,0,1},{-2,0,2},{-1,0,1}},
{{-2,0,2},{-4,0,4},{-2,0,2}},
{{-1,0,1},{-1,0,1},{-1,0,1}}};
但是我认为循环方法要性感得多。