【C++】B2108 图像模糊处理


在这里插入图片描述

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳]
本文专栏: 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);
      

💯小结

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

在这里插入图片描述


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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

怎么把word试题转成excel?

在教育行业、学校管理以及在线学习平台中&#xff0c;试题库的高效管理是一项核心任务。许多教育工作者和系统开发人员常常面临将 Word 中的试题批量导入 Excel 的需求。本文将详细介绍如何快速将试题从 Word 转换为 Excel&#xff0c;帮助您轻松解决繁琐的数据整理问题&#x…

minibatch时,损失如何记录

目录 minibatch时&#xff0c;损失如何记录 报错&#xff1a;UnboundLocalError: local variable coef referenced before assignment是什么回事 未溢出则不会报错&#xff0c;可以完整滴运行完成 indent 缩进 炫酷技能&#xff1a;一遍运行&#xff0c;一遍画图 实例1 解释…

Linux : Linux环境开发工具vim / gcc / makefile / gdb / git的使用

Linux环境开发工具的使用 一、操作系统的生态二、程序下载安装&#xff08;一&#xff09;程序安装方式&#xff08;二&#xff09;包管理器 yum / apt 运行原理 三、文本编辑器 vim&#xff08;一&#xff09;认识vim 下的操作模式&#xff08;二&#xff09;命令模式常用的快…

国产游戏崛起,燕云十六移动端1.9上线,ToDesk云电脑先开玩

游戏爱好者的利好消息出新了&#xff01;网易大型武侠仙游《燕云十六声》正式官宣&#xff0c;移动端要在1月9日正式上线了&#xff01;你期待手游版的燕云吗&#xff1f;不妨评论区留言说说你的看法。小编分别花了几个小时在台式机电脑和手机上都试了下&#xff0c;欣赏画面还…

力扣刷题:数组OJ篇(下)

大家好&#xff0c;这里是小编的博客频道 小编的博客&#xff1a;就爱学编程 很高兴在CSDN这个大家庭与大家相识&#xff0c;希望能在这里与大家共同进步&#xff0c;共同收获更好的自己&#xff01;&#xff01;&#xff01; 目录 1.轮转数组&#xff08;1&#xff09;题目描述…

有序数据中插入不确定数据保证数据插入的位置顺序正确排序

解决有序数据中插入不确定数据保证数据插入的位置顺序正确排序 前言 java 数据库中存储自增id 有序的数据&#xff0c; 前端页面基于 id 5和 6 之间新增一条数据&#xff0c;在 id 6 和 7之间新增 2条&#xff0c;或者更复杂的场景&#xff0c;后台接口如何保存数据使得页面数…

python无需验证码免登录12306抢票 --selenium(2)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 [TOC](python无需验证码免登录12306抢票 --selenium(2)) 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 就在刚刚我抢的票&#xff1a;2025年1月8日…

DNS协议漏洞利用实验_hust计算机网络安全实验

文章目录 计算机网络安全实验 DNS协议漏洞利用实验 docker使用 建立实验环境docker常用指令 一些注意事项设置本地 DNS 服务器 配置用户计算机设置本地DNS服务器在本地 DNS 服务器中建一个区域 修改主机文件&#xff08;可略&#xff09;netwox实施DNS的用户响应欺骗攻击netwo…

基于MP157AAA的I2C练习

练习要求&#xff1a; 通过I2C分别实现与芯片si7006(获取湿度、温度)和芯片ap3216(获取环境光照强度)的通讯&#xff1b; 1、运行效果 2、分析ap3216如何获取光照强度 2.1、需要操作的寄存器 通过分析手册&#xff0c;需要操作以下寄存器: 0x00&#xff1a;系统配置 0x0C&…

【Linux】深入理解文件系统(超详细)

目录 一.磁盘 1-1 磁盘、服务器、机柜、机房 &#x1f4cc;补充&#xff1a; &#x1f4cc;通常网络中用高低电平&#xff0c;磁盘中用磁化方向来表示。以下是具体说明&#xff1a; &#x1f4cc;如果有一块磁盘要进行销毁该怎么办&#xff1f; 1-2 磁盘存储结构 ​编辑…

网络安全图谱以及溯源算法

