【数据结构与算法】图像——四叉树自适应模糊(ppm图像为例)

news2024/9/22 1:15:18

源于大作业~~

目录

前言

一、实现算法

二、结果展示

三、算法框架 

(1) QuadTreeNode.h

(2) 结点扩展、细化模糊层次 

(3) 模糊化图像四叉树转为图像

(4) 主函数代码

四、说明

五、结语 


前言

一张图片常常会存在空间冗余,即一大部分区域的色彩值相同,然而存储时却将这些像素块视作不同的色彩值,以满足较好的格式规整化。除了存储图片外,对于图片精度不是很高的要求、或者说要求对图片进行一定的模糊化处理,这种种情况都要求对图片的空间冗余进行降低。

针对模糊处理图片的要求,对图片分成四个象限,用一颗四叉树记录,四叉树的叶子结点记录图片的像素值,中间结点用于评判/细分模糊层次。

这样就可以根据一张图片的冗余/细节的分布,自动地进行选择模糊层次。

关键词:四叉树,自适应模糊,图片处理,空间冗余


一、实现算法

模糊化/降低冗余等等,可以将一块区域的色彩值用一个RGB块代替,而不至于每个色彩都单独备份一个。而这个过程,可以将一块区域的像素值,通过计算、选择出一个代表的像素值,来代替这个区域的所有像素值。针对模糊图片问题,为了保持一定的平滑性,采取中位数/均值等简单方法可以做到,也可以进阶采用高斯模糊等等手段。我采用了简单的均值模糊。

然而,一张图片,总是有部分存在空间冗余,部分边缘细节较多,统一的进行模糊,是不理智且不满足要求的。对此,评判一张图片是否需要模糊化,我们可以通过判断其“离散”情况来选择。最简单的“离散”情况度量,即计算RGB三色的方差。当方差和阈值Tolerance进行比较,小于阈值意味着这一个区域的相似程度足够高可以进行均值模糊;大于阈值则意味着相似程度不够高,需要继续细分细化,再进行上述操作。

对此,可以得出以下递归算法:

①图像计算RGB三色方差D1,D2,D3。

②D1>Tolerance || D2>Tolerance || D3>Tolerance 跳转到③否则跳转到④

③标记子图为中间结点。将子图分为四个区域,对每个子图,跳转到①

④计算子图RGB的均值ER,EG,EB,将这一区域所有的像素RGB值赋为对应均值ER,EG,EB。标记为叶子结点。返回。

    一开始,用一个四叉树结点root记录整张图片的像素信息,采用上述递归算法,可以将这一个root结点扩展到一棵树,这棵树的所有的叶子结点记录着整个模糊化后的图的信息。

    将整棵树转化为图时,只需要遍历整棵树,将叶子结点的色彩区块信息取出并整合,就可以得到模糊化后的图片。

不是很明白算法?看下面这张图片你就明白了!

对图片划分越细,细节越多;反之越粗糙。对于那些分块后满足阈值要求的图像,就模糊并存储其像素值,否则继续细分——直到满足阈值或图片足够小。

二、结果展示 

原图:

Tolerance:0                               

      Tolerance:5

Tolerance:15

Tolerance:25

Tolerance:35

Tolerance:50

Tolerance:100(haha~~)


三、算法框架 

因为大作业提交时间还没有截止,所以不方便开源所有代码,这里给出框架。

(1) QuadTreeNode.h

struct Pos	//偏移量记录
{
    int x, y;
};
struct color	//像素RGB值记录
{
    unsigned char r;
    unsigned char g;
    unsigned char b;
};
class QuadTreeNode
{
public:
//记录细分的四个子图(valid==false,需要细化的情况下链接子图)
QuadTreeNode *q1, *q2, *q3, *q4; // 1~4象限
//记录子图相对于原图的偏移量,以便树转图
Pos position;
//记录子图的长宽像素数
int height, width;
//记录是否为叶子结点,即是否为模糊化图像信息记录结点
bool valid;
//这一结点对应的范围的色彩信息
color **rgbs;
//记录结点深度
    int depth;
public:
    QuadTreeNode(color **r, int wd, int ht);
    QuadTreeNode(int posx, int posy, int wd, int ht);
//计算是否差异超过Tolerance
bool VarianceCalculate(int Tolerance);
//随机化模糊
bool RandomPuzzyTag();
//计算R均值
int AverageR();
//计算G均值
int AverageG();
//计算B均值
int AverageB();
//模糊化区域
    void Fuzzify();
};

