深度图像边缘提取及转储

原创 云深之无迹 2023-02-24 15:51

不会吧?不会吧?不会吧?不会有人忘记我还会写图像处理的代码吧?别说了,我知道你忘了,没关系,我会在这篇文章写一些很简短的代码实现常见的图像处理工作(别问为啥写不长,能力有限,20行开外就不受控制了)。

如何提取深度图像的边缘信息?
Sobel算子:Sobel算子是一种基于图像梯度的边缘检测算法,可以在x方向和y方向上计算图像的梯度,然后将两个梯度值合并成一个边缘强度值。通常可以使用Sobel算子来检测深度图像中的水平和垂直边缘。
Scharr算子是一种改进的Sobel算子,它使用了更大的卷积核来平滑图像,并在计算梯度时使用更准确的权重。Scharr算子在处理低对比度图像时表现更好。
Laplacian算子:Laplacian算子是一种基于二阶微分的边缘检测算法,可以检测出深度图像中的较强的边缘。该算子计算图像的拉普拉斯变换,并寻找其中的极值点作为边缘点。
深度边缘检测算法:除了基于梯度或微分的算法,还有一些专门针对深度图像的边缘检测算法。这些算法通常利用深度图像的信息来检测物体表面的变化,例如深度跳变或斜率变化等。
Canny算子是一种广泛使用的边缘检测算法,它采用了多步骤的边缘检测过程。首先,使用高斯滤波器平滑图像,然后计算图像的梯度和梯度方向。接下来,应用非极大值抑制和双阈值处理来提取边缘。最后,通过连接具有强度边缘的像素来获得完整的边缘。Canny算子在抑制噪声和保留真实边缘方面表现良好,通常被认为是一种比Sobel算子更优秀的边缘检测算法。
如何使用Python实现一个抽帧算法?
为啥会有这种东西?原因就是因为图像帧太多又不需要都处理~
import cv2
def extract_frames(video_path, interval): # 打开视频文件 cap = cv2.VideoCapture(video_path) # 计算视频总帧数和帧率 frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) fps = cap.get(cv2.CAP_PROP_FPS) # 计算抽帧间隔 interval_frames = int(interval * fps) # 初始化帧计数器和关键帧列表 count = 0 frames = [] # 逐帧遍历视频 while True: ret, frame = cap.read() if not ret: break count += 1 # 如果是关键帧,将其添加到关键帧列表中 if count % interval_frames == 0: frames.append(frame) # 关闭视频文件 cap.release()    return frames
照指定的时间间隔从视频中抽取关键帧
上述代码中,extract_frames()函数接受视频文件路径和抽帧间隔作为输入参数,返回一个包含关键帧的列表。在函数内部,首先使用cv2.VideoCapture()函数打开视频文件,并使用cv2.CAP_PROP_FRAME_COUNT和cv2.CAP_PROP_FPS获取视频总帧数和帧率。然后,根据指定的抽帧间隔计算需要保留的关键帧,在逐帧遍历视频时根据帧计数器来判断当前帧是否为关键帧,如果是,则将其添加到关键帧列表中。最后,使用cap.release()函数关闭视频文件。
可以使用以下代码调用extract_frames()函数来从视频文件中抽取关键帧:
frames = extract_frames('video.mp4', 1)  # 抽取间隔为1秒的关键帧for frame in frames:    cv2.imshow('frame', frame)    cv2.waitKey(0)cv2.destroyAllWindows()
上述代码将抽取间隔设置为1秒,然后遍历返回的关键帧列表,使用cv2.imshow()函数显示每个关键帧,并在用户按下键盘后继续显示下一个关键帧。最后,使用cv2.destroyAllWindows()函数关闭所有显示窗口。
让我们使用一个算子来提取深度图像的边缘信息的函数:
Sobel算子是一种常用的边缘检测算子,它利用图像的灰度值变化来检测边缘。
import cv2import numpy as np
def extract_depth_edges(depth_img): # 计算Sobel算子的卷积核 sobelx = cv2.Sobel(depth_img, cv2.CV_64F, 1, 0, ksize=3) sobely = cv2.Sobel(depth_img, cv2.CV_64F, 0, 1, ksize=3) # 计算梯度幅值和方向 grad_mag = np.sqrt(sobelx ** 2 + sobely ** 2) grad_dir = np.arctan2(sobely, sobelx) # 将梯度幅值归一化到0-255之间 grad_mag_norm = cv2.normalize(grad_mag, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U) # 将梯度方向转换为角度 grad_dir_deg = (grad_dir * 180 / np.pi) % 180 # 应用非极大值抑制 grad_mag_nms = cv2.Canny(grad_mag_norm, 100, 200)    return grad_mag_nms
上述代码中,extract_depth_edges()函数接受深度图像作为输入参数,返回提取的边缘信息。在函数内部,首先使用cv2.Sobel()函数计算x和y方向上的Sobel算子的卷积核,然后计算梯度幅值和方向。接下来,将梯度幅值归一化到0-255之间,并将梯度方向转换为角度。最后,应用非极大值抑制(Canny边缘检测算法)来提取边缘信息,并返回结果。
可以使用以下代码调用extract_depth_edges()函数来提取深度图像的边缘信息:
depth_img = cv2.imread('depth_image.png', cv2.IMREAD_GRAYSCALE)edges = extract_depth_edges(depth_img)cv2.imshow('depth_edges', edges)cv2.waitKey(0)cv2.destroyAllWindows()
上述代码将读取深度图像并将其作为输入参数传递给extract_depth_edges()函数,然后显示提取的边缘信息。
有时候会有这样的需求,把提取的图像边缘保存在一个txt文件中:
假设我们已经提取了深度图像的边缘信息,存储在名为edge_img的NumPy数组中,边缘值的范围在0到255之间。
import numpy as np
# 假设我们已经提取了深度图像的边缘信息,存储在名为edge_img的NumPy数组中
# 将边缘值缩放到0到1之间edge_img = edge_img / 255.0
# 将边缘信息转换为字符串格式edge_str = np.array2string(edge_img, separator=',', formatter={'float_kind':lambda x: "%.5f" % x})
# 将字符串写入txt文件with open('edge_info.txt', 'w') as f:    f.write(edge_str)
在上面的代码中,我们将边缘值缩放到0到1之间,并将其转换为字符串格式。我们使用NumPy的array2string函数将数组转换为字符串,并使用逗号作为分隔符。我们还设置了formatter参数,将浮点数的小数位数限制为5位。最后,我们将字符串写入名为edge_info.txt的txt文件中。
请注意,在读取txt文件时,需要使用适当的代码将字符串转换回NumPy数组格式。
虽然一直写不了长代码,但是不妨碍我写在一起:
接下来把抽帧算法和保存边缘到txt的函数写在一起
import cv2import numpy as np
def extract_edge(frame, threshold): # 使用高斯模糊平滑图像 blurred = cv2.GaussianBlur(frame, (3, 3), 0) # 转换为灰度图像 gray = cv2.cvtColor(blurred, cv2.COLOR_BGR2GRAY) # 使用Canny算法提取边缘 edges = cv2.Canny(gray, threshold, threshold * 2) return edges
def save_edges_to_txt(edges, filename): # 将边缘值缩放到0到1之间 edges = edges / 255.0 # 将边缘信息转换为字符串格式 edge_str = np.array2string(edges, separator=',', formatter={'float_kind':lambda x: "%.5f" % x}) # 将字符串写入txt文件 with open(filename, 'w') as f: f.write(edge_str)
# 读取深度图像depth_img = cv2.imread('depth_img.png')# 指定抽帧间隔interval = 10# 提取深度图像边缘edges = extract_edge(depth_img, 50)# 抽帧,保留每隔interval个像素sampled_edges = edges[::interval, ::interval]# 将边缘信息保存到txt文件中save_edges_to_txt(sampled_edges, 'edge_info.txt')
在上面的代码中,我们定义了一个extract_edge函数来提取深度图像的边缘,该函数使用高斯模糊平滑图像并使用Canny算法提取边缘。我们还定义了一个save_edges_to_txt函数,将边缘信息保存到txt文件中。
在主函数中,我们首先读取深度图像,然后指定抽帧间隔。我们使用extract_edge函数提取深度图像边缘,并使用抽帧算法保留每隔interval个像素。最后,我们使用save_edges_to_txt函数将提取的边缘信息保存到txt文件中。
应该是可以直接运行的,如果运行不了你再改改?
上面鄙人已经教了你把图像转换成txt的文件,如何把保存在txt文件里面的边缘信息恢复成图像呢?
你会不?
1.从txt文件中读取边缘信息字符串,并将其转换为NumPy数组。可以使用numpy.loadtxt函数将文件中的数据加载到NumPy数组中。
2。根据边缘信息数组的大小创建一个全零的数组,然后将边缘信息数组的值复制到全零数组的对应位置上。可以使用numpy.zeros函数创建全零数组,并使用numpy.put函数将边缘信息数组的值复制到全零数组的对应位置上。
3.对全零数组进行插值操作,以生成与原始深度图像相同大小的边缘图像。可以使用cv2.resize函数对全零数组进行插值操作。
4.对插值后的边缘图像进行二值化处理,以生成二值图像。可以使用cv2.threshold函数对插值后的边缘图像进行二值化处理。
import cv2import numpy as np
def load_edges_from_txt(filename, shape): # 从txt文件中读取边缘信息 edge_str = np.loadtxt(filename, delimiter=',') # 创建全零数组 edges = np.zeros(shape) # 将边缘信息复制到全零数组的对应位置上 np.put(edges, np.arange(shape[0]*shape[1]), edge_str) # 对全零数组进行插值操作 edges = cv2.resize(edges, (shape[1], shape[0])) # 对插值后的边缘图像进行二值化处理 ret, edges = cv2.threshold(edges, 0, 255, cv2.THRESH_BINARY) return edges
# 读取深度图像depth_img = cv2.imread('depth_img.png')# 获取深度图像大小height, width = depth_img.shape[:2]# 从txt文件中加载边缘信息,并恢复成图像edges = load_edges_from_txt('edge_info.txt', (height//10, width//10))# 显示原始深度图像和恢复的边缘图像cv2.imshow('depth_img', depth_img)cv2.imshow('edges', edges)cv2.waitKey(0)cv2.destroyAllWindows()
在上面的代码中,我们定义了一个load_edges_from_txt函数,该函数从txt文件中加载边缘信息,并将其恢复成图像。该函数首先使用numpy.loadtxt函数从文件中加载数据,并将其转换为NumPy数组。然后,该函数根据指定的图像大小创建一个全零数组,并使用numpy.put函数将边缘信息数组的值复制到全零数组的对应位置上。接下来,该函数对全零数组进行插值操作,并使用cv2.threshold函数对插值后的边缘图像进行二值化处理,生成二值图像。
最后一个代码,把1000x1000的图像信息转换到10x10的图像里面,应该怎么做?
使用图像缩放操作。可以使用OpenCV中的cv2.resize函数对原始图像进行缩放操作。该函数的输入参数包括原始图像、目标图像大小和插值方法等。
import cv2
# 读取原始图像img = cv2.imread('original_image.png')# 缩放图像new_img = cv2.resize(img, (10, 10), interpolation=cv2.INTER_AREA)# 显示原始图像和缩放后的图像cv2.imshow('original', img)cv2.imshow('new', new_img)cv2.waitKey(0)cv2.destroyAllWindows()
在上面的代码中,我们使用cv2.imread函数读取原始图像,然后使用cv2.resize函数对原始图像进行缩放操作,将其缩放为10x10的图像。在cv2.resize函数中,我们将目标图像大小设置为(10, 10),并将插值方法设置为cv2.INTER_AREA。最后,我们使用cv2.imshow函数显示原始图像和缩放后的图像。
代码没有测试,写20行代码测鸡毛,应该是错不了的,祝你Copy的开心!

