《数据结构、算法与应用C++语言描述》-队列的应用-图元识别问题

本文主要是介绍《数据结构、算法与应用C++语言描述》-队列的应用-图元识别问题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

《数据结构、算法与应用C++语言描述》-队列的应用-图元识别问题

图元识别

问题描述

数字化图像是一个 mxm 的像素矩阵。在单色图像中,每一个像素要么为0,要么为 1。值为0的像素表示图像的背景。值为1的像素表示图元上的一个点,称其为图元像素。两个像素是相邻的,是指它们左右相邻或上下相邻。两个相邻的图元像素是同一个图元的像素。图元识别的目的就是给图元像素做标记,使得两个像素标记相同,当且仅当它们是同一个图元的像素。

考察图 9-14a,它是一个7×7 图像。空白方格表示背景像素,标记为1 的方格表示图元像素。像素(1,3)和(2,3)是同一个图元的像素,因为它们是相邻的。像素(2,4)与(2,3)是相邻的,它们也属于同一图元。因此,三个像素(1,3)、(2,3)和(2,4)属于同一个图元。由于没有其他的像素与这三个像素相邻,因此这三个像素定义了一个图元。图 9-14a 的图像有 4 个图元。第一个图元是像素集合{(1,3),(2,3),(2,4)};第二个是{(3,5),(4,4),(4,5),(5,5)};第三个是{(5,2),(6,1),(6,2),(6,3),(7,1),(7,2),(7,3)};第四个是{(5,7),(6,7),(7,6),(7,7))。在图9-14b中,图元像素都做了标记,两个像素标记相同,当且仅当它们属于同一个图元。我们用数字 2,3,4,…作为图元标记。这里我们没有用数字1 做图元标记,是因为我们用1表示未做标记的图元像素。
在这里插入图片描述

求解策略

通过扫描像素来识别图元。扫描的方式是逐行扫描,每一行逐列扫描。当扫描到一个未标记的图元像素时,给它一个图元标记。然后把这个图元像素作为一个新图元的种子,通过识别和标记所有与该种子相邻的图元像素,来寻找新图元剩余的像素。与种子相邻的图元像素称为1-间距像素。然后,识别和标记与1-间距像素相邻的所有未标记的图元像素,这些像素被称为2-间距像素。接下来识别和标记与2-间距像素相邻的未标记的图元像素。这个过程一直持续到没有新的、未标记的、相邻的图元像素为止。

代码

