【C++】图像模糊处理题目详解与实现


在这里插入图片描述

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳]
本文专栏: C++

文章目录

  • 💯前言
  • 💯题目描述
    • 题目内容
    • 输入格式
    • 输出格式
    • 示例
      • 输入:
      • 输出:
  • 💯题目分析
    • 问题拆解
  • 💯我的做法
    • 代码实现
    • 代码分析
  • 💯老师的做法
    • 代码实现
    • 代码分析
  • 💯两种实现的对比
  • 💯相关概念拓展
    • 1. 四舍五入的实现
    • 2. 二维数组的边界处理
  • 💯优化建议
  • 💯小结


在这里插入图片描述


💯前言

  • 在C++程序设计学习中,处理二维数组与图像问题是一个重要的实践内容,能够帮助我们熟悉矩阵操作、边界条件处理以及浮点运算等核心技能。本篇文章将以一个图像模糊处理的题目为切入点,详细剖析题目背景、解题思路与两种代码实现(我的做法与老师的代码),并对两者进行深入比较与优化。同时,还将补充相关概念的详细解析,以期让读者对问题有全面而深入的理解。
    C++ 参考手册
    在这里插入图片描述

💯题目描述

题目来源于一个二维矩阵的图像模糊处理问题,其具体要求如下:
B2108 图像模糊处理
在这里插入图片描述

题目内容

给定一个 nm 列的图像各像素点的灰度值,要求用如下方法对其进行模糊处理:

  1. 四周外围的像素点灰度值保持不变。
  2. 中间像素点新灰度值为该像素点及其上下左右相邻四个像素点灰度值的平均(包含到最近的整数)。

输入格式

  • 第一行包含两个整数 nm,表示图像像素点的行数和列数。 1 ≤ n , m ≤ 100 1 \leq n, m \leq 100 1n,m100
  • 接下来 n 行,每行包含 m 个整数,表示图像像素的灰度值。
  • 每个整数为 0 ∼ 255 0 \sim 255 0255 之间的值,相邻两个整数之间用单个空格隔开。

输出格式

  • n 行,每行 m 个整数,为模糊处理后的图像。相邻两个整数之间用单个空格隔开。

示例

输入:

4 5
100 100 100 100 50
50 50 50 50 50
50 50 100 200 200
100 100 50 50 100

输出:

100 100 100 100 50
50 80 80 60 50
50 80 90 90 200
100 100 50 50 100

💯题目分析

问题拆解

要解决这个问题,我们需要完成以下任务:

  1. 边界处理:外围像素点保持原始灰度值不变。
  2. 中间像素模糊处理
    • 计算公式为:
      模糊后的灰度值 = 当前像素点灰度值 + 上下左右相邻像素点灰度值 5 。 \text{模糊后的灰度值} = \frac{\text{当前像素点灰度值} + \text{上下左右相邻像素点灰度值}}{5}。 模糊后的灰度值=5当前像素点灰度值+上下左右相邻像素点灰度值
    • 结果需“包含到最近的整数”。

💯我的做法

以下是我实现该题目的代码。

代码实现

#include <iostream>
#include <cmath>
using namespace std;int arr1[105][105];
int arr2[105][105];int main()
{int n, m;cin >> n >> m;for(int i = 0; i < n; i++){for(int j = 0; j < m; j++){cin >> arr1[i][j];}} for(int i = 0; i < n; i++){for(int j = 0; j < m; j++){if(i == 0 || i == n - 1 || j == 0 || j == m - 1)arr2[i][j] = arr1[i][j];else{double result = (arr1[i - 1][j] + arr1 [i + 1][j] + arr1[i][j - 1] + arr1[i][j + 1] + arr1[i][j]) / 5.0;arr2[i][j] = (int)round(result);}}} for(int i = 0; i < n; i++){for(int j = 0; j < m; j++){cout << arr2[i][j] << " ";}cout << endl;} return 0;	
} 

在这里插入图片描述

在这里插入图片描述