评论 (0)
  • 《精通机器学习:MATLAB 分步实施指南》
    《精通机器学习:MATLAB 分步实施指南》
  • 从0写自己的Linux x86操作系统
    分享一套操作系统课程——从0写自己的Linux x86操作系统,附源码+课件+开发工具+参考资料+磁盘映像下载。

    适用人群
    对操作系统内部工作机制感兴趣,想要设计操作系统的大学生、软件开发人员

    课程采用从0行代码编写的方式,教你如何写一个类似于Linux 0.11的x86操作系统,从而深入掌握操作系统的工作原理。

    课程大纲
    第一阶段:引导程序设计
        设计boot程序,接管计算机运行权
        设计loader程序,加载并解析操作系统内核
    第二阶段:多进程管理
        增加中断处理模块,可处理硬件中断和异常
        利用多任务机制,实现系统中多进程的运行
        实现信号量与锁,允许进程之间同步和互斥
    第三阶段:虚拟内存管理
        为系统增加页表,实现进程加载到虚拟地址
        利用分页机制,让进程之间相互隔离,运行互不影响
    第四阶段:tty与文件系统
        增加文件系统模块,可从磁盘上加载程序并执行
        支持标准输入输出文件,允许应用使用printf输出
    第五阶段:命令行shell实现
        实现命令行接口,解析命令行参数并执行
        创建自己的应用程序,并在shell中动态加载并执行
  • 中低压配电实用技术.pdf
    中低压配电实用技术.pdf
  • 基于ESP32-CAM的人工智能机器人设计资料
    基于ESP32-CAM的人工智能机器人设计资料
  • CS5290兼容CS5230防破音AB/D切换,5.2W单声道GF类音频功放IC
    CS5290兼容CS5230防破音AB/D切换,5.2W单声道GF类音频功放IC
  • 面向多功能嵌入式客户端系统的高端平台
    面向多功能嵌入式客户端系统的高端平台 白皮书
  • 基于python人工智能算法的五官识别设计资料
    基于python人工智能算法的五官识别设计资料
  • 中低压配电网装置性违章的表现与整治.pdf
    中低压配电网装置性违章的表现与整治.pdf

  • 14、谷景科普0510色环电感超声波震荡后出现不良的常见原因分析
    14、谷景科普0510色环电感超声波震荡后出现不良的常见原因分析
  • C++微服务架构及安全云盘项目实训课程
    分享课程——C++微服务架构及安全云盘项目实训,包含课程配套资料下载。


    本课程从实践中理解软件工程,学习需求分析、架构设计、详细设计文档的编写,学习编程规范,了解多人协作开发策略,理解并引用软件的版本管理,熟悉git工具和软件发布管理流程, bug管理提交问题。
  • By Toradex秦海1). 简介嵌入式 Linux  由于运行平台通常资源受限同时对稳定性要求高,因此需要比较精简,那么针对 SSH 服务器/客户端应用,通常也不使用庞大的 OpenSSH,而是采用十分精简的 Dropbear SSH工具。Dropbear 是一个基于 MIT License 的开源软件,其一些基本信息可以参考如下软件发布页面:https://matt.ucc.asn.au/dropbear/dropbear.html 本文所演示的平台来自于Toradex
    hai.qin_651820742 2023-05-31 15:16 103浏览
  • 网约车行业竞争越来越卷,自动驾驶成为网约车平台重要的发力点,滴滴、T3出行、曹操出行等网约车平台相继对外宣布自动驾驶的计划并提出了“小目标”。滴滴发布两款自动驾驶核心硬件——“北曜Beta”激光雷达和三域融合计算平台“Orca虎鲸”,并宣布首款自动驾驶量产车型计划于2025年接入滴滴共享出行网络。T3出行联手轻舟智航在苏州启动Robtaxi的公开运营,并计划到2026年末,L4自动驾驶车辆商业运营达1000辆。曹操出行与吉利汽车达成战略合作,计划围绕出行平台构建集车内空间开发、定制车、智能驾驶、
    刘旷 2023-05-30 10:51 225浏览
  • 阻抗匹配是指负载阻抗与激励源内部阻抗互相适配,得到最大功率输出的一种工作状态。阻抗匹配是微波电子学的一部分,也是射频电路中非常重要的一部分,主要用于传输线路中,以达到能够将所有高频微波信号传输到负载点的目的。回溯到原点,提高能源效率。阻抗,顾名思义就是对电路中电流起到阻碍作用的元器件。我们在射频电路中,又引入了特征阻抗和等效阻抗两个概念。特征阻抗是射频传输线的一个固有特性,其物理意义是在射频传输线上入射波电压与入射波电流的比值,或者反射波电压和反射波电流的比值。等效阻抗也是传输线理论的一个概念,
    cxtf004 2023-05-30 14:58 186浏览
  •  近日,财政部会计司发布了《关于公布电子凭证会计数据标准(试行版)的通知》,为做好电子凭证会计数据标准深化试点工作,研究制定了9类电子凭证的会计数据标准。在通知的《电子凭证会计数据标准——全面数字化的电子发票(试行版)》指南中,明确了数电票报销入账归档的具体处理方式。    指南明确: 接收方取得数电票报销入账归档的,应按照《财政部 国家档案局关于规范电子会计凭证报销入账归档的通知》(财会〔2020〕6号,以下称《通知》)和《会计档案管
    科技财经汇 2023-05-29 20:47 190浏览
  • 在电脑内存条、显卡上,有一排金黄色导电触片,就是大家俗称的“金手指”。在PCB设计制作行业中的“金手指”(Gold Finger,或称Edge Connector),是由connector连接器作为PCB板对外连接网络的出口。关于“金手指”你知道多少呢?小编已做足了功课,今天就带大家全面了解PCB中“金手指”的设计,以及一些可制造性细节的处理等知识。“金手指”的功能用途1、“金手指”互连点当辅助PCB(如显卡、内存条)连接到主板时,会通过几个母槽中的其中一个插槽,如PCI、ISA或AGP槽,在外
    攻城狮华哥 2023-05-31 11:46 108浏览
  • [2] 电容器与电容 (1)什么是电容器? 电容器是用于储存电荷的器件,其中包含一对或多对由绝缘体分隔的导体。容器通常由铝、钽或陶瓷等材料制成。各种材料的电容器在系统中使用时具有各自的优缺点,如表 1 所示。陶瓷电容器通常是理想的选择,因为其电容变化最小,而且成本较低。                 (2)  直流电压降额        
    HGno1 2023-05-29 23:42 182浏览
  • 一、二极管基础 1、   基础知识 2、   各项参数: (1)    结电容       结电容有两种,分别是势垒电容和扩散电容。        势垒电容:PN结两端电压变化,引起积累在中间区域的电荷数量的改变,从而呈现电容效应,这个电容就是势垒电容。 扩散电容:当有外加正向偏压时,在PN结两侧的少子扩散
    HGno1 2023-05-29 22:55 173浏览
  • 近日,经纬恒润AUTOSAR基础软件产品INTEWORK-EAS-CP成功适配智芯半导体的Z20K14x产品家族。同时,经纬恒润完成了对智芯半导体Z20K14X 产品MCAL软件适配和工程集成,为智芯半导体提供了全套AUTOSAR解决方案。  左图:经纬恒润AUTOSAR EAS CP软件工程配置页面  右图:智芯半导体Z20K14x产品板   通过本次合作,智芯半导体的芯片产品将以功能更加完善、性能更加量化、服务更加完整的状态面向车
    hirain 2023-05-30 11:12 240浏览
  • [1] 压降 (1)什么是压降? 压降电压 VDO 是指为实现正常稳压,输入电压 VIN 必须高出所需输出电压 VOUT(nom) 的最小压差。 (2)决定压降的因素是什么?                           
    HGno1 2023-05-29 23:34 174浏览
  • 射频(RF)电路板设计虽然在理论上还有很多不确定性,但RF电路板设计还是有许多可以遵循的法则。不过,在实际设计时,真正实用的技巧是当这些法则因各种限制而无法实施时,如何对它们进行折衷处理,本文将集中探讨与RF电路板分区设计有关的各种问题。1、微过孔的种类电路板上不同性质的电路必须分隔,但是又要在不产生电磁干扰的最佳情况下连接,这就需要用到微过孔(microvia)。通常微过孔直径为0.05mm~0.20mm,这些过孔一般分为三类,即盲孔(blind via)、埋孔(bury via)和通孔(th
    攻城狮华哥 2023-05-30 11:27 202浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