(2) 结点扩展、细化模糊层次 

//以Tolerance为模糊阈值,扩展rt结点(自然少不了递归)
void TreeFuzzifyExtend(QuadTreeNode *rt, int Tolerance){...}

(3) 模糊化图像四叉树转为图像

//将四叉树记录的模糊化后的图像像素信息传递给二维数组img[][]
void TreeToImage(QuadTreeNode *rt, color **img){...}

(4) 主函数代码

值得说明的是,实验所给的图片为ppm格式,因此读写比较特殊。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "QuadTreeNode.h"
// #include "QuadTree.h"
#include "QuadTreeFunc.h"

void printImage(char *fileName, int width, color **a);
// color color;

// To get ppm image from jpeg file, please visit https://convertio.co/jpg-ppm/
void readImage(int p, char *inFile, char *outFile) // Note that width == height here
{
	FILE *f = fopen(inFile, "rb");

	char u[3]; // placehoder
	int width, height, max_value;
	fscanf(f, "%s%d%d%d%c", u, &width, &height, &max_value, &u[0]);

	int i;
	color **colors, **img;
	colors = (color **)malloc(height * sizeof(color *));
	img = (color **)malloc(height * sizeof(color *));
	for (i = 0; i < height; i++)
	{
		colors[i] = (color *)malloc(width * sizeof(color));
		img[i] = (color *)malloc(width * sizeof(color));
	}
	for (i = 0; i < height; i++)
		fread(colors[i], sizeof(color), width, f);
	fclose(f);
	//=============================================================
	QuadTreeNode *rt = new QuadTreeNode(colors, width, height);
	TreeFuzzifyExtend(rt,100);
	TreeToImage(rt, img);
	//=============================================================
	printImage(outFile, width, img);
}

void printImage(char *fileName, int width, color **a) // Note that width == height here
{
	FILE *f = fopen(fileName, "wb");

	fprintf(f, "P6\n");
	fprintf(f, "%d %d\n", width, width);
	fprintf(f, "255\n");

	int i;
	for (i = 0; i < width; i++)
		fwrite(a[i], sizeof(color), width, f);

	fclose(f);
}

// int main(int argc, char **argv)
int main()
{
	int tolerance = 0;
	char inFile[100];
	char outFile[100];
	// if (argc > 1)
	{
		// tolerance = atoi(argv[1]);
		// inFile = argv[2];
		// outFile = argv[3];
		strcpy(inFile,"D:\\...\\a.ppm");
		strcpy(outFile,"D:\\...\\result.ppm");
		readImage(tolerance, inFile, outFile);
	}
	return 0;
}

 除了正常的I/O和预处理,自己编写的部分,千言万语汇成主函数的几行话:


四、说明

1、可以采用命令行读取指令的方式,但是为了方便调试,我修改了那部分源代码。可以通过重载的main函数 int main(int argc, char **argv) 来实现。

2、除了均值模糊外,还可以选择中位数模糊

3、随机模糊化处理的部分,被我注释掉了

4、将ppm格式转为jpg格式可以简单的采用python库函数

from PIL import Image
 
img = Image.open("D:\\...\\a.ppm")
img.save("D:\\...\\a.jpg")

#img.show()

5、为了得到更加平滑的处理结果,可以了解一下高斯模糊这种高级的玩意

6、其余源代码将在大作业提交结束后上传开源。 


五、结语

无论数据结构与算法还是程序设计等等 ,不要局限于作业,做一些小东西,小项目,小工程,小工具等等,都会让学习变得有趣。谁不想有一个能吹牛逼的本科呢?

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

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

相关文章

Node.js二:fs模块