代码分析

  1. 输入部分
    • 通过两层循环读取矩阵的灰度值到 arr1 中。
  2. 模糊处理
    • 使用两层循环遍历矩阵的每一个像素点。
    • 边界点:直接将原始值赋值到结果矩阵 arr2 中。
    • 中间点:计算该点及其上下左右四个点的平均值,使用 round() 函数进行四舍五入,然后赋值到 arr2 中。
  3. 输出部分
    • 遍历 arr2 矩阵,将每行数据输出。

💯老师的做法

下面是老师的实现代码。

代码实现

#include <iostream>
using namespace std;const int N = 110;
int arr1[N][N]; // 旧数据
int arr2[N][N]; // 新数据
int n, m;int main() {cin >> n >> m;int i = 0;int j = 0;for (i = 0; i < n; i++) {for (j = 0; j < m; j++) {cin >> arr1[i][j];arr2[i][j] = arr1[i][j];}}for (i = 1; i < n - 1; i++) {for (j = 1; j < m - 1; j++) {arr2[i][j] = (arr1[i][j] + arr1[i - 1][j] + arr1[i + 1][j] + arr1[i][j - 1] + arr1[i][j + 1]) / 5.0 + 0.5;}}for (i = 0; i < n; i++) {for (j = 0; j < m; j++) {cout << arr2[i][j] << " ";}cout << endl;}return 0;
}

在这里插入图片描述

在这里插入图片描述

代码分析

  1. 边界初始化
    • 老师直接在输入矩阵时,将 arr1 的数据赋值给 arr2,实现了边界初始化。
  2. 模糊处理逻辑
    • 对中间像素点进行模糊计算时,将平均值的浮点结果直接加上 0.5,然后用强制类型转换 (int) 实现四舍五入。
  3. 输出部分
    • 同样使用两层循环输出结果矩阵 arr2

💯两种实现的对比

对比点我的做法老师的做法
边界处理使用条件语句单独处理边界像素。在输入时直接完成边界初始化。
模糊计算使用 round() 函数实现四舍五入。通过 + 0.5 与强制类型转换 (int) 实现四舍五入。
代码结构边界处理与模糊处理分开,逻辑清晰但略显冗余。将边界初始化与输入结合,更加简洁。
浮点运算使用浮点除法后取整,增加了一些计算开销。避免了额外函数调用,更高效。

💯相关概念拓展

1. 四舍五入的实现

两种方法:

  1. 使用数学库中的 round() 函数:
    • 直接返回最近的整数。
  2. 手动实现:
    • 对浮点数加 0.5,然后强制类型转换为整数。
    • 更高效,避免额外函数调用。

2. 二维数组的边界处理

在处理二维数组时,常见的边界条件有:

  • 边界像素点保持不变。
  • 超出边界时采取特殊值(例如零填充)。
  • 通过循环边界实现(例如,最后一行的邻居是第一行)。

💯优化建议

在已有代码的基础上,提出以下优化:

  1. 避免浮点运算

    • 使用整数除法和四舍五入的等效操作:
      arr2[i][j] = (arr1[i][j] + arr1[i - 1][j] + arr1[i + 1][j] + arr1[i][j - 1] + arr1[i][j + 1] + 2) / 5;
      
    • +2 是为了模拟加 0.5 的效果,且无需浮点运算。
  2. I/O 优化

    • 如果数据量较大,可以使用更高效的输入输出方法:
      ios::sync_with_stdio(false);
      cin.tie(nullptr);
      

💯小结

  • 在这里插入图片描述
    通过本文对图像模糊处理问题的详解,我们不仅学习了如何处理二维数组,还深入对比了两种实现方式,掌握了边界处理、四舍五入、浮点运算优化等技巧。这些经验可迁移至其他矩阵操作类题目中,为复杂问题的求解提供清晰的思路和工具。希望这篇文章对你有所启发!

在这里插入图片描述


在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/891811.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在 Ubuntu 22.04 上部署 AppArmor 应用安全教程

