OpenCV 笔记(6):像素间的基本关系——邻域、邻接、通路、连通、距离

像素是图像的基本元素,像素与像素之间存在着某些联系,理解像素间的基本关系是数字图像处理的基础。常见的像素间的基本关系包括:邻域、邻接、通路、连通、距离。

Part11. 邻域

邻域表示了像素之间的连接关系。

像素(x,y)的邻域,是指与像素(x,y)对应的点的集合{(x+p,y+q)} ,其中 (p,q) 为一对有意义的整数。邻域是像素(x,y)附近像素形成的区域,像素 (x,y) 也被称为中心像素。

最常用的邻域有以下几种:

  • 4 邻域:对于像素(x,y),上下左右4个像素被称为 4 邻域,使用

    表示。4 邻域的四个像素分别是:(x,y-1)、(x,y+1)、(x-1,y)、(x+1,y)。
  • D 邻域:对于像素(x, y), 其左上、右上、左下、右下的四个对角上的像素组成了 D 邻域,使用

    表示。D 邻域四个像素分别是:(x + 1, y + 1)、( x + 1, y - 1)、(x - 1, y + 1)、(x - 1, y - 1)。
  • 8 邻域:对于像素(x,y),它的4-邻域的点和 D-邻域的点组成了 8 邻域,使用

    表示。那么,
82f509f564c855db931e049c47752e37.jpeg
邻域.png

邻域是一个很基础的概念。后续我们对图像进行卷积操作的时候,通常是对当前像素的邻域像素进行操作的

以一个最简单的均值滤波为例,均值滤波是对于每一个像素点, 将其设定为取其邻域窗口内的所有像素的平均值。

算术均值滤波器的公式:

其中,

表示以像素(x,y)为中心的区域,m*n 是 模板的大小。f(x,y) 表示原图像,g(x,y) 表示使用 定义的邻域中的像素所计算出的算术平均值。

这里的模板,也可以被称为核(kernels)、窗口(windows)、掩模(mask)。

下图以 3*3 的模板为例,均值滤波会对原图像的每一个像素点,计算它的邻域像素和模版矩阵的对应元素的乘积,然后加起来,作为该像素位置的值。窗口的移动是从左到右,然后从上到下依次移动。

07694cee5400e58dc45f5fc015637e5f.jpeg
卷积.png

下面,实现一个简单的均值滤波函数

Mat meanFilter(Mat &src, int ksize = 3)
{
    cv::Mat dst = src.clone();

    int k0 = ksize/2;
    int sum[3] = {0,0,0};
    for(int i=k0;i<dst.rows-k0-1;i++)
    {
        for(int j=k0;j<dst.cols-k0-1;j++)
        {
            memset(sum,0, sizeof(sum));

            for(int channel = 0; channel<3; channel++)
            {
                for(int m = 0;m<ksize;m++)
                {
                    for (int n=0;n<ksize;n++)
                    {
                        sum[channel] += src.at<cv::Vec3b>(i-k0+m,j-k0+n)[channel];
                    }
                }

                dst.at<Vec3b>(i,j)[channel] = saturate_cast<uchar>((float)sum[channel] /(ksize*ksize));
            }
        }
    }
    return dst;
}

当然这个代码只是粗略地实现均值滤波,存在着很多优化的空间,例如使用积分图、卷积核分离等。OpenCV 也提供了均值滤波函数 blur() 函数。

int main(int argc,char *argv[])
{
    Mat src = imread(".../flower.jpg");
    imshow("src",src);
    Mat dst;

    dst = meanFilter(src, 15);
    imshow("meanFilter",dst);

    blur(src,dst,Size(15,15));
    imshow("blur",dst);

    waitKey(0);
    return 0;
}
42f72e3811f86c675a4ade5466eb32b0.jpeg
均值滤波函数效果.png

上面只是简单例举了领域的使用场景,后续会有专门的文章来详细介绍卷积和滤波。

Part22. 邻接

邻接是指两个像素,在位置上相邻并且取值相同或相近

我们用 V 表示定义邻接的灰度值集合。在二值图像中,V={1} 表示值为1的像素邻接。在灰度图像中,V 包含更多的元素。

  • 4 邻接:对于灰度值在 V 集合中的像素 p 和 q,如果 q 在

    中,那么像素 p 和 q 是 4 邻接的。
  • 8 邻接:对于灰度值在 V 集合中的像素 p 和 q,如果 q 在

    中,那么像素 p 和 q 是 8 邻接的。
  • m 邻接(混合邻接):m 邻接是 8 邻接的改进。只要满足以下任何一个条件即可:

    • q 在

    • q 在

      中,且集合在 中没有来自 V 中的像素。

