Как использовать массив таблиц поиска Matlab из 512 элементов в OpenCV?

Я разрабатываю морфологические операции в OpenCV. Я пытаюсь имитировать функции remove и bridge в bwmorph Matlab. Для этого я обратился к определению функции bwmorph.m, там я получил массивы таблиц поиска для удаления и соединения.

После этого шага процедура одинакова как для Matlab, так и для OpenCV.

      lut(img,lutarray,img)

Проблема в том, что Matlab использует схему таблицы поиска с 512 элементами (9 бит), в то время как OpenCV использует схему поиска с 256 элементами (8 бит), как мне использовать lutarray Matlab в OpenCV?

Проведя небольшое исследование, я наткнулся на этот пост< /а>.

Что имеет в виду человек, когда говорит, что он «разделил» изображение от 0 до 512, а затем на две части?

Верен ли вышеописанный метод? Есть ли альтернативы этому?


person MyBushisaNeonJungle    schedule 14.05.2016    source источник
comment
Никто? Я думаю, что человек имел в виду, что он применял операции к первой (0-255) и второй (256-511) половинам гистограммы размером 512 бинов (??), но опять же это предположение с моей стороны, я может быть совершенно не в курсе с этим. Пытался связаться с этим человеком (sonmi), но он попал прямо в список рассылки @yahoogroups. Кто-нибудь может мне с этим помочь? Как использовать lutarray Matlab в openCV для двоичных изображений?   -  person MyBushisaNeonJungle    schedule 15.05.2016
comment
Пожалуйста, не портите здесь свои посты. Мы надеемся, что каждый, у кого есть хороший вопрос, получит ответ, но, поскольку 99% присутствующих здесь — волонтеры, мы не можем этого гарантировать.   -  person halfer    schedule 31.05.2016
comment
bwlookup(BW,lut) или applylut выполняет операцию нелинейной фильтрации окрестностей 2 на 2 или 3 на 3 для двоичного изображения или изображения в градациях серого BW, где cv::LUT — это операция таблицы поиска для каждого пикселя. Так что да, вы можете разделить изображение для выполнения последнего, но первое упомянутое: bw = applylut(bw, lut) в bwmorph.m не может быть реплицировано с помощью cv::LUT или другой стандартной функции OpenCV.   -  person mainactual    schedule 31.05.2016
comment
Спасибо за ответы. Я где-то читал, что библиотека OpenCV использует 8 элементов вокруг пикселя в качестве значений для таблицы поиска. Я прав в этом? Кажется, я где-то видел схему, но сейчас не могу найти. Хотите знать, в каком порядке биты берутся из значения пикселя?   -  person MyBushisaNeonJungle    schedule 31.05.2016
comment
Нет. cv::LUT не является операцией соседства, а B(x,y) ‹- LUT[A(x,y)] для всех (x,y). Вы можете имитировать удаление bwmorphs по изображению за вычетом эрозии по ядру в форме звезды. Мост требует немного больше усилий.   -  person mainactual    schedule 01.06.2016
comment
Собственно так и пробовал. Я могу удалить модель с помощью findcontours + drawcontours в OpenCV. Но мне все еще нужно смоделировать еще несколько морфологических операций, таких как мост и т. д. Я имел в виду, как операция LUT применяется к OpenCV, я где-то читал, что восемь элементов, окружающих объект, преобразуются в десятичное число, которое ищется в LUT, после чего значение в позиции в LUT, заданное десятичной дробью, является выходным. Если вышесказанное неверно, как работает LUT в OpenCV? продолжение.....   -  person MyBushisaNeonJungle    schedule 01.06.2016
comment
продолжение сверху. К настоящему времени я чертовски хорошо запомнил результаты поиска Google для большинства вариантов того, как таблица поиска работает в OpenCV, пока ничего. Даже в их собственных документах есть часть того, как сканировать изображения. Это ничего не объясняет о самой функции lut. Пробовал искать в определении лут функции(её код), не мог толком понять в чём дело. Поэтому любые книги или ссылки, которые могут объяснить, как работает LUT в OpenCV, были бы замечательными.   -  person MyBushisaNeonJungle    schedule 01.06.2016
comment
Возможно, стоит использовать дескрипторы, чтобы пинговать людей здесь, OP (cc @mainactual).   -  person halfer    schedule 02.06.2016
comment
@halfer хорошо, если это дает вам какое-то закрытие, я был тем, кто проголосовал за ваш комментарий о том, чтобы не разрушить мой собственный пост. Я подумал, что это был довольно хороший совет.   -  person MyBushisaNeonJungle    schedule 03.06.2016
comment
@ user6334139: хорошо, спасибо. Я надеюсь, что вы можете получить ответ, который вам нужен здесь - я не знаю это доменное пространство, но приведенный ниже ответ выглядит хорошо.   -  person halfer    schedule 03.06.2016
comment
@halfer извините, если вы подумали, что я вас проигнорировал. Я чувствовал, что если я отвечу, вы можете подумать, что я спорю с вами, что вовсе не входит в мои намерения. Но спасибо за очистку поста и все, что вы сделали.   -  person MyBushisaNeonJungle    schedule 05.06.2016


