深度图像边缘提取及转储
不会吧?不会吧?不会吧?不会有人忘记我还会写图像处理的代码吧?别说了,我知道你忘了,没关系,我会在这篇文章写一些很简短的代码实现常见的图像处理工作(别问为啥写不长,能力有限,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 cv2
import 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 cv2
import 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 cv2
import 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的开心!
相关文章
- OpenCV4 调用HED边缘检测算法
- 深度揭秘华为边缘计算系统设计的六大核心原则
- 基于边缘端的体态识别实例
- 边缘计算也许是网络的未来
- 同时采用边缘计算和云计算的4个好处
- 基于边缘智能网关的智能售货机应用
- 曹建农院士:未来边缘计算:趋于分布式智能
- 云原生边缘计算助力人机物融合泛在计算
- 全球边缘计算专利申请前10中国占9个,怎么做到的?
- 腾讯云边缘安全加速(EdgeOne)之规则引擎
- AI降维打击人类画家,文生图引入ControlNet,深度、边缘信息全能复用
- Copula估计边缘分布模拟收益率计算投资组合风险价值VaR与期望损失ES|附代码数据
- Linux之家:探索分支的未知边缘(linux的分支)
- 刘江川:工业边缘计算将互联网带向何处?
- 对话刘江川:工业边缘计算的“黑马”如何造?
- 雾计算和边缘计算对物联网的意义何在?
- 担心智能家居泄露隐私?别怕,边缘AI来帮你