cs50 pset4 фильтр "края" - PullRequest
       117

cs50 pset4 фильтр "края"

0 голосов
/ 04 августа 2020

Когда я пропускаю фотографию через свой edges код, изображение возвращается полностью белым, за исключением трех рядов пикселей внизу, которые выглядят так же, как в режиме c rainbow tv. Я пытался отладить свой код, но все еще не могу понять:

void edges(int height, int width, RGBTRIPLE image[height][width])
{
    int gx[3][3] = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}};
    int gy[3][3] = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}};
    int redx = 0;
    int greenx = 0;
    int bluex = 0;
    int redy = 0;
    int greeny = 0;
    int bluey = 0;
    int finalred = 0;
    int finalgreen = 0;
    int finalblue = 0;
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            for (int k = i - 1; k <= i + 1 && k < height && k >= 0; k++)
            {
                for (int m = j - 1; m <= j + 1 && m < width && m >= 0; m++)
                {
                    if (k < i)
                    {
                        if (m < j)
                        {
                            redx += image[k][m].rgbtRed * gx[0][0];
                            greenx += image[k][m].rgbtGreen * gx[0][0];
                            bluex += image[k][m].rgbtBlue * gx[0][0];
                            redy += image[k][m].rgbtRed * gy[0][0];
                            greeny += image[k][m].rgbtGreen * gy[0][0];
                            bluey += image[k][m].rgbtBlue * gy[0][0];
                            // gx[?][0]
                        }
                        else if (m > j)
                        {
                            redx += image[k][m].rgbtRed * gx[0][2];
                            greenx += image[k][m].rgbtGreen * gx[0][2];
                            bluex += image[k][m].rgbtBlue * gx[0][2];
                            redy += image[k][m].rgbtRed * gy[0][2];
                            greeny += image[k][m].rgbtGreen * gy[0][2];
                            bluey += image[k][m].rgbtBlue * gy[0][2];
                            // gx[?][2]
                        }
                        else
                        {
                            redx += image[k][m].rgbtRed * gx[0][1];
                            greenx += image[k][m].rgbtGreen * gx[0][1];
                            bluex += image[k][m].rgbtBlue * gx[0][1];
                            redy += image[k][m].rgbtRed * gy[0][1];
                            greeny += image[k][m].rgbtGreen * gy[0][1];
                            bluey += image[k][m].rgbtBlue * gy[0][1];
                            // gx[?][1]
                        }
                        // gx[0][?]
                    }
                    else if (k > i)
                    {
                        if (m < j)
                        {
                            redx += image[k][m].rgbtRed * gx[2][0];
                            greenx += image[k][m].rgbtGreen * gx[2][0];
                            bluex += image[k][m].rgbtBlue * gx[1][0];
                            redy += image[k][m].rgbtRed * gy[2][0];
                            greeny += image[k][m].rgbtGreen * gy[2][0];
                            bluey += image[k][m].rgbtBlue * gy[2][0];
                            // gx[?][0]
                        }
                        else if (m > j)
                        {
                            redx += image[k][m].rgbtRed * gx[2][2];
                            greenx += image[k][m].rgbtGreen * gx[2][2];
                            bluex += image[k][m].rgbtBlue * gx[2][2];
                            redy += image[k][m].rgbtRed * gy[2][2];
                            greeny += image[k][m].rgbtGreen * gy[2][2];
                            bluey += image[k][m].rgbtBlue * gy[2][2];
                            // gx[?][2]
                        }
                        else
                        {
                            redx += image[k][m].rgbtRed * gx[2][1];
                            greenx += image[k][m].rgbtGreen * gx[2][1];
                            bluex += image[k][m].rgbtBlue * gx[2][1];
                            redy += image[k][m].rgbtRed * gy[2][1];
                            greeny += image[k][m].rgbtGreen * gy[2][1];
                            bluey += image[k][m].rgbtBlue * gy[2][1];
                            // gx[?][1]
                        }
                        // gx[2][?]
                    }
                    else
                    {
                        if (m < j)
                        {
                            redx += image[k][m].rgbtRed * gx[1][0];
                            greenx += image[k][m].rgbtGreen * gx[1][0];
                            bluex += image[k][m].rgbtBlue * gx[1][0];
                            redy += image[k][m].rgbtRed * gy[1][0];
                            greeny += image[k][m].rgbtGreen * gy[1][0];
                            bluey += image[k][m].rgbtBlue * gy[1][0];
                            // gx[?][0]
                        }
                        else if (m > j)
                        {
                            redx += image[k][m].rgbtRed * gx[1][2];
                            greenx += image[k][m].rgbtGreen * gx[1][2];
                            bluex += image[k][m].rgbtBlue * gx[1][2];
                            redy += image[k][m].rgbtRed * gy[1][2];
                            greeny += image[k][m].rgbtGreen * gy[1][2];
                            bluey += image[k][m].rgbtBlue * gy[1][2];
                            // gx[?][2]
                        }
                        else
                        {
                            redx += image[k][m].rgbtRed * gx[1][1];
                            greenx += image[k][m].rgbtGreen * gx[1][1];
                            bluex += image[k][m].rgbtBlue * gx[1][1];
                            redy += image[k][m].rgbtRed * gy[1][1];
                            greeny += image[k][m].rgbtGreen * gy[1][1];
                            bluey += image[k][m].rgbtBlue * gy[1][1];
                            // gx[?][1]
                        }
                        // gx[1][?]
                    }
                }
            }
            finalred = (redx)^2 + (redy)^2;
            finalgreen = (greenx)^2 + (greeny)^2;
            finalblue = (bluex)^2 + (bluey)^2;
            if (finalred > 255)
            {
                finalred = 255;
            }
            if (finalgreen > 255)
            {
                finalgreen = 255;
            }
            if (finalblue > 255)
            {
                finalblue = 255;
            }
            image[i][j].rgbtRed = finalred;
            image[i][j].rgbtGreen = finalgreen;
            image[i][j].rgbtBlue = finalblue;
        }
    }
    return;
}