像素 p 和 q 是 4 邻接,那么它们一定是 8 邻接的。反之,不一定成立。

下图反应了 8 邻接会带来二义性。

7df2076d86cbd0e64103c212e8c45224.jpeg
邻接.png

从图中可以看到,p 是中心像素。

  1. q1、q2 和 p 是 8 邻接的。

  2. q1 和 p 非 m 邻接的。

  3. q2 和 p 是 m 邻接的。

某条通路经过像素 q2、p、q1,那会有几种走法呢?

如果从 p、q1、q2 是 8 邻接的角度看,p 到 q1 可以有2种走法,所以 q2 到 q1 的通路有2条。

同理,从 m 邻接角度看,p 和 q1 只有1种走法,所以 q2 到 q1 的通路只有1条。

所以,m 邻接的引入是为了消除 8 邻接常常带来二义性

从集合的角度看:

邻接邻接邻接

Part33. 通路

通路:从像素 p

到像素 q 的通路是特定的像素序列,其坐标为:

,,,

并且满足,

和 对于 是邻接的。

闭合通路:如果满足

,则通路是闭合通路。

由不同的邻接定义,可以得到不同的通路:4 邻接 => 4 通路,8 邻接 => 8 通路,m 邻接 => m 通路

db5ecb59ff08ed211c691db615361fca.jpeg
通路.png

所以,从中间的图可以看到 q2 和 q1 之间存在 8 通路,从最右的图可以看到 q2 和 q1 之间存在 m 通路。

从集合的角度看:

通路通路通路

下图中,p-q 通路对应的是不同的通路。

ea91d48d9691c6efdd3ad02f4872ca63.jpeg
多种通路.png

Part44. 连通

连通:若 S 是图像中的一个像素子集,对于任意的

。如果存在一条由 S 中像素组成的从 p 到 q 的通路,则称 p 在图像集 S 中与 q 连通

邻接连通的一种特例,连通是由一系列依次邻接的像素组成的。

连通分为 4 连通8 连通

连通分量:对于 S 中任意像素 p,所有与 p 相连通且又在 S 中的像素集合。

连通集:如果 S 中仅有一个连通分量,则 S 称为连通集。

在之前基本图形的绘制那篇文章里, 曾介绍过绘图函数所使用的 lineType 参数。

下面对这个参数做一些补充说明:

  • LINE_4 :基于 4 连通 Bresenham 算法处理的直线。

  • LINE_8 :基于 8 连通 Bresenham 算法处理的直线。

  • LINE_AA :基于高斯滤波平滑处理的直线。

2d426d030aeb6f93624a097b9cac62ba.jpeg
lineType 参数.png

下面的例子,展示了使用不同的 lineType 参数的效果

int main(int argc,char *argv[])
{
    Mat image = Mat::zeros(Size(80, 80), CV_8UC3);
    image.setTo(255);// 设置屏幕为白色

    Point p1(20, 0);
    Point p2(80, 60);
    Point p3(0, 0);
    Point p4(80, 80);
    Point p5(0, 20);
    Point p6(60, 80);

    line(image, p1, p2, Scalar(0, 0, 255), 1, LINE_4);
    line(image, p3, p4, Scalar(255, 0, 0), 1, LINE_8);
    line(image, p5, p6, Scalar(0, 255, 0), 1, LINE_AA);

    imshow("src", image);

    waitKey(0);
    return 0;
}

将生成的图片放大,可以看到使用 LINE_4、LINE_8、LINE_AA 画出来的线段效果是不同的。使用 LINE_AA 效果看上去是最好的,其次是 LINE_8。

2b55e54b010f3ebfb97b72a77363bf4a.jpeg
不同lineType参数的效果.png

通过邻接可以引申很多概念,邻接 -> 通路 -> 连通 -> 连通集 -> 区域/邻接区域 -> 前景和背景 -> 边界

Part55. 距离

对于像素 p(x,y)、q(s,t) 和 z(u,v),如果满足:

  • 非负性:D(p,q) ≥ 0

  • 同一性:D(p,q)=0,当且仅当p=q时

  • 对称性:D(p,q) = D(q,p)

  • 直递性:D(p,z) ≤ D(p,q) + D(q,z)

则称 D 是距离的度量函数。

在欧几里得空间中,点

和点 之间的 闵可夫斯基距离
  • 曼哈顿距离

当 p = 1 时,即为曼哈顿距离或城市距离、街区距离,是指两个向量之间的距离,在计算距离时不涉及对角线移动。像素 p(x,y) 和 q(s,t) 之间的距离公式:

表示从像素 p 向像素 q 出发,每次能走的点必须是在当前像素点的 4 邻域中。一步一步走到 q 点后,一共经过的像素点数就是曼哈顿距离。

  • 欧式距离

