栅格一矢量数据转换是数据转换的一种方法,即矢量与栅格两种数据形式之间的转换技术。空间数据表示的两种方法各有优缺点和适用场合,因此需要根据使用目的进行栅格一矢量数据的转换。

矢量数据向栅格数据的转换一般比较方便;对于点、线目标,由其所在的栅格行、列数表示,对于面状目标,则需判定落人该面积内的像元.通常栅格(像元)尺寸均大于原来坐标表示的分辨率,所以若将栅格化数据再反转回去,则不可能达到原来矢量数据的精度.将矢量数据转化为栅格数据,主要用于空间分析、多边形叠置等。

        栅格数据矢量化较为复杂,如果由一幅扫描的数字化地图来建立矢量数据库,则需要经过数字图象处理,如边缘增强、细化、二值化、特征提取及模式识别才能获得矢量数据。人们通常将多色地图分色后逐个元素(如等高线地貌、水系、道路网、地物、符号与注记等)加以识别和提取。如果将数字影像矢量化,则需要事先做好重采样、图象处理、影像匹配和影像理解等过程,才能将影像上的语义和非语义信息提取出来,并形成矢量形式的数据。

说明:栅格数据矢量化流程参考:GIS中栅格数据转换矢量数据算法 | 麻辣GIS

一、栅格数据矢量化流程

1、二值化

由于扫描后的图像是以不同灰度级存储的,为了进行栅格数据矢量化的转换,需压缩为两级(0和1),称为二值化。

2、二值图像预处理

对于扫描输入的图幅,由于原稿不干净等原因,总是会出现一些飞白、污点、线划边缘凹凸不平等。

3、细化骨架化

所谓细化就是将二值图像象元阵列逐步剥除轮廓边缘的点,使之成为线划宽度只有一个象元的骨架图形。细化后的图形骨架既保留了原图形的绝大部分特征,又便于下一步的跟踪处理。

细化的基本过程是:

  1. 确定需细化的象元集合;
  2. 移去不是骨架的象元;
  3. 重复,直到仅剩骨架象元;

如果是对扫描后的地图图像进行细化处理,应符合下列基本要求:

  1. 保持原线划的连续性;
  2. 线宽只为一个象元;
  3. 细划后的骨架应是原线划的中心线;
  4. 保持图形的原有特征;

4、追踪

细化后的二值图像形成了骨架图,追踪就是把骨架转换为矢量图形的坐标序列。其基本步骤为:

  1. 从左向右,从上向下搜索线划起始点,并记下坐标;
  2. 朝该点的8个方向追踪点,若没有,则本条线的追踪结束,转(1)进行下条线的追踪;否则记下坐标;
  3. 把搜索点移到新取的点上,转(2);

注意的是,已追踪点应作标记,防止重复追踪。

5、拓扑化

为了进拓扑化,需找出线的端点和结点,以及孤立点。

  1. 孤立点:8邻城中没有为1的象元。如图(1);
  2. 端点:8邻城中只有一个为1的象元。如图(2);
  3. 结点:8邻城中有三个或三个以上为1的象元。如图(3);

二、栅格数据矢量化实验

1、栅格数据矢量化代码

说明:由于代码有点多,如果全部贴上去的话会造成博客有些卡顿(上一篇博客就是放太多代码造成打开时卡顿),所以下面三个源文件都是只放了部分代码,如果需要完整工程,见底部链接!!!

(1)myVector.h

