Нежелательный шумовой элемент во время дилатации

Я применяю операцию расширения к бинарному изображению рисового зерна. При использовании структурирующего элемента размером 9x9 частицы шума увеличиваются, что логично. Но когда я использую структурирующий элемент размером 15x15, я получаю новые шумовые частицы, примыкающие к исходным шумовым частицам. Это очень сбивает с толку, так как я не могу понять, почему это происходит. Структурирующий элемент представляет собой матрицу размера nxn со всеми единицами. Изображения были прикреплены для справки.

Исходное изображение:
введите здесь описание изображения

Увеличенное изображение (9x9 SE):
введите здесь описание изображения

Увеличенное изображение (15x15 SE):
введите здесь описание изображенияПожалуйста, помогите!!

Код:

void DilateBinary(Mat Image, Mat& op, double* SE, int m){
op=Image.clone();
double pixelvalue;

int limit=(m-1)/2;
for(int y = limit; y < (Image.rows - limit); y++)
            {
                for(int x = limit; x < (Image.cols - limit); x++)
                {
                    double max=0.0;
                    //printf("Input pixel: %u \n",Image.at<unsigned char>(y,x));
                    for(int j = -limit; j <=limit ; j++)
                    {
                        for(int i = -limit; i <=limit ; i++)
                        {
                            if(*(SE + (j+1)*m + (i+1) ) > 0)
                            {
                                pixelvalue = (*(SE + (j+1)*m + ((2*limit)-(i+1)) )) * (Image.at<unsigned char>(y+j,x+i));
                                //printf("%f",pixelvalue);
                                if (pixelvalue>127)
                                    max=255.0;
                            }
                        }
                    }
                    op.at<uchar>(y,x) = max;
                    //printf("Output pixel: %u \n",op.at<unsigned char>(y,x));
                    //printf("Modified pixel= %f %d\n",pixelvalue,cvRound(pixelvalue));

                }
            }

Примечание. SE — это указатель на маску/SE, которую я использую. & m равно 9 для 9x9 SE, 15 для 15x15 SE.........


person avr    schedule 25.02.2015    source источник
comment
Так в чем именно заключается ваш вопрос? Почему это происходит или как от них избавиться? Также, пожалуйста, укажите язык программирования, который вы используете. Это Матлаб? Спасибо!   -  person Benoit_11    schedule 25.02.2015
comment
я считаю, что это не должно происходить. если это правильно, то почему это происходит. Если не так, то почему это происходит и как это исправить.   -  person avr    schedule 25.02.2015
comment
Я использую C. Код был вставлен в заявление.   -  person avr    schedule 25.02.2015
comment
Индексация в маске выглядит неправильно, вы получите отрицательные индексы.   -  person Mark Ransom    schedule 25.02.2015
comment
я почти уверен, что индексация правильная. он дает правильные результаты вплоть до 9x9 SE. я получаю ошибку (если она есть) только для 15x15 SE.   -  person avr    schedule 25.02.2015
comment
хотя вы можете заменить ((2*limit)-(i+1)) на (i+1)). это будет то же самое, поскольку SE - симметричная матрица со всеми единицами.   -  person avr    schedule 25.02.2015


Ответы (1)


Виновником является ваш оператор if внутри вторых вложенных блоков цикла for:

for(int j = -limit; j <=limit ; j++) {
    for(int i = -limit; i <=limit ; i++) {
        if(*(SE + (j+1)*m + (i+1) ) > 0) {
            pixelvalue = (*(SE + (j+1)*m + ((2*limit)-(i+1)) ))  (Image.at<unsigned char>(y+j,x+i));
            if (pixelvalue>127)
                max=255.0;
        }
    }
}

То, как вы индексируете свой элемент структурирования, предполагает, что это маска 3 x 3, потому что вы ожидаете, что i и j колеблются от -1 до 1. Марк Рэнсом прав в своей оценке, у вас будут индексы с отрицательными значениями. Попробуйте установить m = 15, в этом и заключается ваша проблема. Это означает, что limit = 7, а затем начните с начала этого цикла, посмотрите, к какой строке и столбцу вы обращаетесь, когда пытаетесь получить доступ к маске с линейными индексами по строкам.