当 p = 2 时,即为欧式距离,就是直角坐标系的距离。像素 p(x,y) 和 q(s,t) 之间的距离公式:

  • 切比雪夫距离

当 p =

时,即为切比雪夫距离或棋盘距离,像素 p(x,y) 和 q(s,t) 之间的距离公式:

表示从像素 p 向像素 q 出发,每次能走的点必须是在当前像素点的 8 邻域中。一步一步走到 q 点后,一共经过的像素点数就是切比雪夫距离。

Part66. 总结

本文涉及到很多概念,这些概念代表着像素间的基本关系。像邻域、连通在后续文章中很多都会涉及到,像距离又跟相似度有关,所以它们是数字图像的基础。

Java与Android技术栈】公众号

关注 Java/Kotlin 服务端、桌面端 、Android 、机器学习、端侧智能

更多精彩内容请关注:

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

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

相关文章

计算机二级Office真题解析 excel减免税,订单,成绩

第一题 1.将“Excel 减免税.xlsx”文件另存为 excel.xlsx&#xff0c;最后提交该文件&#xff08;1 分&#xff09;。 2.将“对应代码.xlsx”文件中的 sheet1 工作表插入到 excel.xlsx 中&#xff0c;工作 表名重命名为“代码”&#xff08;3 分&#xff09;。 3.在"序号&…

从关键新闻和最新技术看AI行业发展(2023.10.23-11.5第九期) |【WeThinkIn老实人报】

Rocky Ding 公众号&#xff1a;WeThinkIn 写在前面 【WeThinkIn老实人报】旨在整理&挖掘AI行业的关键新闻和最新技术&#xff0c;同时Rocky会对这些关键信息进行解读&#xff0c;力求让读者们能从容跟随AI科技潮流。也欢迎大家提出宝贵的优化建议&#xff0c;一起交流学习&…

将随机数设成3407,让你的深度学习模型再涨一个点!文再附3种随机数设定方法

随机数重要性 深度学习已经在计算机视觉领域取得了巨大的成功&#xff0c;但我们是否曾想过为什么同样的模型在不同的训练过程中会有不同的表现&#xff1f;为什么使用同样的代码&#xff0c;就是和别人得到的结果不一样&#xff1f;怎么样才能保证自己每次跑同一个实验得到的…

Django中Cookie和Session的使用

目录 一、Cookie的使用 1、什么是Cookie&#xff1f; 2、Cookie的优点 3、Cookie的缺点 4、Django中Cookie的使用 二、Session的使用 1、什么是Session&#xff1f; 2、Session的优点 3、Session的缺点 4、Django中Session的使用 三、Cookie和Session的对比 总结 D…

Vue 小黑记事本组件板

渲染功能&#xff1a; 1.提供数据&#xff1a; 提供在公共的父组件 App.vue 2.通过父传子&#xff0c;将数据传递给TodoMain 3.利用 v-for渲染 添加功能&#xff1a; 1.收集表单数据 v-model 2.监听事件&#xff08;回车点击都要添加&#xff09; 3.子传父&#xff0c;讲…

【嵌入式设计】Main Memory:SPM 便签存储器 | 缓存锁定 | 读取 DRAM 内存 | DREM 猝发(Brust)

目录 0x00 便签存储器&#xff08;Scratchpad memory&#xff09; 0x01 缓存锁定&#xff08;Cache lockdown&#xff09; 0x02 读取 DRAM 内存 0x03 DREM Banking 0x04 DRAM 猝发&#xff08;DRAM Burst&#xff09; 0x00 便签存储器&#xff08;Scratchpad memory&#…

Flutter有状态组件StatefulWidget生命周期

StatefulWidget是Flutter中的一个有状态的组件&#xff0c;它的生命周期相对复杂一些。下面是StatefulWidget的生命周期方法及其调用顺序&#xff1a; 1. createState(): 当StatefulWidget被插入到Widget树中时&#xff0c;会调用createState()方法来创建与之关联的State对象。…

软路由R4S+iStoreOS实现公网远程桌面局域网内电脑

软路由R4SiStoreOS实现公网远程桌面局域网内电脑 文章目录 软路由R4SiStoreOS实现公网远程桌面局域网内电脑简介 一、配置远程桌面公网地址配置隧道 二、家中使用永久固定地址 访问公司电脑具体操作方法是&#xff1a;2.1 登录页面2.2 再次配置隧道2.3 查看访问效果 简介 上篇…

力扣511. 游戏玩法分析 I

