【OpenCV 例程200篇】222. 特征提取之弗里曼链码(Freeman chain code)

OpenCV 例程200篇 总目录


【youcans 的 OpenCV 例程200篇】222. 特征提取之弗里曼链码(Freeman chain code)


目标特征的基本概念

通过图像分割获得多个区域,得到区域内的像素集合或区域边界像素集合。我们把感兴趣的人或物称为目标,目标所处的区域就是目标区域。
特征通常是针对于图像中的某个目标而言的。图像分割之后,还要对目标区域进行适当的表示和描述,以便下一步处理。
“表示”是直接具体地表示目标,以节省存储空间、方便特征计算。目标的表示方法,有链码、多边形逼近(MPP)、斜率标记图、边界分段、区域骨架。
“描述”是对目标的抽象表达,在区别不同目标的基础上,尽可能对目标的尺度、平移、旋转变化不敏感。


边界特征描述子

目标的边界描述符(Boundary descriptors),也称为边界描述子。
轮廓就是对目标边界的描述,轮廓属性是基本的边界描述子。

例如:

  • 边界的长度,轮廓线的像素数量是边界周长的近似估计;
  • 边界的直径,边界长轴的长度,等于轮廓最小矩形边界框的长边长度;
  • 边界的偏心率,边界长轴与短轴之比,等于轮廓最小矩形边界框的长宽比;
  • 边界的曲率,相邻边界线段的斜率差;
  • 链码,通过规定长度和方向的直线段来表示边界;
  • 傅里叶描述符,对二维边界点进行离散傅里叶变换得到的傅里叶系数,对旋转、平移、缩放和起点不敏感;
  • 统计矩,把边界视为直方图函数,用图像矩对边界特征进行描述,具有平移、灰度、尺度、旋转不变性。

例程 12.11:闭合曲线的弗里曼链码

链码表示基于线段的 4连通或 8连通。弗里曼链码(Freeman chain code)使用一种编号方案来对每个线段的方向进行编号。

通过对闭合边界曲线向下降采样,简化了初始轮廓。例程中最大轮廓的像素点 1361,简化后轮廓的像素点 34,对应的弗里曼链码长度 34。即用 34位 Freeman 链码可以描述该最大轮廓的边界特征,显著降低了数据量。

相关算法的详细内容,参见 R.C.Gonzalez 《数字图像处理(第四版)》P587-590 例11.1。

#  12.11 闭合曲线的弗里曼链码(Freeman chain code)
import cv2
import numpy as np
from matplotlib import pyplot as pltdef FreemanChainCode(cLoop, gridsep=1):  # 由闭合边界点集生成弗里曼链码# Freeman 8 方向链码的方向数dictFreeman = {(1, 0): 0, (1, 1): 1, (0, 1): 2, (-1, 1): 3, (-1, 0): 4, (-1, -1): 5, (0, -1): 6, (1, -1): 7}diff_cLoop = np.diff(cLoop, axis=0) // gridsep  # cLoop 的一阶差分码direction = [tuple(x) for x in diff_cLoop.tolist()]codeList = list(map(dictFreeman.get, direction))  # 查字典获得链码code = np.array(codeList)  # 转回 Numpy 数组return codeif __name__ == '__main__':# 计算目标轮廓曲线的弗里曼链码img = cv2.imread("../images/Fig1105.tif", flags=1)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 灰度图像blur = cv2.boxFilter(gray, -1, (5, 5))  # 盒式滤波器,9*9 平滑核_, binary = cv2.threshold(blur, 200, 255, cv2.THRESH_OTSU + cv2.THRESH_BINARY)# 寻找二值化图中的轮廓,method=cv2.CHAIN_APPROX_NONE 输出轮廓的每个像素点contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)  # OpenCV4~# 绘制全部轮廓,contourIdx=-1 绘制全部轮廓imgCnts = np.zeros(gray.shape[:2], np.uint8)  # 绘制轮廓函数会修改原始图像imgCnts = cv2.drawContours(imgCnts, contours, -1, (255, 255, 255), thickness=2)  # 绘制全部轮廓# 获取最大轮廓cnts = sorted(contours, key=cv2.contourArea, reverse=True)  # 所有轮廓按面积排序cnt = cnts[0]  # 第 0 个轮廓,面积最大的轮廓,(1361, 1, 2)maxContour = np.zeros(gray.shape[:2], np.uint8)  # 初始化最大轮廓图像cv2.drawContours(maxContour, cnt, -1, (255, 255, 255), thickness=2)  # 绘制轮廓 cntprint("len(contours) =", len(contours))  # contours 所有轮廓的列表print("area of max contour: ", cv2.contourArea(cnt))  # 轮廓面积print("perimeter of max contour: {:.1f}".format(cv2.arcLength(cnt, True)))  # 轮廓周长# 向下降采样,简化轮廓的边界gridsep = 50  # 采样间隔cntPoints = np.squeeze(cnt)  # 删除维度为1的数组维度,(1361,1,2)->(1361,2)subPoints = boundarySubsample(cntPoints, gridsep)  # 自定义函数,通过向下采样简化轮廓print("subsample steps:", gridsep)  # 降采样间距print("points of contour:", cntPoints.shape[0])  # 原始轮廓点数print("points of subsample:", subPoints.shape[0])  # 降采样轮廓点数# 绘制简化轮廓图像subContour = np.zeros(gray.shape[:2], np.uint8)  # 初始化简化轮廓图像[cv2.circle(subContour, point, 1, 160, -1) for point in cntPoints]  # 绘制初始轮廓的采样点[cv2.circle(subContour, point, 4, 255, -1) for point in subPoints]  # 绘制降采样轮廓的采样点cv2.polylines(subContour, [subPoints], True, 255, thickness=2)  # 绘制多边形,闭合曲线# 生成 Freeman 链码cntPoints = np.squeeze(cnt)  # 删除维度为1 的数组维度,(1361,1,2)->(1361,2)pointsLoop = np.append(cntPoints, [cntPoints[0]], axis=0)  # 首尾循环,结尾添加 cntPoints[0]chainCode = FreemanChainCode(pointsLoop, gridsep=1)  # 自定义函数,生成链码 (1361,)print("Freeman chain code:", chainCode.shape)  # 链码长度为轮廓长度subPointsLoop = np.append(subPoints, [subPoints[0]], axis=0)  # 首尾循环,(34,2)->(35,2)subChainCode = FreemanChainCode(subPointsLoop, gridsep=50)  # 自定义函数,生成链码 (34,)print("Down-sampling Freeman chain code:", subChainCode.shape)  # 链码长度为简化轮廓程度print("youcans code:", subChainCode)plt.figure(figsize=(9, 6))plt.subplot(231), plt.axis('off'), plt.title("Origin")plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))plt.subplot(232), plt.axis('off'), plt.title("Blurred")plt.imshow(cv2.cvtColor(blur, cv2.COLOR_BGR2RGB))plt.subplot(233), plt.axis('off'), plt.title("Binary")plt.imshow(binary, 'gray')plt.subplot(234), plt.axis('off'), plt.title("Contour")plt.imshow(imgCnts, 'gray')plt.subplot(235), plt.axis('off'), plt.title("Max contour")plt.imshow(maxContour, 'gray')plt.subplot(236), plt.axis('off'), plt.title("Down sampling")plt.imshow(subContour, 'gray')plt.tight_layout()plt.show()