#include <iostream>
#include <queue>
using namespace std;/*用于存储迷宫地址的结构体*/
struct position
{int row,  //行col;  //列position() {}position(int prow, int pcol):row(prow),col(pcol){}operator int() const { return row; }friend ostream& operator<<(ostream& out, const position x){out << "(" << x.row << "," << x.col << ")";return out;}
};
/*创建二维数组*/
template <class T>
bool make2dArray(T**& x, int numberOfRows, int numberOfColumns)
{try {//行指针x = new T * [numberOfRows];//为每一行分配内存for (int i = 0; i < numberOfRows; i++)x[i] = new int[numberOfColumns];return true;}catch (bad_alloc) { return false; }
}/*遍历二维数组*/
template<class T>
void traverse2dArray(T**& x, int numberOfRows, int numberOfColumns)
{for (int i = 0; i < numberOfRows; i++){for (int j = 0; j < numberOfColumns; j++){cout.width(4);cout << x[i][j] << "  ";}cout << endl;}
}/*图元识别问题全局变量*/
int** pixel;//二维方阵
int pixelSize;//方阵大小/*图元识别*/
/*方格元素为1表示为有像素,方格元素为0表示无像素*/
/*标记为n(n>1)表示为第n个图元*/
void inputPixelQueue()//输入像素矩阵
{cout << "Please enter the size of pixel-Matrix:";while (!(cin >> pixelSize)){cin.clear();//清空标志位while (cin.get() != '\n')//删除无效的输入continue;cout << "Please enter the size of pixel-Matrix:";}//+2的原因是为了避免在处理内部位置和边界位置时存在差别make2dArray<int>(pixel, pixelSize + 2, pixelSize + 2);//初始化边界位置的数值for (int i = 0; i <= pixelSize + 1; i++){pixel[i][0] = 0;pixel[0][i] = 0;pixel[i][pixelSize + 1] = 0;pixel[pixelSize + 1][i] = 0;}//初始化像素for (int i = 1; i <= pixelSize; i++)for (int j = 1; j <= pixelSize; j++){int positionij;cout << "Please enter pixel[" << i << "," << j << "]:";while (!(cin >> positionij)){cin.clear();//清空标志位while (cin.get() != '\n')//删除无效的输入continue;cout << "Please enter pixel[" << i << "," << j << "]:";}pixel[i][j] = positionij;}cout << "The pixel = " << endl;traverse2dArray<int>(pixel, pixelSize + 2, pixelSize + 2);
}
void labelComponents()
{inputPixelQueue();//输入迷宫,Grid二维数组和数组大小GridSize和电路布线共享//初始化偏移量position offset[4];offset[0].row = 0; offset[0].col = 1;//右offset[1].row = 1; offset[1].col = 0;//下offset[2].row = 0; offset[2].col = -1;//左offset[3].row = -1; offset[3].col = 0;//上int numberOfNbrs = 4;//一个像素的相邻位置数//扫描所有像素,标记图元queue<position> q;int id = 1;position here, nbr;for(int i = 1;i <= pixelSize;i++)for (int j = 1; j <= pixelSize; j++){if (pixel[i][j] == 1)//新图元{pixel[i][j] = ++id;here.row = i;here.col = j;while (true){for (int k = 0; k < numberOfNbrs; k++){nbr.row = here.row + offset[k].row;nbr.col = here.col + offset[k].col;if (pixel[nbr.row][nbr.col] == 1){pixel[nbr.row][nbr.col] = id;q.push(nbr);}}//图元中无未考察的像素if (q.empty()) break;here = q.front();q.pop();}}}cout << "The pixel = " << endl;traverse2dArray<int>(pixel, pixelSize+1, pixelSize+2);
}int main()
{cout << "图元识别问题********************" << endl;labelComponents();return 0;
}

运行结果

C:\Users\15495\Documents\Jasmine\Work\coding\cmake-build-debug\coding.exe
鍥惧厓璇嗗埆闂********************
Please enter the size of pixel-Matrix:7
Please enter pixel[1,1]:0
Please enter pixel[1,2]:0
Please enter pixel[1,3]:1
Please enter pixel[1,4]:0
Please enter pixel[1,5]:0
Please enter pixel[1,6]:0
Please enter pixel[1,7]:0
Please enter pixel[2,1]:0
Please enter pixel[2,2]:0
Please enter pixel[2,3]:1
Please enter pixel[2,4]:1
Please enter pixel[2,5]:0
Please enter pixel[2,6]:0
Please enter pixel[2,7]:0
Please enter pixel[3,1]:0
Please enter pixel[3,2]:0
Please enter pixel[3,3]:0
Please enter pixel[3,4]:0
Please enter pixel[3,5]:1
Please enter pixel[3,6]:0
Please enter pixel[3,7]:0
Please enter pixel[4,1]:0
Please enter pixel[4,2]:0
Please enter pixel[4,3]:0
Please enter pixel[4,4]:1
Please enter pixel[4,5]:1
Please enter pixel[4,6]:0
Please enter pixel[4,7]:0
Please enter pixel[5,1]:0
Please enter pixel[5,2]:1
Please enter pixel[5,3]:0
Please enter pixel[5,4]:0
Please enter pixel[5,5]:1
Please enter pixel[5,6]:0
Please enter pixel[5,7]:1
Please enter pixel[6,1]:1
Please enter pixel[6,2]:1
Please enter pixel[6,3]:1
Please enter pixel[6,4]:0
Please enter pixel[6,5]:0
Please enter pixel[6,6]:0
Please enter pixel[6,7]:1
Please enter pixel[7,1]:1
Please enter pixel[7,2]:1
Please enter pixel[7,3]:1
Please enter pixel[7,4]:0
Please enter pixel[7,5]:0
Please enter pixel[7,6]:1
Please enter pixel[7,7]:1
The pixel =0     0     0     0     0     0     0     0     00     0     0     1     0     0     0     0     00     0     0     1     1     0     0     0     00     0     0     0     0     1     0     0     00     0     0     0     1     1     0     0     00     0     1     0     0     1     0     1     00     1     1     1     0     0     0     1     00     1     1     1     0     0     1     1     00     0     0     0     0     0     0     0     0  
The pixel =0     0     0     0     0     0     0     0     00     0     0     2     0     0     0     0     00     0     0     2     2     0     0     0     00     0     0     0     0     3     0     0     00     0     0     0     3     3     0     0     00     0     4     0     0     3     0     5     00     4     4     4     0     0     0     5     00     4     4     4     0     0     5     5     0Process finished with exit code 0

这篇关于《数据结构、算法与应用C++语言描述》-队列的应用-图元识别问题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/250156

相关文章

PostgreSQL的扩展dict_int应用案例解析

《PostgreSQL的扩展dict_int应用案例解析》dict_int扩展为PostgreSQL提供了专业的整数文本处理能力,特别适合需要精确处理数字内容的搜索场景,本文给大家介绍PostgreS... 目录PostgreSQL的扩展dict_int一、扩展概述二、核心功能三、安装与启用四、字典配置方法

Go语言中make和new的区别及说明

《Go语言中make和new的区别及说明》:本文主要介绍Go语言中make和new的区别及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1 概述2 new 函数2.1 功能2.2 语法2.3 初始化案例3 make 函数3.1 功能3.2 语法3.3 初始化

怎样通过分析GC日志来定位Java进程的内存问题

《怎样通过分析GC日志来定位Java进程的内存问题》:本文主要介绍怎样通过分析GC日志来定位Java进程的内存问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、GC 日志基础配置1. 启用详细 GC 日志2. 不同收集器的日志格式二、关键指标与分析维度1.

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

Python中re模块结合正则表达式的实际应用案例

《Python中re模块结合正则表达式的实际应用案例》Python中的re模块是用于处理正则表达式的强大工具,正则表达式是一种用来匹配字符串的模式,它可以在文本中搜索和匹配特定的字符串模式,这篇文章主... 目录前言re模块常用函数一、查看文本中是否包含 A 或 B 字符串二、替换多个关键词为统一格式三、提

从入门到精通C++11 <chrono> 库特性

《从入门到精通C++11<chrono>库特性》chrono库是C++11中一个非常强大和实用的库,它为时间处理提供了丰富的功能和类型安全的接口,通过本文的介绍,我们了解了chrono库的基本概念... 目录一、引言1.1 为什么需要<chrono>库1.2<chrono>库的基本概念二、时间段(Durat

Redis出现中文乱码的问题及解决

《Redis出现中文乱码的问题及解决》:本文主要介绍Redis出现中文乱码的问题及解决,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 问题的产生2China编程. 问题的解决redihttp://www.chinasem.cns数据进制问题的解决中文乱码问题解决总结

Go语言中nil判断的注意事项(最新推荐)

《Go语言中nil判断的注意事项(最新推荐)》本文给大家介绍Go语言中nil判断的注意事项,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1.接口变量的特殊行为2.nil的合法类型3.nil值的实用行为4.自定义类型与nil5.反射判断nil6.函数返回的

C++20管道运算符的实现示例

《C++20管道运算符的实现示例》本文简要介绍C++20管道运算符的使用与实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录标准库的管道运算符使用自己实现类似的管道运算符我们不打算介绍太多,因为它实际属于c++20最为重要的