HLS实现图像膨胀和腐蚀运算--xf_dilation和xf_erosion

一、图像膨胀和图像腐蚀概念

        我们先定义,需要处理的图片为二值化图像A。图片的背景色为黑色,即像素值为0。图片的目标色为白色,即像素值为1。

        再定义一个结构元S,结构元范围内所有的像素为白色,像素值为1。

1、图像的膨胀

        通俗点说:就是将图像的目标像素往外扩张,使目标的尺寸变大,从而达到膨胀的效果。

        详细点说:一个结构元S从图像左上方开始遍历,结构元上任意一个元素与图像上目标元素重合时,此时将结构元锚点置的像素与对应图像位置的像素求“或运算”,更新像素值到此图像位置(即将结构元锚点位置对应的图像像素更新数值为1,即白色)。以此类推,遍历完图像后,得到的新的图像,即为膨胀后的图像。

        比如上图中,假设使用左侧的3x3结构元,遍历图像时,锚点遍历到原始图像绿色位置。此时可以看到,粉色区域存在数值为1的像素,按照膨胀运算,此时将结构元锚点与原始图像锚点像素进行“或运算”,最终处理后的膨胀像素为1。即原始图像的绿色位置的像素由0变成了1。

2、图像的腐蚀

        通俗点说:就是将图像的目标像素往内收缩,使目标的尺寸变小,从而实现腐蚀的效果。

        详细点说:一个结构元S从图像的左上方开始遍历,若结构元所在的图像区域内,像素值全部为1,那么保持结构元锚点位置的像素值为1,即白色;否则,锚点位置的像素值为0,即黑色。遍历完图像后,得到的新图像,即为腐蚀后的图像。 ​​​​​

        比如上图中,假设使用左侧的3x3结构元,遍历图像时,锚点遍历到原始图像绿色位置。此时可以看到,粉色区域存在数值为0的像素,按照腐蚀运算,锚点处最终处理后的膨胀像素为0。即原始图像的绿色位置的像素由1变成了0。

二、HLS实现

        可能不同资料中讲述腐蚀核膨胀的概念会略有区别,但是核心内容是不变的。本文中重点分析vitis HLS的库函数xf_dilation.hpp和xf_erosion.hpp。

1、xf_dilation.hpp

        在AMD赛灵思提供的解释中,图像膨胀处理,即当前像素被NxN邻域中强度最大值代替。公式表示如下:

         其库函数的调用模板和解释见下面代码:

template <int BORDER_TYPE,     //边界处理方式,目前仅支持XF_BORDER_CONSTANTint TYPE,            //图像类型,目前支持8UC1和8UC3int ROWS,            //图像最大行数int COLS,            //图像最大列数int K_SHAPE,         //结构元的形状,支持矩形、十字形和圆形int K_ROWS,          //结构元行数int K_COLS,          //结构元列数int ITERATIONS,      //迭代次数,仅在结构元为矩形时支持多次迭代int NPC = 1,         //单个时钟处理的像素数int XFCVDEPTH_IN_1 = _XFCVDEPTH_DEFAULT,   //输入图像深度int XFCVDEPTH_OUT_1 = _XFCVDEPTH_DEFAULT>  //输出图像深度
void dilate(xf::cv::Mat<TYPE, ROWS, COLS, NPC, XFCVDEPTH_IN_1>& _src,  //输入图像xf::cv::Mat<TYPE, ROWS, COLS, NPC, XFCVDEPTH_OUT_1>& _dst, //输出图像unsigned char _kernel[K_ROWS * K_COLS])   //输入的结构元数值,处理二值化图像时一般默认都为1

        如何使用该函数,可以自行参考赛灵思提供的示例demo,不再赘述。下面主要解析HLS是怎么实现膨胀运算处理的。

         打开xf_dilation.hpp文件,我们可以看到其c++代码。主要的调用函数有4个如下:

          dilate函数:判断输入图像大小与边界处理方式是否满足函数要求。根据结构元调整参数处理图像膨胀。此函数不进行具体的膨胀处理。

        xfdilate函数:根据结构元大小,考虑到边界情况,创建buf(buf包含图像边界以外行的像素值,初值赋为0)。以便处理第一行图像像素的膨胀。该函数主要考虑行边界预处理,缓存图像数据的数组定义为buf。

        Process_function_d函数:根据结构元大小。考虑到边界情况,给src_buf赋予初值(初值为0),以便处理第1列图像像素的膨胀,。该函数主要考虑列边界的预处理,缓存图像数据的数组定义为src_buf,最后得到与结构元大小一致的src_buf_temp_med_apply,然后提取送入到膨胀处理模块进行处理。

        dilate_function_apply函数:该函数判断窗口区域的图像数据中的最大值,赋值给锚点。该函数为图像膨胀的核心处理函数。

        下面举例说明膨胀函数的处理方式:以8*8的二值化8bits深度的图像,结构元大小为3*3的矩形,NPPC=1。(选取这些参数主要是为了减少篇幅且容易理解)

第一步:在dilate函数判断图像,结构元类型、迭代次数等信息是否满足要求。

第二步:xfdilate函数中创建buf数组,数组的大小为buf[3][8]。并且给buf赋予初值。buf[0]的8个像素值均赋为0;buf[1]的8个像素赋值为原始图像的第一行图像数据。如下图。

第三步:执行Process_function_d函数。首先读取图像2行的原始数据,保存至buf[2]中。此时buf数据更新为下图。

        此时我们要用到一个新的数组src_buf,其大小为src_buf[3][3]。其初值皆为0。buf数组经过buf_cop数组和src_buf_temp_copy_extract的一系列转换,最终会得到如下的src_buf数组,如下图:

        此时位于src_buf中的的锚点位置在原始图像之外,所以函数中存在一个start_write标志,用于控制何时将锚点结果写入到_dst中。很明显,锚点在图像边界之外的结果不写入到_dst矩阵中。

第四步:在dilate_function_apply函数中,比较src_buf中的像素结果,将src_buf的最大值赋值输出,最后判断是否在图像边界外,若在图像区域内,则写入到_dst矩阵中。

        综上,循环执行第三步和第四步,根据图像行列数据的读取,更新buf和src_buf中的数据,遍历完成完图像后,膨胀操作完成。

2、xf_erosion.hpp

        在AMD赛灵思提供的解释中,图像腐蚀处理,即当前像素被NxN邻域中强度最小值代替。公式表示如下:

         其库函数的调用模板和解释见下面代码:

template <int BORDER_TYPE,     //边界处理方式,目前仅支持XF_BORDER_CONSTANTint TYPE,            //图像类型,目前支持8UC1和8UC3int ROWS,            //图像最大行数int COLS,            //图像最大列数int K_SHAPE,         //结构元的形状,支持矩形、十字形和圆形int K_ROWS,          //结构元行数int K_COLS,          //结构元列数int ITERATIONS,      //迭代次数,仅在结构元为矩形时支持多次迭代int NPC = 1,         //单个时钟处理的像素数int XFCVDEPTH_IN_1 = _XFCVDEPTH_DEFAULT,   //输入图像深度int XFCVDEPTH_OUT_1 = _XFCVDEPTH_DEFAULT>  //输出图像深度
void erode(xf::cv::Mat<TYPE, ROWS, COLS, NPC, XFCVDEPTH_IN_1>& _src,  //输入图像xf::cv::Mat<TYPE, ROWS, COLS, NPC, XFCVDEPTH_OUT_1>& _dst, //输出图像unsigned char _kernel[K_ROWS * K_COLS])   //输入的结构元数值,处理二值化图像时一般默认都为1

       腐蚀函数与膨胀函数的处理方式几乎相同,仅在最后的function_apply中,由取最大值更改为取最小值。所以不再增加篇幅描述了。只要明白了膨胀函数的原理,腐蚀函数自然也不在话下。

这里需要提一下的是,如果你需要使用的结构元kernel的列数大于15,则该库函数工作可能不正常,这是由赛灵思库函数的运算算法决定的,感兴趣的可以再自己研究一下。

 

 

 

 

 

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

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

相关文章

RedHat9中安装Mysql8.0+出现“错误:GPG 检查失败“的处理

近期通过VM安装了RedHat9&#xff0c;之后在RedHat9中安装Mysql8.0的时候出现了个问题&#xff1a;“错误&#xff1a;GPG 检查失败”&#xff0c;如图所示&#xff1a; 解决方案&#xff1a;重新导入新的秘钥即可&#xff0c;如下所示&#xff1a; rpm --import https://rep…

连接Redis报错解决方案

连接Redis报错&解决方案 问题描述&#xff1a;Could not connect to Redis at 127.0.0.1:6379: 由于目标计算机积极拒绝&#xff0c;无法连接。 问题原因&#xff1a;redis启动方式不正确 解决方案&#xff1a; 在redis根目录下打开命令行窗口&#xff0c;输入命令redi…

Android studio生成二维码

1.遇到的问题 需要生成一个二维码&#xff0c;可以使用zxing第三方组件&#xff0c;增加依赖。 //生成二维码 implementation com.google.zxing:core:3.4.1 2.代码 展示页面 <ImageViewandroid:id"id/qrCodeImageView"android:layout_width"150dp"an…

公有云迁移研究——AWS Translate

大纲 1 什么是Translate2 Aws Translate是怎么运作的3 Aws Translate和Google Translate的区别4 迁移任务4.1 迁移原因 5 Aws Translate的Go demo6 迁移中遇到的问题6.1 账号和权限问题&#xff1a;6.2 小语种 1 什么是Translate Translate是一种文本翻译服务&#xff0c;它使…

HttpComponents: 领域对象的设计

1. HTTP协议 1.1 HTTP请求 HTTP请求由请求头、请求体两部分组成&#xff0c;请求头又分为请求行(request line)和普通的请求头组成。通过浏览器的开发者工具&#xff0c;我们能查看请求和响应的详情。 下面是一个HTTP请求发送的完整内容。 POST https://track.abc.com/v4/tr…

安卓MediaRecorder(2)录制源码分析

文章目录 前言JAVA new MediaRecorder() 源码分析android_media_MediaRecorder.cpp native_init()MediaRecorder.java postEventFromNativeandroid_media_MediaRecorder.cpp native_setup() MediaRecorder 参数设置MediaRecorder.prepare 分析MediaRecorder.start 分析MediaRec…

目标检测——OverFeat算法解读

论文&#xff1a;OverFeat: Integrated Recognition, Localization and Detection using Convolutional Networks 作者&#xff1a;Pierre Sermanet, David Eigen, Xiang Zhang, Michael Mathieu, Rob Fergus, Yann LeCun 链接&#xff1a;https://arxiv.org/abs/1312.6229 文章…

【Flink】Flink核心概念简述

目录 一、Flink 简介二、Flink 组件栈1. API & Libraries 层2. runtime层3. 物理部署层 三、Flink 集群架构四、Flink基本编程模型五、Flink 的部署模式六、Flink 任务的执行模式五、Flink 的优点 一、Flink 简介 Apache Flink 的前身是柏林理工大学一个研究性项目&#x…

IP地址定位技术为网络安全建设提供全新方案

随着互联网的普及和数字化进程的加速&#xff0c;网络安全问题日益引人关注。网络攻击、数据泄露、欺诈行为等安全威胁层出不穷&#xff0c;对个人隐私、企业机密和社会稳定构成严重威胁。在这样的背景下&#xff0c;IP地址定位技术应运而生&#xff0c;为网络安全建设提供了一…

合并一个文件夹下的多个txt文件,并对文本内容分列处理。

python 合并一个文件夹下的多个txt文件&#xff0c;并对文本内容分列。 原始文件&#xff1a; 最终结果&#xff1a; import pandas as pd import xlwt import pandas as pd from sqlalchemy import create_engine import pandas as pd import os import glob dirPath g…

LLM之Agent(四)| AgentGPT:一个在浏览器运行的Agent

AgentGPT是一个自主人工智能Agent平台&#xff0c;用户只需要为Agent指定一个名称和目标&#xff0c;就可以在浏览器中链接大型语言模型&#xff08;如GPT-4&#xff09;来创建和部署Agent平台。 PS&#xff1a;目前agentGPT仅支持chatgpt模型&#xff0c;暂时不支持本地llm模…

(华为)网络工程师教程笔记(网工教程)网工入门——3、静态路由路由表的配置

参考文章&#xff1a;【全236集】网络工程师从基础入门到进阶必学教程&#xff01;通俗易懂&#xff0c;2023最新版&#xff0c;学完即可就业&#xff01;网工入门_华为认证_HCIA_HCIP_数据通信_网工学习路线 文章目录 13. 网工入门10-静态路由&#xff08;路由表的配置&#x…

【Fastadmin】一个完整的轮播图功能示例

目录 1.效果展示&#xff1a; 列表 添加及编辑页面同 2.建表&#xff1a; 3.使用crud一键生成并创建控制器 4.html页面 add.html edit.html index.php 5.js页面 6.小知识点 1.效果展示&#xff1a; 列表 添加及编辑页面同 2.建表&#xff1a; 表名&#xff1a;fa_x…

kubesphere安装后启用DevOps

官方文档&#xff1a;KubeSphere DevOps 系统 1、集群管理---定制资源定义 进入目录&#xff1a;集群管理---定制资源定义搜索&#xff1a;clusterconfiguration 点击 ks-installer 右侧的 &#xff0c;选择编辑 YAML 在该 YAML 文件中&#xff0c;搜索 devops&#xff0c;…

SSM项目实战-前端-在Index.vue中展示第一页数据

1、util/request.js import axios from "axios";let request axios.create({baseURL: "http://localhost:8080",timeout: 50000 });export default request 2、api/schedule.js import request from "../util/request.js";export let getSchedu…

Python搭建代理IP池实现接口设置与整体调度

目录 前言 1. 搭建免费代理IP爬虫 2. 将获取到的代理IP存储到数据库中 3. 构建一个代理IP池 4. 实现调度器来调度代理IP池 5. 实现带有代理IP池的爬虫 总结 前言 在网络爬虫中&#xff0c;代理IP池是一个非常重要的组件。由于许多网站对单个IP的请求有限制&#xff0c;…

【数据结构和算法】--- 栈

目录 栈的概念及结构栈的实现初始化栈入栈出栈其他一些栈函数 小结栈相关的题目 栈的概念及结构 栈是一种特殊的线性表。相比于链表和顺序表&#xff0c;栈只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的…

iphone/安卓手机如何使用burp抓包

iphone 1. 电脑 ipconfig /all 获取电脑网卡ip&#xff1a; 192.168.31.10 2. 电脑burp上面打开设置&#xff0c;proxy&#xff0c;增加一条 192.168.31.10:8080 3. 4. 手机进入设置 -> Wi-Fi -> 找到HTTP代理选项&#xff0c;选择手动&#xff0c;192.168.31.10:8080 …

AI:95-基于卷积神经网络的艺术品风格分类

🚀 本文选自专栏:人工智能领域200例教程专栏 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的核心代码,详细讲解供大家学习,希望可以帮到大家。欢迎订阅支持,正在不断更新…

一套rk3588 rtsp服务器推流的 github 方案及记录 -01

我不生产代码&#xff0c;我只是代码的搬运工&#xff0c;相信我&#xff0c;看完这个文章你的图片一定能变成流媒体推出去。 诉求&#xff1a;使用opencv拉流&#xff0c;转成bgr数据&#xff0c;需要把处理后的数据&#xff08;BGR&#xff09;编码成264&#xff0c;然后推流…