运行结果:

len(contours) = 24
area of max contour: 152294.5
perimeter of max contour: 1525.4
subsample steps: 50
points of contour: 1361
points of subsample: 34
Freeman chain code: (1361,)
Down-sampling Freeman chain code: (34,)
[4 2 4 2 2 4 2 2 2 2 2 0 2 0 0 0 2 0 0 6 0 6 6 6 6 6 6 6 6 4 6 4 4 4]


在这里插入图片描述


【本节完】

说明:本文的案例来自 R.C.Gonzalez 《数字图像处理(第四版)》,本文的程序为作者原创。

版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/125534118)
Copyright 2022 youcans, XUPT
Crated:2022-6-30

欢迎关注 『youcans 的 OpenCV 例程 200 篇』 系列,持续更新中
194.寻找图像轮廓(cv.findContours)
222. 特征提取之弗里曼链码

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

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

相关文章

【OpenCV 例程200篇】224. 特征提取之提取骨架

OpenCV 例程200篇 总目录 【youcans 的 OpenCV 例程200篇】224. 特征提取之提取骨架 目标特征的基本概念 通过图像分割获得多个区域,得到区域内的像素集合或区域边界像素集合。我们把感兴趣的人或物称为目标,目标所处的区域就是目标区域。 特征通常是针…

inuri .php id=,php常用函数(遇见就补充)

preg_match()preg_match(string pattern, string subject [, array matches [, int flags]])在subject字符串中搜索与 pattern给出的正则表达式相匹配的内容。如果提供了 matches,则会被搜索的结果所填充。$matches[0]将包含于整个模式匹配的文本,$match…

【OpenCV 例程200篇】226. 区域特征之紧致度/圆度/偏心率

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】226. 区域特征之紧致度/圆度/偏心率 特征通常是针对于图像中的某个目标而言的。 我们把感兴趣的人或物称为目标,目标所处的区域就是目标区域。图像分割之后,还要对目标区域进…

Java常见的几种设计模式

单例模式 指一个应用程序中,某个类的实例对象只有一个,你没有办法去new,因为构造器是被private修饰的,一般通过getInstance()的方法来获取它们的实例。 getInstance()的返回值是一个对象的引用,并不是一个新的实例&a…

【OpenCV 例程200篇】227. 特征描述之 LBP 纹理特征算子

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】227. 特征描述之 LBP 纹理特征算子 特征通常是针对于图像中的某个目标而言的。 针对目标所在区域的特征描述符(Region descriptors),称为区域特征描述子。 4.2 纹…