一.fs模块概述 2.fs异步写入 /*** 新建一个文件夹&#xff0c;座右铭.txt&#xff0c;写入内容三人行必有我师焉*///1.导入fs模块 const fs require(fs);//2.写入文件 fs.writeFile(./座右铭.txt,三人行必有我师焉,err >{//err写入失败&#xff1a;错误对象&#xff0c;写…

搭建CDH错误记录(踩坑无数)

搭建CDH流程记录 如何搭建本地yum源 1.配置yum源这里使用 阿里源 http://mirrors.aliyun.com/repo/Centos-7.repo wget http://mirrors.aliyun.com/repo/Centos-7.repo2.安装http软件 yum install httpd -y3.配置httpd.conf vi /etc/httpd/conf/httpd.conf在 AddType appli…

【社区图书馆】vue的生命周期

目录 vue的生命周期 生命周期流程 Init Events & Lifecycle beforeCreate Init injections & reactivity created beforeMount Create vm $el and replace ‘el’ with it mounted beforeUpdate Virtual Dom re-render and patch updated beforeDestroy vm…

python+vue 大学生社团管理系统

本系统分为学生&#xff0c;管理员&#xff0c;社团负责人三个角色&#xff0c;学生可以注册登陆系统&#xff0c;查看社团&#xff0c;申请入团&#xff0c;查看参加社团活动&#xff0c;查看社团新闻&#xff0c;社团负责人对社团信息&#xff0c;入团审核&#xff0c;社团新…

Opencv+Python笔记(五)图像阈值化处理

图像阈值化可以理解为一个简单的图像分割操作&#xff0c;阈值又称为临界值&#xff0c;它的目的是确定出一个范围&#xff0c;然后这个范围内的像素点使用同一种方法处理&#xff0c;而阈值之外的部分则使用另一种处理方法或保持原样。 阈值处理有2种方式&#xff0c;一种是固…

ijkplayer解码流程源码解读

ijkplayer是一款基于ffmpeg的在移动端比较流行的开源播放器。FFmpeg是一款用于多媒体处理、音视频编解码的自由软件工程&#xff0c;采用LGPL或GPL许可证。 要想理解ijkplayer源码&#xff0c;首先得知道视频播放器的基本原理。 视频播放器播放一个互联网上的视频文件&#xf…

win10怎么录屏幕视频带声音?有哪些需要注意的地方?

随着科技的不断发展&#xff0c;屏幕录制已成为常见的工具之一。在Win10系统中&#xff0c;录制屏幕视频带声音也变得越来越简单。本文将指导您如何在Win10上实现录制屏幕视频带声音&#xff0c;并介绍一些需要注意的地方。 需要用到的工具和步骤 在Win10系统中&#xff0c;自…

【u盘提示:驱动器未格式化】如何解决?

u盘虽然使用很方便&#xff0c;可随时拷贝资料到任何有电脑的地方&#xff0c;但它的问题也是比较多的&#xff0c;其中u盘提示驱动器未格式化故障最让人心虚&#xff0c;因为已经无法打开u盘了&#xff0c;里面的资料怎么办&#xff0c;很重要的怎么办&#xff0c;所以今天就教…

OAuth2.0 实战总结

title: OAuth2.0 实战总结 date: 2023-01-30 11:23:12 tags: OAuth2.0 categories:开发技术及框架 cover: https://cover.png feature: false 1. 引言 1.1 OAuth 2.0 是什么&#xff1f; 用一句话总结来说&#xff0c;OAuth 2.0 就是一种授权协议。那如何理解这里的“授权”…

前端调试技巧

前端工作中&#xff0c;不仅编码很重要&#xff0c;重现bug&#xff0c;解决bug的能力同样重要。而这些都离不开代码调试。本文就一些调试技巧做出总结&#xff0c;不足之处&#xff0c;欢迎大家多多补充。 PC调试 console.log() 在你觉得有问题的代码处&#xff0c;加上一句 …

基于HFSS软件24GHz雷达天线设计