1 Ответ

1 голос
/ 04 августа 2020

Инициализация переменных

Эти инициализации:

    int redx = 0;
    int greenx = 0;
    int bluex = 0;
    int redy = 0;
    int greeny = 0;
    int bluey = 0;

появляются перед операторами for в i и j, но эти переменные накапливают суммы для каждого пикселя, поэтому они должен быть инициализирован для каждого пикселя. Это находится в операторе for в j и перед операторами for в k и m.

(поскольку это было указано в комментарии, код в вопросе имеет был отредактирован, чтобы присвоить этим переменным нули после обновления каждого пикселя. Это работает, но это плохое решение. Просто переместите определения и инициализации переменных внутри двух внешних for циклов.)

Неверно L oop Условия

Этот оператор завершится ошибкой:

for (int k = i - 1; k <= i + 1 && k < height && k >= 0; k++)

Рассмотрим, что происходит, когда i равно 0. Затем int k = i - 1 инициализирует k равным -1. Тогда k >= 0 ложно, поэтому тест k <= i + 1 && k < height && k >= 0 ложен, поэтому тело l oop никогда не выполняется, и ни один из пикселей в строке с i = 0 не обновляется.

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

Неверный оператор

^ используется для попытки возведения в степень в (redx)^2. В C ^ - это оператор XOR. В этой ситуации, чтобы возвести число в квадрат, просто умножьте само себя, как с redx*redx. В C есть оператор возведения в степень, но он предназначен для арифметики с плавающей запятой c, поэтому он не подходит для этой задачи, и вы узнаете о нем в другом уроке.

Преждевременные обновления изображений

Эти строки:

image[i][j].rgbtRed = finalred;
image[i][j].rgbtGreen = finalgreen;
image[i][j].rgbtBlue = finalblue;

находятся внутри циклов на i и j, поэтому они обновляют изображение по мере обработки каждого пикселя. Это означает, что пиксели, которые еще предстоит обновить, будут использовать новые значения, присвоенные ранее обновленным пикселям. Это неверно; при вычислении значений для новых пикселей следует использовать исходные предварительно обновленные значения. Решение этой проблемы требует использования отдельного буфера для временного хранения новых значений. (Простым решением является использование полного отдельного массива для хранения новых значений, но существуют более эффективные решения, занимающие меньше места.)

Расчет не округляется

Этот код принимает квадрат root и усекает его до целого числа:

finalred = sqrt((redx)^2 + (redy)^2);

Однако в спецификации задачи говорится: «И поскольку значения канала могут принимать только целые значения от 0 до 255, убедитесь, что полученное значение округляется до ближайшего целого числа и

Избыточный код

Такой код появляется несколько раз:

if (k < i)
                    {
                        if (m < j)
                        {
                            redx += image[k][m].rgbtRed * gx[0][0];
                            greenx += image[k][m].rgbtGreen * gx[0][0];
                            bluex += image[k][m].rgbtBlue * gx[0][0];
                            redy += image[k][m].rgbtRed * gy[0][0];
                            greeny += image[k][m].rgbtGreen * gy[0][0];
                            bluey += image[k][m].rgbtBlue * gy[0][0];
                            // gx[?][0]
                        }

По структуре этих циклов k может быть только равным i-1, i или i+1. Следовательно, нет необходимости использовать операторы if для выбора индекса 0, 1 или 2 массивов; мы можем просто вычислить его, и аналогично для m, и тогда для всех случаев хватит одного набора кода:

redx   += image[k][m].rgbtRed   * gx[k-(i-1)][m-(j-1)];
greenx += image[k][m].rgbtGreen * gx[k-(i-1)][m-(j-1)];
bluex  += image[k][m].rgbtBlue  * gx[k-(i-1)][m-(j-1)];
redy   += image[k][m].rgbtRed   * gy[k-(i-1)][m-(j-1)];
greeny += image[k][m].rgbtGreen * gy[k-(i-1)][m-(j-1)];
bluey  += image[k][m].rgbtBlue  * gy[k-(i-1)][m-(j-1)];

Обратите внимание, что проблема обработки краев и углов все еще остается, как указано выше.

Ненужные инициализации

Эти инициализации и сбросы не нужны:

    int finalred = 0;
    int finalgreen = 0;
    int finalblue = 0;
            finalred = 0;
            finalgreen = 0;
            finalblue = 0;

Вместо этого просто определите эти переменные там, где они необходимы; изменить:

            finalred = sqrt((redx)^2 + (redy)^2);
            finalgreen = sqrt((greenx)^2 + (greeny)^2);
            finalblue = sqrt((bluex)^2 + (bluey)^2);

на:

            int finalred = sqrt((redx)^2 + (redy)^2);
            int finalgreen = sqrt((greenx)^2 + (greeny)^2);
            int finalblue = sqrt((bluex)^2 + (bluey)^2);

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

...