​ 本文提出了一种网络攻击溯源框架&#xff0c;以及一种网络安全知识图谱&#xff0c;该图由六个部分组成&#xff0c;G <H&#xff0c;V&#xff0c;A&#xff0c;E&#xff0c;L&#xff0c;S&#xff0c;R>。 1|11.知识图 ​ 网络知识图由六个部分组成&#xff0c…

《Spring Framework实战》7:4.1.2.容器概述

欢迎观看《Spring Framework实战》视频教程 容器概述 该接口表示 Spring IoC 容器&#xff0c;并负责实例化、配置和组装 bean。 容器在组件上获取其指令&#xff0c;以实例化、配置和 通过读取配置元数据进行汇编。可以表示配置元数据 作为带注释的组件类、具有工厂方法的配置…

学生公寓技术规格书如何编写?

学生公寓限电柜的技术规格书主要包括以下内容‌&#xff1a; ‌用电计量计费‌&#xff1a;限电柜可以通过计算机售电管理系统进行用电计量计费&#xff0c;学生需要预交电费&#xff0c;系统会自动将数据传给控电柜和配电箱&#xff0c;对宿舍的电量进行累减计量‌。 ‌时间控…

【HarmonyOS NEXT】鸿蒙应用点9图的处理(draw9patch)

【HarmonyOS NEXT】鸿蒙应用点9图的处理&#xff08;draw9patch&#xff09; 一、前言&#xff1a; 首先在鸿蒙中是不支持安卓 .9图的图片直接使用。只有类似拉伸的处理方案&#xff0c;鸿蒙提供的Image组件有与点九图相同功能的API设置。 可以通过设置resizable属性来设置R…

SpringBoot 使用 Cache 集成 Redis做缓存保姆教程

1. 项目背景 Spring Cache是Spring框架提供的一个缓存抽象层&#xff0c;它简化了缓存的使用和管理。Spring Cache默认使用服务器内存&#xff0c;并无法控制缓存时长&#xff0c;查找缓存中的数据比较麻烦。 因此Spring Cache支持将缓存数据集成到各种缓存中间件中。本文已常…

MySQL事件功能简介

MySQL 的事件调度器&#xff08;Event Scheduler&#xff09;提供了一种便捷的方法来定时执行 SQL 语句&#xff0c;从而实现数据维护、报告生成等自动化操作。本文将详细介绍 MySQL 的事件功能&#xff0c;并说明如何使用 Navicat 管理这些事件。 1. 什么是 MySQL 事件调度器…

高光谱相机的特点

光谱特性 高光谱分辨率&#xff1a;能将光谱范围分割成极窄的波段&#xff0c;光谱分辨率通常达到纳米级甚至亚纳米级&#xff0c;可精确捕捉到不同物质在细微光谱差异上的特征&#xff0c;比如可以区分不同种类的植被因叶绿素含量等差异而在光谱上的细微变化。 多波段探测&a…

备考蓝桥杯:数据结构概念浅谈

目录 1数据结构的概念 什么是数据结构: 为什么要有数据结构 2.数据结构的三个组成要素 1.逻辑结构 2.存储结构 3.数据运算 3。算法好坏的度量&#xff08;时间复杂度和空间复杂度&#xff09; 时间复杂度计算 最优和平均和最差时间复杂度 计算时间复杂度例子 空间复…

闲谭SpringBoot--ShardingSphere分库分表探究

文章目录 1. 背景2. 创建数据库3. 修改yml配置文件4. 分片算法类5. 测试6 小结 1. 背景 接上文&#xff0c;我们对日志表&#xff0c;进行了按月的分表&#xff0c;这样每个月几百万条数据量还是扛得住的。 但是如果数据再多呢&#xff0c;除了提高硬件性能&#xff0c;还有一…

基于伪分布式模式部署Hadoop集群

1.上传Hadoop安装包 在/export/software目录下使用rz命令上传Hadoop安装包 2.创建目录 在/export/servers目录下创建wfb-hadoop目录&#xff0c;用于存放Hadoop的安装目录&#xff0c;命令如下&#xff1a; mkdir -p /export/servers/wfb-hadoop 3.安装Hadoop 1)将Hadoop安…