В настоящее время я изо всех сил пытаюсь сделать 3D-детектор Sobel Edge на C (что я совсем новичок).Он работает не совсем так, как ожидалось (выделение не краев в твердом трехмерном объекте), и я надеялся, что кто-то может увидеть, где я ошибся.(и извините за плохое расстояние в этом посте)
Прежде всего, 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++) {
Теперь вот мясо, где оно становится немного хитрым.Я взвешиваю свой оператор Собеля так, что если вы представите одну двумерную поверхность ядра, это будет {{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) {
Значение дляadd должен быть просто значением изображения в этом пикселе, умноженным на значение ядра в этом пикселе.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 на трехмерные ядра:
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}}};
Но я думаю, что циклический подходнамного сексуальнее.