在这篇教程中&#xff0c;我们将为你设置 AppArmor 以增强应用程序的安全性。 AppArmor 是一个 Linux 安全模块&#xff0c;允许你限制各个程序的功能。通过强制执行强制访问控制策略&#xff0c;AppArmor 增强了你的应用程序和系统的安全性。 AppArmor 是一个易于使用的 Lin…

Nginx:动静分离

什么是动静分离? 动静分离 是指将网站中的静态资源(如图片、样式表、脚本等)和动态内容(如 PHP、Python、Node.js 等后端生成的内容)分开部署和处理。这样做的好处是可以利用不同的服务器或缓存策略来优化不同类型的资源。 动静分离的好处 提高性能:静态资源可以直接从…

每天40分玩转Django:Django插件开发

Django插件开发 一、插件开发概述表 阶段主要任务技术要点难度准备工作项目结构设计、环境配置项目布局、setup.py★★★☆☆开发实现功能开发、测试编写Django AppConfig、Signals★★★★☆文档编写API文档、使用说明Markdown、reStructuredText★★★☆☆发布部署PyPI打包…

什么是TDD测试驱动开发(Test Driven Development)?

什么是测试驱动开发&#xff1f; 软件开发团队通常会编写自动化测试套件来防止回归。这些测试通常是在编写应用程序功能代码之后编写的。我们将采用另一种方法&#xff1a;在实现应用程序代码之前编写测试。这称为测试驱动开发 (TDD)。 为什么要应用 TDD&#xff1f;通过在实…

后台管理系统用户退出登录方案实现

退出登录一直是一个通用的前端实现方案&#xff0c;对于退出登录而言&#xff0c;它的触发时机一般有两种&#xff1a; 1. 用户主动退出&#xff0c;即用户点击登录按钮之后退出&#xff1b; 2. 用户被动退出&#xff0c;Token过期或被 其他人"顶下来" 时退出&…

文献分享:BGE-M3——打通三种方式的嵌入模型

文章目录 1. \textbf{1. } 1. 背景与导论 1.1. \textbf{1.1. } 1.1. 研究背景 1.2. \textbf{1.2. } 1.2. 本文的研究 1.3. \textbf{1.3. } 1.3. 有关工作 2. M3-Embedding \textbf{2. M3-Embedding} 2. M3-Embedding 2.1. \textbf{2.1. } 2.1. 模型核心: 混合检索方式 2.1.1. \…

Hadoop•FinalShell连接VMware免密登录

听说这是目录哦 FinalShell连接VMware&#x1f324;️解决重连失效FinalShell的使用 免密登录⛈️能量站&#x1f61a; FinalShell连接VMware&#x1f324;️ 保持虚拟机的开机状态&#xff0c;打开FinalShell&#xff0c;如果虚拟机关机或者挂起&#xff0c;连接就会断开。 …

一个在ios当中采用ObjectC和opencv来显示图片的实例

前言 在ios中采用ObjectC编程利用opencv来显示一张图片&#xff0c;并简单绘图。听上去似乎不难&#xff0c;但是实际操作下来&#xff0c;却不是非常的容易的。本文较为详细的描述了这个过程&#xff0c;供后续参考。 一、创建ios工程 1.1、选择ios工程类型 1.2、选择接口模…

《Rust权威指南》学习笔记(五)

高级特性 1.在Rust中&#xff0c;unsafe是一种允许绕过Rust的安全性保证的机制&#xff0c;用于执行一些Rust默认情况下不允许的操作。unsafe存在的原因是&#xff1a;unsafe 允许执行某些可能被 Rust 的安全性检查阻止的操作&#xff0c;从而可以进行性能优化&#xff0c;如手…

【顶刊TPAMI 2025】多头编码(MHE)之极限分类 Part 3:算法实现