答案&#xff1a; select player_id,min(event_date) as first_login from Activity a group by player_id我最开始写的错误答案是这样的&#xff1a; select player_id,event_date as first_login from Activity a group by player_id having event_date min(event_date…

Docker - DockerFile

Docker - DockerFile DockerFile 描述 dockerfile 是用来构建docker镜像的文件&#xff01;命令参数脚本&#xff01; 构建步骤&#xff1a; 编写一个dockerfile 文件docker build 构建成为一个镜像docker run 运行脚本docker push 发布镜像&#xff08;dockerhub&#xff0…

无监督学习的集成方法:相似性矩阵的聚类

在机器学习中&#xff0c;术语Ensemble指的是并行组合多个模型&#xff0c;这个想法是利用群体的智慧&#xff0c;在给出的最终答案上形成更好的共识。 这种类型的方法已经在监督学习领域得到了广泛的研究和应用&#xff0c;特别是在分类问题上&#xff0c;像RandomForest这样…

【KVM-5】KVM架构

前言 大家好&#xff0c;我是秋意零。今天分析的内容是KVM架构。 &#x1f47f; 简介 &#x1f3e0; 个人主页&#xff1a; 秋意零&#x1f525; 账号&#xff1a;全平台同名&#xff0c; 秋意零 账号创作者、 云社区 创建者&#x1f9d1; 个人介绍&#xff1a;在校期间参与…

正点原子嵌入式linux驱动开发——Linux IIO驱动

工业场合里面也有大量的模拟量和数字量之间的转换&#xff0c;也就是常说的ADC和DAC。而且随着手机、物联网、工业物联网和可穿戴设备的爆发&#xff0c;传感器的需求只持续增强。比如手机或者手环里面的加速度计、光传感器、陀螺仪、气压计、磁力计等&#xff0c;这些传感器本…

计算机视觉(CV)技术的优势和挑战

计算机视觉技术在很多领域具有很大的优势,例如: 自动化:计算机视觉技术可以帮助实现自动化生产和检测,省去了人力成本和时间成本。 准确性:计算机视觉技术可以提高生产和检测的准确性,降低了人工操作产生的误差。 速度:计算机视觉技术可以实现高速速度的生产和检测,提高…

flv.js在vue中的使用

Flv.js 是 HTML5 Flash 视频&#xff08;FLV&#xff09;播放器&#xff0c;纯原生 JavaScript 开发&#xff0c;没有用到 Flash。由 bilibili 网站开源。它的工作原理是将 FLV 文件流转码复用成 ISO BMFF&#xff08;MP4 碎片&#xff09;片段&#xff0c;然后通过 Media Sour…

【vue实战项目】通用管理系统:封装token操作和网络请求

目录 1.概述 2.封装对token的操作 3.封装axios 1.概述 前文我们已经完成了登录页&#xff1a; 【vue实战项目】通用管理系统&#xff1a;登录页-CSDN博客 接下来我们要封装一下对token的操作和网络请求操作。之所以要封装这部分内容是因为token我们登陆后的所有请求都要携…

Python爬虫从基础到入门:认识爬虫

Python爬虫从基础到入门:认识爬虫 1. 认识爬虫2. 开始简单的爬虫操作(使用requests)3. 辨别“数据”是静态加载还是动态生成的1. 认识爬虫 爬虫用自己的话说其实就是利用一定的编程语言,到网络上去抓取一些数据为自己所用。那为什么要用爬虫呢?自己直接到网页上去copy数据它…

线性代数本质系列(二)矩阵乘法与复合线性变换,行列式,三维空间线性变换

本系列文章将从下面不同角度解析线性代数的本质&#xff0c;本文是本系列第二篇 向量究竟是什么&#xff1f; 向量的线性组合&#xff0c;基与线性相关 矩阵与线性相关 矩阵乘法与复合线性变换 三维空间中的线性变换 行列式 逆矩阵&#xff0c;列空间&#xff0c;秩与零空间 克…

Arthas(阿尔萨斯)--(二)

目录 一、Arthas学习 1、JVM相关命令一 1、dashboard 2、thread 3、jvm 4、sysprop 一、Arthas学习 Arthas(阿尔萨斯)--(一) Arthas代码开源地址 1、JVM相关命令一 1、dashboard dashboard:显示当前系统的实时数据面板&#xff0c;按q或ctrlc退出 ID: Java 级别的线…

vue3 ref 与shallowRef reactive与shallowReactive

ref 给数据添加响应式&#xff0c;基本类型采用object.defineProperty进行数据劫持&#xff0c;对象类型是借助reactive 实现响应式&#xff0c;采用proxy 实现数据劫持&#xff0c;利用reflect进行源数据的操作 let country ref({count:20,names:[河南,山东,陕西],objs:{key…