Алгоритм трехмерного оператора Собела в Си - PullRequest
0 голосов
/ 25 октября 2018

В настоящее время я изо всех сил пытаюсь сделать 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}}};

Но я думаю, что циклический подходнамного сексуальнее.

...