目录 1 三种多头编码&#xff08;MHE&#xff09;实现1.1 多头乘积&#xff08;MHP&#xff09;1.2 多头级联&#xff08;MHC&#xff09;1.3 多头采样&#xff08;MHS&#xff09;1.4 标签分解策略 论文&#xff1a;Multi-Head Encoding for Extreme Label Classification 作者…

docker中使用Dockerfile设置Volume挂载点

关于在docker中如何使用Volume&#xff0c;可以参考文章&#xff1a; docker中使用Volume完成数据共享-CSDN博客 如果想在生成docker镜像的时候设置好挂载点&#xff0c;而不是在运行镜像生成容器时生成。 下面以自建一个tomcat镜像为例&#xff0c;演示如何在生成镜像时设置…

springboot548二手物品交易boot代码(论文+源码)_kaic

摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统二手物品交易信息管理难度大&#xff0c;容错率低&#x…

通往O1开源之路

“Scaling of Search and Learning: A Roadmap to Reproduce o1 from Reinforcement Learning Perspective”由复旦大学和上海人工智能实验室的研究者撰写。该论文从强化学习视角出发&#xff0c;深入分析了实现类似OpenAI o1模型性能的路线图&#xff0c;聚焦于策略初始化、奖…

SD下载、安装、使用、卸载-Stable Diffusion整合包v4.10发布!

目录 前言概述 SD安装1、安装软件2、启动3、配置4、运行5、测试 导入SD模型【决定画风】常用模型下载安装模型 SD卸载SD文生图提示词提示词使用技巧提示词的高级使用技巧强调关键词 前言 我向来不喜欢搞一些没有用的概念&#xff0c;所以直接整理可能用到的东西。 sd简单的说…

Mac iTerm2集成DeepSeek AI

1. 去deepseek官网申请api key&#xff0c;DeepSeek 2. 安装iTerm2 AI Plugin插件&#xff0c;https://iterm2.com/ai-plugin.html&#xff0c;插件解压后直接放到和iTerms相同的位置&#xff0c;默认就在/Applications 下 3. 配置iTerm2 4. 重启iTerm2,使用快捷键呼出AI对话…

MySQL数据库笔记——多版本并发控制MVCC

大家好&#xff0c;这里是Good Note&#xff0c;关注 公主号&#xff1a;Goodnote&#xff0c;本文详细介绍MySQL的并发控制&#xff1a;多版本并发控制MVCC。 文章目录 背景介绍数据库并发控制——锁机制悲观锁和乐观锁悲观锁乐观锁 数据库并发控制——MVCC 的引入MVCC 和锁机…

电脑里msvcr120.dll文件丢失怎样修复?

电脑里msvcr120.dll文件丢失的修复指南 在电脑的日常使用中&#xff0c;我们可能会遇到各种各样的系统文件丢失问题&#xff0c;其中msvcr120.dll文件的丢失就是较为常见的一种。作为一名在软件开发领域深耕多年的从业者&#xff0c;我将为大家详细解析msvcr120.dll文件的重要…

今日头条ip属地根据什么显示?不准确怎么办

在今日头条这样的社交媒体平台上&#xff0c;用户的IP属地信息对于维护网络环境的健康与秩序至关重要。然而&#xff0c;不少用户发现自己的IP属地显示与实际位置不符&#xff0c;这引发了广泛的关注和讨论。本文将深入探讨今日头条IP属地的显示依据&#xff0c;并提供解决IP属…

【Rust自学】10.3. trait Pt.1:trait的定义、约束与实现

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 题外话&#xff1a;trait的概念非常非常非常重要&#xff01;&#xff01;&#xff01;整个第10章全都是Rust的重难点&#xff01;&#x…

大白话拆解——多线程中关于死锁的一切(七)(已完结)

前言&#xff1a; 25年初&#xff0c;这个时候好多小伙伴都在备战期末 小编明天还有一科考试&#xff0c;日更一篇&#xff0c;今天这篇一定会对小白非常有用的&#xff01;&#xff01;&#xff01; 因为我们会把案例到用代码实现的全过程思路呈现出来&#xff01;&#xff…