【OpenCV 例程200篇】228. 特征描述之 extendLBP 改进算子

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】228. 特征描述之 extendLBP 改进算子 特征通常是针对于图像中的某个目标而言的。针对目标所在区域的特征描述符(Region descriptors),称为区域特征描述子。 局部…

【OpenCV 例程200篇】229. 特征描述之 LBP 算子比较(skimage)

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】229. 特征描述之 LBP 算子比较(skimage) 局部二值模式(LBP,Local binary patterns)是一种用来描述图像局部纹理特征的算子,它具…

Java多线程的使用

无论在我们的工作中还是在我们的生活中,我们都会用到多线程的知识,今天就给大家讲一下如何使用多线程。 序幕 线程的启动 如何使线程暂停 如何使线程停止 线程的优先级 线程安全相关的问题 我们首先要知道进程和线程分别是什么? 进程 - 进…

oracle 存储过程 db,oracle数据库的存储过程是什么?

oracle数据库的存储过程:一组为了完成特定功能的SQL语句集,经编译后存储在数据库中。存储过程是由流控制和SQL语句书写的过程,这个过程经编译和优化后存储在数据库服务器中,应用程序使用时只要调用即可。存储过程(Stored Procedur…

【OpenCV 例程200篇】230. 特征描述之 LBP 统计直方图

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】230. 特征描述之 LBP 统计直方图 局部二值模式(LBP,Local binary patterns)是一种用来描述图像局部纹理特征的算子,它具有旋转不变性和灰度不变性的优点…

【OpenCV 例程200篇】232. 特征描述之频谱方法

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】232. 纹理特征之频谱方法 4.3 纹理特征之频谱方法 傅里叶谱可以描述图像中的周期性或半周期性二维模式的方向性,因此可以基于傅里叶变换对纹理进行频谱分析。 纹理与图像频谱中的高频分…

java制作oracle程序,Java程序操作Oracle两种方式之简单实现

Java程序操作Oracle两种方式之简单实现1.通过JDBC-ODBC桥连接Oracle数据库(1)创建odbc源,在控制面板->管理工具->数据源(odbc)中添加DSN,比如取名为wangtao,选择一个Service,输入用户名密码,测试连接,若通过说明成功;(注意&…

【OpenCV 例程200篇】233. 区域特征之矩不变量

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】233. 区域特征之矩不变量 4.4 区域特征之矩不变量 矩是概率与统计中的一个概念,是随机变量的一种数字特征。矩函数在图像分析中有着广泛的应用,如模式识别、目标分类、图像编…

【OpenCV 例程200篇】231. 特征描述之灰度共生矩阵(GLCM)

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】231. 特征描述之灰度共生矩阵(GLCM) 4.2.4 灰度共生矩阵(GLCM) 灰度共生矩阵(Gray level co-occurrence matrix,GLCM&#xff…

oracle11 处理器数,11G AWR中%Total CPU与%Busy CPU指标的疑问

ODM FINDING:FROM http://www.os2ora.com/how-to-analyze-awr-report-1/ 推荐 kaya 的这篇文章引用如下:如果关注数据库的性能,那么当拿到一份AWR报告的时候,最想知道的第一件事情可能就是系统资源的利用情况了,而首当其冲的&am…

【OpenCV 例程200篇】237. 基于主成分提取的方向校正(OpenCV)

『youcans 的 OpenCV 例程200篇 - 总目录』 【youcans 的 OpenCV 例程200篇】237. 基于主成分提取的方向校正(OpenCV) 主成分分析(Principal Components Analysis,PCA)是一种基于统计的数据降维方法,又称主…

swoole 捕捉php错误,swoole怎么处理错误

在协程编程中可直接使用try/catch处理异常。但必须在协程内捕获,不得跨协程捕获异常。不仅是应用层throw的Exception,底层的一些错误也是可以被捕获的,如function、class、method不存在下面的代码中,try/catch和throw在不同的协程…

【OpenCV 例程200篇】235. 特征提取之主成分分析(sklearn)

『youcans 的 OpenCV 例程300篇 - 总目录』 【youcans 的 OpenCV 例程 300篇】235. 特征提取之主成分分析(sklearn) 特征提取是指从原始特征中通过数学变换得到一组新的特征,以降低特征维数,消除相关性,减少无用信息…

Linux 进程资源分配,linux 进程管理和内存分配

1、进程相关概念进程:正在运行中的程序内核功用:进程管理、文件系统、网络功能、内存管理、驱动程序、安全功能等Process:运行中的程序的一个副本,是被载入内存的一个指令集合进程 ID(Process ID,PID)号码被用来标记各…

【OpenCV 例程300篇】234. 特征提取之主成分分析(PCA)

『youcans 的 OpenCV 例程300篇 - 总目录』 【youcans 的 OpenCV 例程300篇】234. 特征提取之主成分分析(PCA) 5.1 特征提取的方法 初步获取的图像特征维数通常很大,而且往往包含一定的无关或冗余特征。特征提取是指从原始特征中通过数学变…