前言&#xff1a;近年来&#xff0c;我国的汽车保有量不断增加&#xff0c;汽车交通事故引发的财产损失和人 员伤亡也在不断增加。为了有效减少交通事故发生&#xff0c;车载雷达得到了各大汽车厂商和各个研究机构的普遍重视。现在国际上主要国家都把 24GHz 和 77GHz 两个频段分…

解决谷歌翻译不能使用的问题

今天登录国外网站&#xff0c;发现谷歌翻译已无法正常使用&#xff0c;网上最多的方法就是更改host文件&#xff0c;在host内增加ip地址&#xff0c;但是经常失效&#xff0c;经常手动更改增加ip着实烦恼&#xff0c;还有可能有别的错误。 最终解决方式是&#xff1a;登录GitH…

新版本ProPhet时间序列预测1:模型解释和安装和初步使用

ProPhet时间序列预测1安装和初步使用 安装pip安装conda安装 Prophet模型使用读取数据将数据处理为ds和y两列看下数据的分布模型训练预测可视化预测结果可视化趋势、假期、每周、季节性、年度季节性的回归图1.0之前模型保存 安装 安装1.0版本之后: 区别: 1.0版本叫prophet <…

设计模式-行为型模式之策略模式

5. 策略模式 5.1. 模式动机 完成一项任务&#xff0c;往往可以有多种不同的方式&#xff0c;每一种方式称为一个策略&#xff0c;我们可以根据环境或者条件的不同选择不同的策略来完成该项任务。 在软件开发中也常常遇到类似的情况&#xff0c;实现某一个功能有多个途径&#x…

【原理图专题】如何把PCB元件位号重排并反标到原理图

在画原理图时我们有时会复制以前项目或其他项目已经现成的模块进行电路的搭建。但可能会遇到一个问题,就是复制过来后位号也跟着过来了。比如说一个板子可能只有100个元件,但是会出现位号上千的元件。这对于后面我们焊接、维修等都很不利。 那可能有人会问,我直接在画完原理…

Redis持久化机制导致服务自启动后恢复数据过长无法使用以及如何关闭

场景 若依前后端分离版手把手教你本地搭建环境并运行项目&#xff1a; 若依前后端分离版手把手教你本地搭建环境并运行项目_霸道流氓气质的博客-CSDN博客 在上面搭建前后端分离的项目后&#xff0c;如果需要在windows服务上进行部署。 若依前后端分离版本&#xff0c;Windo…

58 openEuler搭建Mariadb数据库服务器-管理数据库

文章目录 58 openEuler搭建Mariadb数据库服务器-管理数据库58.1 创建数据库58.2 查看数据库58.3 选择数据库58.4 删除数据库58.5 备份数据库58.6 恢复数据库 58 openEuler搭建Mariadb数据库服务器-管理数据库 58.1 创建数据库 可以使用CREATE DATABASE语句来创建数据库。 CR…

Jetson Nano (4GB)烧写jetbot Image

一、Image下载 1、官方下载&#xff0c;浏览器访问Using SD Card Image - JetBot&#xff0c;下载jetbot-043_nano-4gb-jp45.zip。 注意&#xff1a;通过此方式下载需要电脑能访问外网。 2、天翼网盘下载&#xff0c;https://cloud.189.cn/t/q2mUJv7jaIna &#xff08;访问码…

【三十天精通Vue 3】 第十五天 Vue 3的异步组件和代码拆分

✅创作者&#xff1a;陈书予 &#x1f389;个人主页&#xff1a;陈书予的个人主页 &#x1f341;陈书予的个人社区&#xff0c;欢迎你的加入: 陈书予的社区 &#x1f31f;专栏地址: 三十天精通 Vue 3 文章目录 引言一、Vue 3 中的异步组件1.1 异步组件的概念1.2 Vue 3 中的异步…

Python机器学习、深度学习技术提升气象、海洋、水文领域应用

Python是功能强大、免费、开源&#xff0c;实现面向对象的编程语言&#xff0c;能够在不同操作系统和平台使用&#xff0c;简洁的语法和解释性语言使其成为理想的脚本语言。除了标准库&#xff0c;还有丰富的第三方库&#xff0c;Python在数据处理、科学计算、数学建模、数据挖…