Если limit = 7, значит в начале j = -7, i = -7 и так (j+1)*m = (-7+1)*15 = -90. Также (2*limit) - (i+1) = (2*7) - (-7+1) = 20. В конечном итоге это означает, что вы пытаетесь получить доступ к ячейке памяти SE - 90 + 20 = SE - 70, поэтому вы фактически оцениваете ячейку памяти в 70 байтах (при условии, что unsigned char) от источника вашего элемента структурирования, а не в верхнем левом углу элемента структурирования. ... так вы уверены, что написали этот код правильно? Я удивлен, что вы еще не получили никаких ошибок сегментации. Возможно, вам повезло с 9 x 9, потому что смещение строки отрицательное, но смещение столбца будет положительным, и они могут быть равны по величине, так что вам, вероятно, повезло с доступом ко всем элементам структурирования тогда, но это, конечно, не будет быть верным для более высоких размеров маски.

Чтобы обеспечить охват всех коэффициентов маски, необходимо изменить смещение на +limit, а не +1. Я также не понимаю 2*limit внутри оператора if. Вы можете просто получить доступ к элементу маски напрямую. Поэтому нужно сделать так:

for(int j = -limit; j <=limit ; j++) {
    for(int i = -limit; i <=limit ; i++) {
        if(*(SE + (j+limit)*m + (i+limit) ) > 0) {
            pixelvalue = (*(SE + (j+limit)*m + (i+limit) )) * (Image.at<unsigned char>(y+j,x+i));
            if (pixelvalue>127)
                max=255.0;
        }
    }
}

Однако, если я могу что-то предложить, поскольку вы выполняете морфологическое бинарное расширение, вам нужно только проверить, не соприкасаются ли какие-либо пиксели в вашем структурирующем элементе с белым пикселем. Поскольку это квадратный структурирующий элемент, это будет еще проще. По сути, в окрестности m x m пикселя, если какой-либо пиксель не равен нулю, вы должны установить вывод на 255 и выйти из цикла. Небольшая оптимизация вашего кода может быть:

for(int j = -limit; j <=limit ; j++) {
    for(int i = -limit; i <=limit ; i++) {
        pixelValue = (*(SE + (j+limit)*m + (i+limit) )); // Get structuring element value
        pixelValue *= (Image.at<unsigned char>(y+j,x+i)); // Obtain corresponding intensity
        if (pixelValue != 0) { // If non-zero, set output to max and break
            max = 255.0;
            i = limit + 1; j = limit + 1; // break out of loop
        }
    }
}

Это, очевидно, ничего не спасет, когда у вас есть области полной темноты, но когда дело доходит до областей, которые полностью белые, двойные вложенные циклы for, которые проходят через структурирующий элемент, будут выполняться только один раз. Это может сэкономить несколько тактов, но всегда помните, что морфология грубой силы уже сама по себе имеет ужасную вычислительную сложность.

person rayryeng    schedule 25.02.2015
comment
коррекция работает. спасибо, что указали. Даже мне интересно, как у меня нет ошибок сегментации!! А оптимизация, наконец, сокращает время работы в данном случае более чем на 50%. хорошее предложение! - person avr; 25.02.2015
comment
@avr - А, в том-то и дело с выделенной памятью, лол. Это непростой бизнес. Иногда доступ к этому элементу в этом неопределенном месте работает, а иногда нет. Вы определенно получили бы ошибку, если бы этот массив хранился в стеке (т.е. объявлял массив известного размера во время компиляции), а не в куче (т.е. динамически выделял массив во время выполнения). - person rayryeng; 25.02.2015
comment
@rayryeng, кажется, вы занимаетесь обработкой изображений — не могли бы вы помочь нам открыть эту специальную группу: area51.stackexchange .com/proposals/66531/computer-vision/72084 Просто голосуйте за вопросы, набравшие менее 10 голосов "за". Спасибо. - person Royi; 26.02.2015
comment
@Drazick - Кажется, не так ли? Некоторое время назад я голосовал за предложение CV StackExchange, а также за вопросы. Осталось дождаться одобрения! - person rayryeng; 26.02.2015
comment
@rayryeng, вы отвечаете многим людям, не могли бы вы также предложить им помощь? Как насчет того, чтобы помочь мне создать форум по обработке изображений и компьютерному зрению? - person Royi; 26.02.2015
comment
@Drazick - Звучит многообещающе. Я даже могу подать заявку на модерацию этого форума. Я посмотрю что я могу сделать! - person rayryeng; 26.02.2015
comment
@rayryeng, не могли бы вы поддержать изменение имени (добавление обработки изображений в название форума в дополнение к Computer Vision): discuss.area51.stackexchange.com/questions/17733/ - person Royi; 26.02.2015
comment
@Drazick - я видел этот пост, когда был там несколько минут назад. Я проголосовал за ваш ответ. - person rayryeng; 26.02.2015