Ответы (1)


bwlookup(bw,lut)

http://se.mathworks.com/help/images/ref/bwlookup.html

или внутри, applylut оба выполняют операцию соседства 2 на 2 или 3 на 3 на бинарном (черно-белом) изображении, тогда как cv::LUT OpenCV выполняет преобразование уровня серого для каждого пикселя (тесно связанное с intlut в MATLAB). Примером последнего является выполнение гамма-коррекции на изображении уровня серого.

//! transforms array of numbers using a lookup table: dst(i)=lut(src(i))
CV_EXPORTS_W void LUT(InputArray src, InputArray lut, OutputArray dst,
                  int interpolation=0);

Насколько мне известно, в OpenCV нет реализации окрестности bwlookup. Однако, следуя описанию MATLAB bwlookup, вы можете написать его самостоятельно.

// performs 3-by-3 lookup on binary image
void bwlookup( 
    const cv::Mat & in, 
    cv::Mat & out, 
    const cv::Mat & lut,
    int bordertype=cv::BORDER_CONSTANT, 
    cv::Scalar px = cv::Scalar(0) ) 
{
    if ( in.type() != CV_8UC1 )
        CV_Error(CV_StsError, "er");
    if ( lut.type() != CV_8UC1 || lut.rows*lut.cols!=512 || !lut.isContinuous() )
        CV_Error(CV_StsError, "lut size != 512" );
    if ( out.type() != in.type() || out.size() != in.size() )
        out = cv::Mat( in.size(), in.type() );

    const unsigned char * _lut = lut.data;
    cv::Mat t;
    cv::copyMakeBorder( in,t,1,1,1,1,bordertype,px);
    const int rows=in.rows+1;
    const int cols=in.cols+1;
    for ( int y=1;y<rows;++y)
    {
        for ( int x=1;x<cols;++x)
        {
            int L = 0;
            const int jmax=y+1;
#if 0 // row-major order
            for ( int j=y-1, k=1; j<=jmax; ++j, k<<=3 )
            {
                const unsigned char * p = t.ptr<unsigned char>(j) + x-1;
                for ( unsigned int u=0;u<3;++u )
                {
                    if ( p[u] )
                        L += (k<<u);
#else // column-major order (MATLAB)
            for ( int j=y-1, k=1; j<=jmax; ++j, k<<=1 )
            {
                const unsigned char * p = t.ptr<unsigned char>(j) + x-1;
                for ( unsigned int u=0;u<3;++u )
                {
                    if ( p[u] )
                        L += (k<<3*u);
#endif
                }
            }
            out.at<unsigned char>(y-1,x-1)=_lut[ L ];
        }
    }
}

Я тестировал его на remove и bridge, так что должно работать. Надеюсь, это поможет.

Изменить: после проверки случайной таблицы поиска,

lut = uint8( rand(512,1)>0.5 ); % @MATLAB
B = bwlookup( A, lut );

Я перевернул порядок, в котором индексы появляются в таблице поиска (не имеет значения, является ли операция симметричной).

person mainactual    schedule 02.06.2016
comment
Привет @mainactual, Большое спасибо за ваш ответ. Я хотел спросить вас, как вы реализовали морфологические операции? Я только что попробовал эту штуку для lutarray для удаления на бинарном изображении, и все, что я получаю, это черный экран. - person MyBushisaNeonJungle; 03.06.2016
comment
@user6334139 user6334139, вы можете умножить массив lut (1 и 0) на желаемое выходное значение (обычно 0xFF), поэтому вывод будет следовать. Или, альтернативно, изменить масштаб out. Я думаю, что трудно уменьшить 1s на экране. Я просто сохранил таблицу поиска MATLAB в формате png и импортировал ее таким образом. - person mainactual; 03.06.2016
comment
Хорошо заработало! Проверим еще несколько морфологических операций и сообщим вам. А пока не могли бы вы рассказать мне свою интерпретацию кода? Что в нем происходит? - person MyBushisaNeonJungle; 05.06.2016
comment
@ user6334139, он создает шаблон соседства 3 на 3, устанавливая / выключая биты [0: 8] в соответствии с их положением в соседстве. Впоследствии любая такая морфологическая операция становится поиском O(1). - person mainactual; 06.06.2016
comment
Здравствуйте, я проверил реализацию и она дает результат. Тот же результат для удаления и соединения, а также для любой другой операции LUTarray. Я посмотрел результаты для них обоих в Matlab, и они вообще не соответствуют результату. Я смотрю на определение октавы ядра bwmorph.m = - conndef (ndims (bw), минимальное); kernel(ceil (число (ядро)/2)) = nnz (ядро) -1; morph = @(x) convn (x, ядро, то же самое) › 0; - person MyBushisaNeonJungle; 06.06.2016
comment
Ядро (для любого одноканального двоичного изображения) представляет собой матрицу, подобную той, что упоминается в сообщении для пользователей OpenCV, состоящую из степеней 2. Последняя строка кажется проблемой. Я использую для этого filter2D, но результат выглядит как реализация моста Octave. Я чувствую, что упускаю одну и ту же функцию в filter2D и › 0, которую я смоделировал как пороговое значение больше нуля, правильно ли я делаю это? - person MyBushisaNeonJungle; 06.06.2016
comment
@ user6334139, вам не нужно его покупать, это с открытым исходным кодом. Однако это не вопрос мнения, поэтому я предлагаю вам запустить код перекрестной проверки github.com/mainactual/ bwlookup . Это относится к MATLAB, про октаву понятия не имею. - person mainactual; 07.06.2016
comment
@mainactual Я проверил код по таблицам поиска, предоставленным в MATLAB, для подхода скелетирования, и не дал того же результата, что и MATLAB. Для скелетирования есть 8 LUT, которые выполняются повторно до тех пор, пока пиксели в бинарном изображении перестанут меняться. Я проверяю, где могла возникнуть ошибка, но, пожалуйста, дайте мне знать, если вы взглянете на нее. Отличная работа кстати :) - person Mahdi Chamseddine; 01.02.2017
comment
@MMahdiChamseddine, приятно, что вам нравится :) Я проверил MATLAB Circles.png: все 8 лутов экспортированы как uint8( images.internal.lutskel(i) ), всего 100 итераций (к тому времени они должны сойтись), а логика скопирована из algbwmorph, как вы сказали. Убедитесь, что функция не используется принудительно (должно быть input.data!=output.data), и используйте алгоритм из github. Мои результаты были идентичны. - person mainactual; 01.02.2017
comment
@mainactual как ни странно, когда я попробовал алгоритм в другой день, он сработал. Я мог что-то изменить, не документируя это, и поэтому я не могу знать, что вызвало проблему в первую очередь. спасибо за ваш ответ и извините за поздний ответ. - person Mahdi Chamseddine; 07.02.2017