реализация заточки Лапласа в оттенках серого - PullRequest
0 голосов
/ 06 октября 2018

Я пытаюсь реализовать повышение резкости по Лапласу с помощью C ++, вот мой код:

img = imread("cow.png", 0);
Mat convoSharp() {

    //creating new image
    Mat res = img.clone();
    for (int y = 0; y < res.rows; y++) {
        for (int x = 0; x < res.cols; x++) {
            res.at<uchar>(y, x) = 0.0;
        }
    }

    //variable declaration
    int filter[3][3] = { {0,1,0},{1,-4,1},{0,1,0} };
    //int filter[3][3] = { {-1,-2,-1},{0,0,0},{1,2,1} };
    int height = img.rows;
    int width = img.cols;
    int filterHeight = 3;
    int filterWidth = 3;
    int newImageHeight = height - filterHeight + 1;
    int newImageWidth = width - filterWidth + 1;
    int i, j, h, w;

    //convolution
    for (i = 0; i < newImageHeight; i++) {
        for (j = 0; j < newImageWidth; j++) {
            for (h = i; h < i + filterHeight; h++) {
                for (w = j; w < j + filterWidth; w++) {
                    res.at<uchar>(i,j) += filter[h - i][w - j] * img.at<uchar>(h,w);
                }
            }
        }
    }

    //img - laplace
    for (int y = 0; y < res.rows; y++) {
        for (int x = 0; x < res.cols; x++) {

            res.at<uchar>(y, x) = img.at<uchar>(y, x) - res.at<uchar>(y, x);

        }
    }



    return res;
}

this is the result

Я действительно не знаю, что пошло не так, я также пыталсядругой фильтр (1,1,1), (1, -8,1), (1,1,1) и результат также одинаков (более или менее).Я не думаю, что мне нужно нормализовать результат, потому что результат находится в диапазоне от 0 до 255. Кто-нибудь может объяснить, что действительно пошло не так в моем коде?

Ответы [ 2 ]

0 голосов
/ 06 октября 2018

Проблема частично в том, что вы переполняете ваш uchar, как предложено rafix07 , но это не полная проблема.

Лаплас изображения содержит отрицательные значения.Он должен.И вы не можете ограничить их до 0, вам нужно сохранить отрицательные значения.Кроме того, он может иметь значения до 4 * 255 с учетом вашей версии фильтра.Это означает, что вам нужно использовать 16-битный тип со знаком для хранения этого вывода.

Но есть более простой и эффективный подход!

Вы вычисляете img - laplace(img).С точки зрения сверток (*), это 1 * img - laplace_kernel * img = (1 - laplace_kernel) * img.То есть вы можете объединить обе операции в одну свертку.Ядро 1, которое не меняет образ, - [(0,0,0),(0,1,0),(0,0,0)].Вычтя из этого ваше ядро ​​Лапласа, вы получите [(0,-1,0),(-1,5,-1),(0,-1,0)].

Итак, просто вычислите свертку с этим ядром и сделайте это, используя int в качестве промежуточного типа, который затем зажимаете в вывод ucharдиапазон, как показано rafix07.

0 голосов
/ 06 октября 2018

Проблема : uchar слишком мала, чтобы содержать частичные результаты операции filerting.

Вы должны создать временную переменную и добавить все отфильтрованные позиции в эту переменную, а затем проверить, если значениетемпература находится в диапазоне <0,255>, если нет, вам нужно зафиксировать конечный результат, чтобы он соответствовал <0,255>.

. Выполнение ниже строки

res.at<uchar>(i,j) += filter[h - i][w - j] * img.at<uchar>(h,w);

частичный результат может быть больше 255(максимальное значение в uchar) или отрицательное значение (в фильтре -4 или -8).temp должен быть опечатанным целочисленным типом для обработки случая, когда частичный результат имеет отрицательное значение.

Исправление:

for (i = 0; i < newImageHeight; i++) {
    for (j = 0; j < newImageWidth; j++) {
        int temp = res.at<uchar>(i,j); // added
        for (h = i; h < i + filterHeight; h++) {
            for (w = j; w < j + filterWidth; w++) {
                temp += filter[h - i][w - j] * img.at<uchar>(h,w); // add to temp
            }
        }
        // clamp temp to <0,255>
        res.at<uchar>(i,j) = temp;
    }
}

Вы также должны ограничивать значения до диапазона <0,255>, когда вы делаетевычитание изображений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...