CS50 - pset4 过滤器“模糊”问题

2024-01-01

我的模糊功能表现得很奇怪。我从 check50 重新创建了 3x3 位图,以便从测试中获得更近似的结果,但由于某种原因,每个右边缘或下边缘像素都无法正常工作。

在调试时,我发现由于某种原因,我的 for 循环行为不正常。我将在下面展示我的代码和示例。

Code:

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE temp[height][width]; // Declares temporary structure to avoid overwriting of original values while running loops

    // For loop to set the value of i, rows or height
    for (int i = 0; i < height; i++)
    {
        // For loop to set the value of j, columns or width
        for (int j = 0; j < width; j++)
        {
            float counter = 0.0;
            int sumRed = 0;
            int sumGreen = 0;
            int sumBlue = 0;

            // For loop to set the value of k, to get surrounding pixels
            for (int k = -1; k < 2; k++)
            {
                for (int m = -1; m < 2; m++)
                {
                    if ((i - k) >= 0 && (i - k) < height && (j - m) >= 0 && (j - m) < width)
                    {
                        sumRed = sumRed + image[i - k][j - m].rgbtRed; // Adds the value of verified pixel to the sum
                        sumGreen = sumGreen + image[i - k][j - m].rgbtGreen;
                        sumBlue = sumBlue + image[i - k][j - m].rgbtBlue;
                        counter++; // To get the average
                    }
                }
            }

            temp[i][j].rgbtRed = round(sumRed / counter); // Sets new color based on average of surrounding pixels
            temp[i][j].rgbtGreen = round(sumGreen / counter);
            temp[i][j].rgbtBlue = round(sumBlue / counter);
        }
    }

    // Start new loops to switch original values with temp values
    for (int i = 0; i < height - 1; i++)
    {
        for (int j = 0; j < width - 1; j++)
        {
            image[i][j].rgbtRed = temp[i][j].rgbtRed;
            image[i][j].rgbtGreen = temp[i][j].rgbtGreen;
            image[i][j].rgbtBlue = temp[i][j].rgbtBlue;
        }
    }

    return;
}

这是output https://i.stack.imgur.com/8pBfU.png.

作为我在调试过程中发现的示例,可以这样说:

i = 0
j = 2
k = 0
m = 0

在这里,而不是sumRed得到的值image[0 - 0][2 - 0] (RGB 70, 80, 90),它的值来自image[2][2] (RGB 240, 250, 255).

我还没有测试其他错误情况,但我想那里也发生了类似的事情。

任何帮助将不胜感激。


这是我的最高评论的开头:

如果这样可能会更好counter是一个int。然后做:round((double) sumRed / counter),但是,输出单元只有八位。你可能需要:sumRed = round((double) sumRed / counter); temp[i][j].rgbtRed = (sumRed < 255) ? sumRed : 255;这是饱和度数学。否则,当您分配给 8 位单元时,它是模数学,相当于sumRed % 256。那会产生257 --> 1(接近黑色)而不是257 --> 255(亮红)

你最大的问题是你的卷积核索引计算不正确。

代替:

(i - k)
(j - m)

你要:

(i + k)
(j + m)

另外,您对要复制回来的最终循环的限制temp to image相差 1。

另外,我会使用更多描述性变量。而且,您的代码可以稍微简化一些。这是包含错误修复的重构版本:

#include <math.h>

typedef struct {
    unsigned char rgbtRed;
    unsigned char rgbtGreen;
    unsigned char rgbtBlue;
} __attribute__((__packed__)) RGBTRIPLE;