//命名空间只在头文件中包含即可,否则易出错
using namespace std;
using namespace cv;class myVector
{
public:myVector();~myVector();//定义结构体,和类的作用类似struct result{QVector<QVector<Point2d> > roads; //Point2d二维数据点类型,用于存放坐标QVector<double> width;QString ImageFilePath;int rows;int cols;};public:QVector<result> roadInformation;   //保存矢量化后的数据结果,包括新旧影像//************************** 道路细化 **************************////对输入图像道路进行细化//void imageThin(Mat& src, Mat& dst);//道路细化查表法//Mat img_bone(Mat& mat);//查表法//Mat lookUpTable(Mat& mat, int lut[]);//************************** 道路矢量化 **************************////利用栅格道路数据创建矢量化道路数据,切割大小为deltaSizevoid  createVectorFromFile(QString inputFileName, int deltaSize);//利用栅格道路数据创建矢量化道路数据,不切割//void createVectorFromFile(QString inputFileName, QString outputFilePath);//道路矢量化//void createVector(Mat& binSrc, Mat& mix_src, Mat& endPoint, Mat& nodePoint, int index, bool cut, int startX, int startY);//简化矢量道路数据//void simplifyVector(int index);//简化矢量道路数据//QVector<Point2d> simplifyVector(QVector<Point2d> vector, int threshold);//输出矢量道路数据//void outputBinaryResult(int index, QString outputFilePath, QString str);

(2)myVector.cpp

//************************** 道路矢量化 **************************////利用栅格道路数据创建矢量化道路数据,不切割//
void myVector::createVectorFromFile(QString inputFileName, QString outputFilePath)
{clock_t start, finish;    //clock_t 是一个长整型数据类型,是一种用于保存时间的数据类型start = clock();        //返回值是该程序从启动到clock()函数调用占用CPU的时间,创建矢量化道路的起始时间double tim;Mat src_img, dst_img, imgbone, src_imgBool, imgbone_bool, imgnode_bool, img_endpoint_bool;//判断导入的数据是否存在,参数 0 是指imread按单通道的方式读入图像,即灰白图像if ((src_img = imread(inputFileName.toStdString(), 0)).empty()){cout << "load image error!";return;}result Result;                         //result是自定义的类Result.ImageFilePath = inputFileName;Result.rows = src_img.rows;Result.cols = src_img.cols;roadInformation.append(Result);         //添加当前影像数据/******************** 道路细化 ********************/qDebug() << "开始细化..." << endl;double thin_start = (double)getTickCount();//高斯滤波是一种线性滤波器,能够有效的抑制噪声、平滑图像GaussianBlur(src_img, src_img, Size(7, 7), 0, 0);//输入图像细化imageThin(src_img, src_imgBool);threshold(src_imgBool, src_imgBool, 0, 255, THRESH_OTSU);imgbone = img_bone(src_imgBool);double thin_end = ((double)getTickCount() - thin_start) / getTickFrequency();qDebug() << "细化道路数据使用时间:" << thin_end << "s" << endl;qDebug() << "细化结束!" << endl;//去掉噪,例如过滤很小或很大像素值的图像点//threshold(src_img, src_imgBool, 0, 255, THRESH_OTSU);//Mat imgbone = img_bone(src_imgBool);imwrite(".\\image_save\\roadThin.png", imgbone * 255);/******************** 道路矢量化 ********************/qDebug() << "开始矢量化..." << endl;double change_detection_start = (double)getTickCount();threshold(imgbone, imgbone_bool, 0, 255, THRESH_BINARY);Mat nodePoint = road_node(imgbone);                   //获取弧段连接点Mat endPoint = road_endpoint(imgbone);                //获取弧段端点Mat mix_node = LineBreak(imgbone_bool, nodePoint); //对弧段进行打断//矢量化createVector(src_imgBool, mix_node, endPoint, nodePoint, roadInformation.size() - 1, false, 0, 0);double vector_end = ((double)getTickCount() - change_detection_start) / getTickFrequency();qDebug() << "矢量化道路数据所用时间:" << vector_end << endl;
}

(3)main.cpp

#include<iostream>#include"myVector.h"// 注:main.cpp 文件中不能再添加命名空间,否则会调用自定义成员函数时找不到标识符int main()
{myVector roadThinAndVector;roadThinAndVector.createVectorFromFile("..\\testImage\\labels.png", "roadThin.png");  //旧时相影像栅格数据矢量化//简化矢量道路数据,也即一些预处理,如:平滑等roadThinAndVector.simplifyVector(0);       //旧影像//输出矢量道路数据简化后的道路数据roadThinAndVector.outputBinaryResult(0, "roadVector.png", ".\\old_vector_result.txt");qDebug() << "矢量化结束!" << endl;system("pause");return 0;
}

2、栅格数据矢量化结果

(1)输入二值图

(2) 细化、矢量化结果

 

说明:左图是细化结果,右图是矢量化结果; 

(3)配置说明

vs2019 + opencv4.4.0 + Qt5.12.5 + gdal2.3.2 + Debug x64

vs2019、opencv4.4.0 和 Qt5.12.5 的配置过程比较简单这里就不过多阐述了;

gdal2.3.2 的配置流程见:https://blog.csdn.net/weixin_47156401/article/details/120648970?spm=1001.2014.3001.5502

上述环境配置完成后使用该工程的过程中,若出现以下问题:

如果出现无法打开 Qt 源文件,解决方案见:https://blog.csdn.net/weixin_47156401/article/details/120626400?spm=1001.2014.3001.5502

说明:上述环境配置、问题解决方案都是通过亲测验证,真实有效!!!

代码工程文件中包含二值图细化、矢量化和矢量化简化等工程,且代码注释非常详细,由上述给出的部分代码也可以看出,在使用的过程中如有疑问,可留言!

工程链接:栅格数据矢量化代码实现-C/C++文档类资源-CSDN下载

栅格数据矢量化(附有完整代码)相关推荐

  1. 爬虫基础:python实现爬取无水印某瓜视频(附有完整代码,超详细)

    文章目录 一.前言 二.爬无水印的某瓜视频 1.分析网站 2.完整代码 三.总结 一.前言 爬虫真的很尴尬,稍微写点文章,分析网站什么的,就不给过,版权问题,哎,我会在边缘疯狂试探,一定要写详细点,让 ...

  2. 封装uniapp-uni-table组件,获取点击行事件,可传入自定义表头,传入后端数据,获取多选数据(其中行点击事件只有H5端可以用)附有完整代码

    功能如下:↓ 传值如下↓ data() {return {tableParam: {type: "selection", //是否可以多选loading: false,//加载状态 ...

  3. 高斯正反算—投影坐标转大地坐标、大地坐标转投影坐标(附有完整代码及测试结果)

            本文意在介绍高斯正反算的基本原理和代码实现!针对高斯正反算网上给出的方法很多,但是我试了之后发现多少都有些问题:或公式原理问题.或精度问题!         通过查找资料对其进行了总结 ...

  4. 入门C语言第三话:数组之实战篇——扫雷(进阶版——图形化界面,递归展开,播放音乐与音效,标记取消雷,记录雷的个数,鼠标点击,文末附有完整代码)

    文章目录 前言 每日鸡汤 基本思路 衔接基础班扫雷 准备阶段 正文 一.雷盘信息的存储 1.设置雷盘11*11与初始化 2.放置雷 3.放置雷周围的信息 二.图形化界面 1.创建与初始化窗口 2.加载 ...

  5. 【影像配准】遥感影像配准结果输出tif影像(附有完整代码)

            遥感影像经过配准后会输出两幅影像:配准后的参考影像和待配准影像:         注:png 转 tif         因为两幅多时像影像在拍摄时即便是同源也无法保证拍摄到的景象完全 ...

  6. ArcGIS实验教程——实验三十三:ArcScan自动矢量化完整案例教程

    ArcGIS实验视频教程合集:<ArcGIS实验教程从入门到精通>(附配套实验数据)> 文章目录 1 ArcScan 简介 2. ArcScan使用前提及注意事项 3. ArcGIS ...

  7. Stanford UFLDL教程 矢量化编程

    矢量化编程 当使用学习算法时,一段更快的代码通常意味着项目进展更快.例如,如果你的学习算法需要花费20分钟运行完成,这意味着你每个小时能"尝试"3个新主意.但是假如你的程序需要20 ...

  8. OpenCV差分二值化的实时场景文本检测的实例(附完整代码)

    OpenCV差分二值化的实时场景文本检测的实例 OpenCV差分二值化的实时场景文本检测的实例 OpenCV差分二值化的实时场景文本检测的实例 OpenCV差分二值化的实时场景文本检测的实例(附完整代 ...

  9. 【Android 插件化】VirtualApp 接入 ( 安装 APK 插件应用 | 启动插件 APK 应用 | MainActivity 安装启动插件完整代码 )

    文章目录 一.安装 APK 插件应用 二.启动插件 APK 应用 三.MainActivity 完整代码 四.博客源码 一.安装 APK 插件应用 调用 VirtualCore.get().insta ...

  10. scrapy中集成selenium+浏览器池实现selenium的并发爬取LCSC网站中非结构化表格数据+异步存储进mysql+完整代码

    爬取https://lcsc.com/products/Connectors_365.html这个网址下所有的表格数据. 蓝色的都是要爬取的子页面,要爬取子页面里面的表格数据 ,表格数据如下: 右上角 ...

最新文章

  1. java实现排程算法_康托展开算法和逆康托展开算法[Java实现]
  2. 华为服务器显示红色的心跳,服务器心跳检查
  3. 21 岁理工男开源的这个编辑器火了!
  4. 2.1、spring属性注入-Set方法注入
  5. 函数matlab,Matlab函数
  6. JavaScript 断点调试技巧
  7. android打包规范包含第三方库aar,Android Studio 打包AAR和第三方静态库(示例代码)
  8. Java 中的异常处理
  9. Python 模拟微博登陆,亲测有效!
  10. securecrt遇到一个致命的错误且必须关闭_淄博plc维修西门子plcs7-200致命错误7强制数据永久存储区错误...
  11. c语言编程流水灯与交通灯实验,C51单片机实验报告流水灯交通灯定时器双机交互时钟(10页)-原创力文档...
  12. firework、301重定向、二级域名、nofollow、网站伪静态化、TKD标签、robots、canonical标签
  13. ofd文件怎么编辑文字
  14. ANSYS入门——模态分析步骤与实例详解
  15. 并联串联混合的电压和电流_如何正确地把锂电池串联和并联起来
  16. Python量化学习笔记04——量化投资——以Python为工具 Part01-C04
  17. 扩展jQuery读书笔记:第一章,jQuery扩展
  18. 关于echart 饼图显示不出来 挖坑总结
  19. CentOS7 安装cellranger-4.0.0
  20. Minecraft 1.12.2 彩色渐变字体0.2 多重渐变

热门文章

  1. 浏览器无法打开搜索引擎页面
  2. 从应用工程师的角度再谈车载 Android 系统
  3. wordpress入门主题_WordPress播客入门指南
  4. stagefright与opencore对比
  5. Vmware虚拟机红帽子Linux联网
  6. 4款简单实用的的服务器文件管理工具推荐
  7. Ubuntu20软件商店无法正确加载,解决办法
  8. 机器学习---黑箱原理
  9. 关于PMP考试的流程,很实用
  10. 最简单的基于FFMPEG的封装格式转换器(致敬雷霄骅)