Вопрос

Я рассчитал гистограмму (простой одномерный массив) для трехмерного изображения в оттенках серого.Теперь я хотел бы рассчитать градиент этой гистограммы в каждой точке.На самом деле это означало бы, что мне нужно вычислить градиент для 1D-функции в определенных точках.Однако у меня нет функции.Итак, как я могу рассчитать это с конкретными значениями x и y?

Для простоты не могли бы вы объяснить мне это на примере гистограммы - например, со следующими значениями (x - интенсивность, а y - частота этой интенсивности):

х1 = 1;у1 = 3

х2 = 2;у2 = 6

х3 = 3;у3 = 8

х4 = 4;у4 = 5

х5 = 5;у5 = 9

х6 = 6;у6 = 12

х7 = 7;у7 = 5

х8 = 8;у8 = 3

х9 = 9;у9 = 5

х10 = 10;у10 = 2

Я знаю, что это тоже математическая задача, но, поскольку мне нужно решить ее на C++, я подумал, что вы могли бы мне помочь.

Спасибо за совет, Марк

Это было полезно?

Решение

Я думаю, что вы можете рассчитать свой градиент, используя тот же подход, который использовался в обнаружении границы изображений (который является градиентным исчислением). Если ваша гистограмма находится в векторе, вы можете рассчитать приближение градиента как*:

for each point in the histogram compute 
     gradient[x] = (hist[x+1] - hist[x])

Это очень простой способ сделать это, но я не уверен, является ли наиболее точным.

  • приближение, потому что вы работаете с дискретными данными вместо непрерывных

Отредактирован:

Другие операторы могут подчеркнуть небольшие различия (небольшие градиенты станут более подчеркнутыми). Алгоритм Робертса вытекает из исчисления производного:

lim delta -> 0 = f(x + delta) - f(x) / delta

Delta бесконечно стремится к 0 (чтобы избежать 0 деления), но никогда не бывает равна нулю. Как и в памяти компьютера, это невозможно, самое маленькое, что мы можем получить от Delta, - 1 (потому что 1 - наименьшее расстояние от точек на изображении (или гистограмме)).

Замена

lim delta -> 0 to lim delta -> 1

мы получаем

f(x + 1) - f(x) / 1 = f(x + 1) - f(x) => vet[x+1] - vet[x]

Другие советы

Два в целом подходят здесь:

  1. дискретное приближение к производной
  2. Возьмите реальную производную установленную функцию

в первый случай пытаться:

g = (y_(i+1) - y_(i-1))/2*dx

во всех точках, кроме концов, или один из

g_left-end  = (y_(i+1) - y_i)/dx
g_right-end = (y_i - y_(i-1))/dx

куда dx расстояние между x точками. (В отличие от одинаково правильного определения Андрес предложил, этот симметричный. Имеет ли это значение или нет, зависит от того, что вы используете.)

в Второй случай, подходит а сплайн к вашим данным [*], и спросите библиотеку сплайна производную в той точке, которую вы хотите.

*] Используйте библиотеку! Не реализуйте это самостоятельно, если это не учебный проект. Я бы использовал КОРЕНЬ Потому что у меня уже есть это на моей машине, но это довольно тяжелый пакет, чтобы получить сплайн ...


Наконец, если вы данные шумны, вы хотите сгладить его перед тем, как сделать обнаружение склона. Это было, вы избегаете погони за шумом и смотрите только на крупномасштабные склоны.

  1. Возьмите квадратную бумагу и нарисуйте на ней гистограмму.Нарисуйте также вертикальную и горизонтальную оси через точку 0,0 вашей гистограммы.

  2. Возьмите линейку и в каждой интересующей вас точке вращайте линейку до тех пор, пока она не будет соответствовать вашему представлению о градиенте в этой точке.Очень важно, чтобы вы это сделали, ваше определение градиента — то, которое вам нужно.

  3. Как только прямой край окажется под нужным углом, нарисуйте линию под этим углом.

  4. Опустите перпендикуляры из любых двух точек на только что нарисованную линию.Следующий шаг будет проще сделать, если расстояние по горизонтали между двумя выбранными вами точками составляет около 25 % или более ширины вашей гистограммы.Из тех же двух точек нарисуйте горизонтальные линии, пересекающие вертикальную ось вашей гистограммы.

  5. Ваши линии теперь определяют расстояние по оси X и расстояние по Y, то есть длину горизонтальных/вертикальных (соответственно) осей, отмеченных их пересечениями с перпендикулярами/горизонтальными линиями.Нужный градиент — это расстояние по оси Y, разделенное на расстояние по оси X.

Теперь перевести это в код очень просто, за исключением шага 2.Вам необходимо определить критерии определения градиента в любой точке гистограммы.Простые варианты включают в себя:

а) в каждой точке положите линейку так, чтобы она проходила через эту точку и следующую справа от нее;

б) в каждой точке опустите линейку так, чтобы она проходила через эту точку и следующую слева от нее;

в) в каждой точке опустите линейку так, чтобы она прошла через точку слева и точку справа.

Возможно, вы захотите изучить более сложные варианты, такие как подгонка кривой (например, квадратичного полинома или полинома более высокого порядка) к ряду точек на гистограмме и использование ее производной для представления градиента.

Пока вы не поймете вопрос на бумаге, избегайте кодирования на C++ или чем-то еще.Как только вы это поймете, кодирование станет тривиальным.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top