// Blur image
void
blur(int height, int width, RGBTRIPLE image[height][width])
{
    // Declares temporary structure to avoid overwriting of original values
    // while running loops
    RGBTRIPLE temp[height][width];
#if 1
    RGBTRIPLE *tmp;
    RGBTRIPLE *img;
#endif

    // For loop to set the value of yctr, rows or height
    for (int yctr = 0; yctr < height; yctr++) {
        // For loop to set the value of xctr, columns or width
        for (int xctr = 0; xctr < width; xctr++) {
#if 0
            float counter = 0.0;
#else
            int counter = 0;
#endif
            int sumRed = 0;
            int sumGreen = 0;
            int sumBlue = 0;

            // For loop to set the value of yoff, to get surrounding pixels
            for (int yoff = -1; yoff < 2; yoff++) {
// NOTE/BUG: this is the main bug
#if 0
                int ycur = yctr - yoff;
#else
                int ycur = yctr + yoff;
#endif
                if (ycur < 0)
                    continue;
                if (ycur >= height)
                    continue;

                for (int xoff = -1; xoff < 2; xoff++) {
// NOTE/BUG: this is the main bug
#if 0
                    int xcur = xctr - xoff;
#else
                    int xcur = xctr + xoff;
#endif
                    if (xcur < 0)
                        continue;
                    if (xcur >= width)
                        continue;

                    // Adds the value of verified pixel to the sum
                    tmp = &image[ycur][xcur];
                    sumRed += tmp->rgbtRed;
                    sumGreen += tmp->rgbtGreen;
                    sumBlue += tmp->rgbtBlue;
                    counter++;      // To get the average
                }
            }

            // Sets new color based on average of surrounding pixels
            tmp = &temp[yctr][xctr];

#if 0
            tmp->rgbtRed = round(sumRed / counter);
            tmp->rgbtGreen = round(sumGreen / counter);
            tmp->rgbtBlue = round(sumBlue / counter);
#else

            sumRed = round((double) sumRed / counter);
            tmp->rgbtRed = (sumRed < 255) ? sumRed : 255;

            sumGreen = round((double) sumGreen / counter);
            tmp->rgbtGreen = (sumGreen < 255) ? sumGreen : 255;

            sumBlue = round((double) sumBlue / counter);
            tmp->rgbtBlue = (sumBlue < 255) ? sumBlue : 255;
#endif
        }
    }

    // Start new loops to switch original values with temp values
// NOTE/BUG: the for loop ranges are incorrect
#if 0
    for (int yctr = 0; yctr < height - 1; yctr++) {
        for (int xctr = 0; xctr < width - 1; xctr++) {
            image[yctr][xctr].rgbtRed = temp[yctr][xctr].rgbtRed;
            image[yctr][xctr].rgbtGreen = temp[yctr][xctr].rgbtGreen;
            image[yctr][xctr].rgbtBlue = temp[yctr][xctr].rgbtBlue;
        }
    }
#endif

#if 0
    for (int yctr = 0; yctr < height; yctr++) {
        for (int xctr = 0; xctr < width; xctr++) {
            image[yctr][xctr] = temp[yctr][xctr];
        }
    }
#endif

#if 1
    tmp = &temp[0][0];
    img = &image[0][0];

    int idxlim = width * height;
    for (int idxcur = 0; idxcur < idxlim; idxcur++)
        img[idxcur] = tmp[idxcur];
#endif
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

CS50 - pset4 过滤器“模糊”问题 的相关文章

  • 将 Stream 反序列化为 List 或任何其他类型

    尝试将流反序列化为List
  • 在动态事件处理程序中引用“this”

    在我的 myClass 类中 我使用 Reflection Emit 为 myClass 类成员之一动态编写事件处理程序 我已经成功地做到了这一点 现在 我想修改事件处理程序以调用 myClass 类中的实例方法之一 但是 我无法弄清楚如何
  • 将图像文件从网址复制到本地文件夹?

    我有该图像的网址 例如 http testsite com web abc jpg http testsite com web abc jpg 我想将该 URL 复制到 c images 中的本地文件夹中 而且当我将该文件复制到文件夹中时
  • 如何使用 MVVM 更新 WPF 中编辑的数据? [复制]

    这个问题在这里已经有答案了 我正在为聊天应用程序构建 UI 设计 在尝试更新所选联系人的消息时遇到问题 选择现有联系人 选择编辑选项 然后编辑其属性 例如用户名和图像 后 唯一进行的更改是联系人的用户名和图像 我仍然想更改 MessageM
  • 使用API​​隐藏程序标题栏

    它可以使用 c 和 windows api 删除窗口控制台标题栏 如果是的话如何 请 这个简单的应用程序隐藏并显示其所在控制台的标题栏 它会立即将控制台标题更改为 guid 以查找窗口句柄 然后 它使用 ToggleTitleBar 使用找
  • 在Application_AquireRequestState事件中用POST数据重写Url

    我有一个在其中注册路线的代码Application AcquireRequestState应用程序的事件 注册路由后 我会在 Http 运行时缓存中设置一个标志 这样我就不会再次执行路由注册代码 在此事件中注册路线有特定原因Applicat
  • 无法从 Web api POST 读取正文数据

    我正在尝试从新的 Asp Net Web Api 中的请求中提取一些数据 我有一个像这样的处理程序设置 public class MyTestHandler DelegatingHandler protected override Syst
  • Qt 计算和比较密码哈希

    目前正在 Qt 中为测验程序构建面向 Web 的身份验证服务 据我了解 在数据库中存储用户密码时 必须对其进行隐藏 以防落入坏人之手 流行的方法似乎是添加的过程Salt https en wikipedia org wiki Salt cr
  • 有没有办法使用 i387 fsqrt 指令获得正确的舍入?

    有没有办法使用 i387 fsqrt 指令获得正确的舍入 除了改变精确模式在 x87 控制字中 我知道这是可能的 但这不是一个合理的解决方案 因为它存在令人讨厌的重入型问题 如果 sqrt 操作中断 精度模式将出错 我正在处理的问题如下 x
  • 存储过程上的 OdbcCommand - 输出参数上出现“未提供参数”错误

    我正在尝试执行存储过程 通过 ODBC 驱动程序针对 SQL Server 2005 但收到以下错误 过程或函数 GetNodeID 需要参数 ID 但未提供该参数 ID 是我的过程的 OUTPUT 参数 在存储过程中指定了一个输入 mac
  • 我可以仅在少数情况下关闭模拟吗

    我有一个始终使用模拟的应用程序 但是 当用户以管理员身份登录时 一些操作需要他们写入服务器本身 现在 如果这些用户在实际服务器上没有权限 有些用户没有 则不会让他们写入 我想做的是关闭几个命令的模拟 有没有办法做这样的事情 using Ho
  • C# datagridview 列转入数组

    我正在用 C 构建一个程序 并在其中包含一个 datagridview 组件 datagridview 有固定数量的列 2 我想将其保存到两个单独的数组中 但行数确实发生了变化 我怎么能这样做呢 假设一个名为 dataGridView1 的
  • 防止GDB中的PLT(过程链接表)断点

    在最新版本的 GDB 中 在库函数调用上设置断点会导致多个实际断点 调用过程链接表 PLT 实际的函数调用 这意味着当调用库函数时 我们每次都会经历两次中断 在以前的 GDB 版本中 只会创建 2 因此您只能得到一次中断 那么问题来了 是否
  • 在简单注入器中注册具有多个构造函数和字符串依赖项的类型

    我正在尝试弄清楚如何使用 Simple Injector 我在项目中使用了它 注册简单服务及其组件没有任何问题 但是 当组件具有两个以上实现接口的构造函数时 我想使用依赖注入器 public DAL IDAL private Logger
  • 在VisualStudio DTE中,如何获取ActiveDocument的内容?

    我正在 VisualStudio 中编写脚本 并尝试获取当前 ActiveDocument 的内容 这是我当前的解决方案 var visualStudio new API VisualStudio 2010 var vsDTE visual
  • g++ C++0x 枚举类编译器警告

    我一直在将可怕的 C 类型安全伪枚举重构为新的 C 0x 类型安全枚举 因为它们是way更具可读性 不管怎样 我在导出的类中使用它们 所以我明确地将它们标记为导出 enum class attribute visibility defaul
  • C# 粘贴到文本框时检查剪贴板中的字符

    有没有一些方法可以在粘贴到文本框 C 之前仅检查剪贴板中的字符 Ctrl V 和右键单击 gt 粘贴 但不使用 MaskedTextbox 在文本框文本更改中添加规则以仅接受数字 例如 private string value privat
  • c# 模拟 IFormFile CopyToAsync() 方法

    我正在对一个异步函数进行单元测试 该函数将 IFormFile 列表转换为我自己的任意数据库文件类列表 将文件数据转换为字节数组的方法是 internal async Task
  • 无法使 Polly 超时策略覆盖 HttpClient 默认超时

    我正在使用 Polly 重试策略 并且正如预期的那样 在重试过程中HttpClient达到 100 秒超时 我尝试了几种不同的方法来合并 Polly 超时策略 将超时移至每次重试而不是总计 但 100 秒超时仍然会触发 我读过大约 5 个
  • FindAsync 很慢,但是延迟加载很快

    在我的代码中 我曾经使用加载相关实体await FindAsync 希望我能更好地遵守 C 异步指南 var activeTemplate await exec DbContext FormTemplates FindAsync exec

随机推荐

  • 使用node或express返回json格式的正确方法

    我的问题实际上是复制自使用 Node 或 Express 返回 JSON 的正确方法 https stackoverflow com questions 19696240 proper way to return json using no
  • 如何更改 ImageView 的图像? [复制]

    这个问题在这里已经有答案了 我刚刚开始学习android 我不知道如何改变一个人的形象ImageView 即它有一些在布局中设置的图像 但我想通过编码更改该图像我应该怎么做 这是 xml 文件
  • 带偏移量的 Linux 头/尾

    Linux 中有没有一种方法可以询问 Head 或 Tail 但需要忽略额外的记录偏移量 例如 如果文件example lst包含以下内容 row01 row02 row03 row04 row05 我用head n3 example ls
  • 在页面加载时使 div 晃动?

    有没有办法让 div 框在页面加载时抖动 就像也许只有一次或两次 Update 在这个 URL 上 我的页面加载仍然无法正常工作 我做错了什么 http tinyurl com 79azbav http tinyurl com 79azba
  • React 渲染组件数组

    快问 有人知道如何渲染组件数组吗 试图让开发人员更容易地更改特定组件 它就像一个仪表板 组件列表文件 import React from react export default
  • React hooks 常量的 useMemo 与 useState

    使用 React hooks 定义计算 初始化 常量可以通过两种功能相同的方式执行 我不想讨论这个用例 但足以说明 在某些情况下 可以从初始 props 或状态中派生出一个常量值 而这些值预计不会改变 想想路由数据 绑定调度等 First
  • 无法快速解码 json

    这是http客户端 打印字符串时响应是正确的 但在尝试解码时显示转换错误 let task URLSession shared dataTask with request data response error in Check for E
  • 在 rmarkdown pdf 输出中包装比例表的列名称的有效方法

    我正在使用提问者包制作行比例的加权表 当列名太长时 我想将它们换行 因为我正在制作数百个表 所以该解决方案需要适用于具有不同列数的表 我还想避免将所有列设置为特定宽度 理想情况下 短列名称将保持其正常宽度 而超过指定最大长度的名称将被换行
  • 如何将 8 个小圆圈围绕一个中心大圆圈对齐,如附图所示?

    I have to do this layout 我试图使用RelativeLayout和layout toRightOf layout below等来对齐视图 但我取得的最好成绩是 以下是 xml
  • 将多张地图组合/合并为一张地图

    如何将 dart 中的 2 个或更多地图组合 合并为 1 个地图 例如我有类似的东西 var firstMap 1 2 var secondMap 1 2 var thirdMap 1 2 I want var finalMap 1 2 1
  • 如何在不使用CreateObject的情况下打开excel并获取工作簿

    由于讨论的几个原因here https stackoverflow com questions 25022266 opening an excel file manually allows formulas to run opening a
  • 摆动拖放文件可传输吗?

    我想从我的应用程序拖放到系统文件夹中 以便当我放置一个项目时 它会显示为一个代表我拖动的对象的新文件 我应该使用什么 DataFlavor 我自己想出来了 你只需要使用DataFlavor javaFileListFlavor http d
  • 仅删除逗号前后的空格

    我正在寻找一种正则表达式 方法来仅删除逗号前后的空格 例子 100 0 101 0 101 1 100 1 100 0 100 2 0 2 100 8 0 2 100 8 0 8 100 2 0 8 100 2 0 2 预期结果 100 0
  • 将数据分箱到 Google 地图中的六角形网格中

    我正在尝试在 Google 地图上的六角形网格中显示地理空间数据 为此 给定六边形瓷砖网格尺寸X我需要能够转换 lat lng 坐标转化为 lat lng 包含它们的六边形网格图块的中心 最后 我希望能够在 Google 地图上显示数据 如
  • Composer 与 Symfony 2 自动加载器

    我开始使用Composer http getcomposer org 在一个项目中 我历史上将所有依赖项都置于版本控制之下 该项目目前使用的是Symfony 2 自动加载器 http symfony com doc 2 0 componen
  • Animate.css 不工作

    我在用动画 css https daneden me animate 但它似乎在火狐中不起作用 我正在使用的代码是 div class rotateIn content div 我希望这个 div 在我们加载页面时显示旋转效果 但它似乎不起
  • React Native中的“模块不存在于模块映射或这些目录中”

    我已经开始学习 React Native 我在简单的 React Native 项目中苦苦挣扎 同时在 index android js 中导入新的 js example Home js 我收到以下错误 模块映射或这些目录中不存在模块 Un
  • Json.NET 序列化中有没有办法区分“null 因为不存在”和“null 因为 null”?

    我正在使用 ASP NET webapi 代码库 其中我们严重依赖通过 JSON NET 将消息正文 JSON 反序列化为 NET 对象的自动支持 作为为我们的资源之一构建补丁支持的一部分 我非常希望区分 JSON 对象中不存在的可选属性与
  • Active Admin Gem - Rails 3.2.3,Heroku 错误日志

    我在理解错误日志时遇到问题 我正在使用 Active Admin 一切在我的本地服务器上运行良好 但是当我推送到 Heroku 时 我无法登录或使用 Active admin 我有点不知道问题是什么 我妻子的前端可以工作 但是当我第一次尝试
  • CS50 - pset4 过滤器“模糊”问题

    我的模糊功能表现得很奇怪 我从 check50 重新创建了 3x3 位图 以便从测试中获得更近似的结果 但由于某种原因 每个右边缘或下边缘像素都无法正常工作 在调试时 我发现由于某种原因 我的 for 循环行为不正常 我将在下面展示我的代码