当前位置: 首页 > news >正文

使用Python进行二维图像的三维重建

2D图像的三维重建是从一组2D图像中创建对象或场景的三维模型的过程。这个技术广泛应用于计算机视觉、机器人技术和虚拟现实等领域。

在本文中,我们将解释如何使用Python执行从2D图像到三维重建的过程。我们将使用TempleRing数据集作为示例,逐步演示这个过程。该数据集包含了在对象周围的一个环上采样的阿格里真托(Agrigento)“Dioskouroi神庙”复制品的47个视图。

三维重建的关键概念

在深入了解如何使用Python从2D图像执行三维重建的详细步骤之前,让我们首先回顾一些与这个主题相关的关键概念。

深度图

深度图是一幅图像,其中每个像素代表摄像机和场景中相应点之间的距离。深度图常用于计算机视觉和机器人技术中,用于表示场景的三维结构。

有许多不同的方法可以从2D图像计算深度图,包括立体对应、结构光和飞行时间等。在本文中,我们将使用立体对应来从示例数据集计算深度图。

Point Cloud

点云是表示对象或场景形状的三维空间中的一组点。点云常用于计算机视觉和机器人技术中,用于表示场景的三维结构。

一旦我们计算出代表场景深度的深度图,我们可以使用它来计算一个三维点云。这涉及使用有关摄像机内部和外部参数的信息,将深度图中的每个像素投影回三维空间。

网格

网格是一个由顶点、边和面连接而成的表面表示。网格常用于计算机图形学和虚拟现实中,用于表示对象或场景的形状。

一旦我们计算出代表对象或场景形状的三维点云,我们可以使用它来生成一个网格。这涉及使用诸如Marching Cubes或Poisson表面重建等算法,将表面拟合到点云上。

逐步实现

现在我们已经回顾了与2D图像的三维重建相关的一些关键概念,让我们看看如何使用Python执行这个过程。我们将使用TempleRing数据集作为示例,逐步演示这个过程。下面是一个执行Temple Ring数据集中图像的三维重建的示例代码:

安装库:

pip install numpy scipy

导入库:

#importing libraries 
import cv2
import numpy as np
import matplotlib.pyplot as plt
import os

加载TempleRing数据集的图像:

# Directory containing the dataset images
dataset_dir = '/content/drive/MyDrive/templeRing'
# Initialize the list to store images
images = []# Attempt to load the grayscale images and store them in the list
for i in range(1, 48):  # Assuming images are named templeR0001.png to templeR0047.pngimg_path = os.path.join(dataset_dir, f'templeR{i:04d}.png')img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)if img is not None:images.append(img)else:print(f"Warning: Unable to load 'templeR{i:04d}.png'")# Visualize the input images
num_rows = 5  # Specify the number of rows
num_cols = 10  # Specify the number of columns
fig, axs = plt.subplots(num_rows, num_cols, figsize=(15, 8))# Loop through the images and display them
for i, img in enumerate(images):row_index = i // num_cols  # Calculate the row index for the subplotcol_index = i % num_cols   # Calculate the column index for the subplotaxs[row_index, col_index].imshow(img, cmap='gray')axs[row_index, col_index].axis('off')# Fill any remaining empty subplots with a white background
for i in range(len(images), num_rows * num_cols):row_index = i // num_colscol_index = i % num_colsaxs[row_index, col_index].axis('off')plt.show()

03c47c3cc1e07dc9864795f4449246cf.jpeg

解释:这段代码加载灰度图像序列,将它们排列在网格布局中,并使用matplotlib显示它们。

为每个图像计算深度图:

# Directory containing the dataset images
dataset_dir = '/content/drive/MyDrive/templeRing'
# Initialize the list to store images
images = []# Attempt to load the grayscale images and store them in the list
for i in range(1, 48):  # Assuming images are named templeR0001.png to templeR0047.pngimg_path = os.path.join(dataset_dir, f'templeR{i:04d}.png')img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)if img is not None:images.append(img)else:print(f"Warning: Unable to load 'templeR{i:04d}.png'")# Initialize the list to store depth maps
depth_maps = []# Create a StereoBM object with your preferred parameters
stereo = cv2.StereoBM_create(numDisparities=16, blockSize=15)# Loop through the images to calculate depth maps
for img in images:# Compute the depth mapdisparity = stereo.compute(img, img)    # Normalize the disparity map for visualizationdisparity_normalized = cv2.normalize(disparity, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)    # Append the normalized disparity map to the list of depth mapsdepth_maps.append(disparity_normalized)# Visualize all the depth maps
num_rows = 5  # Specify the number of rows
num_cols = 10  # Specify the number of columns
fig, axs = plt.subplots(num_rows, num_cols, figsize=(15, 8))for i, depth_map in enumerate(depth_maps):row_index = i // num_cols  # Calculate the row index for the subplotcol_index = i % num_cols   # Calculate the column index for the subplotaxs[row_index, col_index].imshow(depth_map, cmap='jet')axs[row_index, col_index].axis('off')# Fill any remaining empty subplots with a white background
for i in range(len(depth_maps), num_rows * num_cols):row_index = i // num_colscol_index = i % num_colsaxs[row_index, col_index].axis('off')plt.show()

解释:这段代码负责使用Stereo Block Matching(StereoBM)算法从一系列立体图像中计算深度图。它遍历灰度立体图像列表,并为每一对相邻图像计算深度图。

可视化每个图像的深度图:

# Initialize an accumulator for the sum of depth maps
sum_depth_map = np.zeros_like(depth_maps[0], dtype=np.float64)
# Compute the sum of all depth maps
for depth_map in depth_maps:sum_depth_map += depth_map.astype(np.float64)
# Calculate the mean depth map by dividing the sum by the number of depth maps
mean_depth_map = (sum_depth_map / len(depth_maps)).astype(np.uint8)
# Display the mean depth map
plt.figure(figsize=(8, 6))
plt.imshow(mean_depth_map, cmap='jet')
plt.title('Mean Depth Map')
plt.axis('off')
plt.show()

输出:

2707fa661da54abeb2386179e16b6ecb.jpeg

解释:这段代码通过累加深度图来计算平均深度图。然后,通过将总和除以深度图的数量来计算平均值。最后,使用jet颜色图谱显示平均深度图以进行可视化。

从平均深度图计算三维点云

# Initialize an accumulator for the sum of depth maps
sum_depth_map = np.zeros_like(depth_maps[0], dtype=np.float64)
# Compute the sum of all depth maps
for depth_map in depth_maps:sum_depth_map += depth_map.astype(np.float64)# Calculate the mean depth map by dividing the sum by the number of depth maps
mean_depth_map = (sum_depth_map / len(depth_maps)).astype(np.uint8)# Display the mean depth map
plt.figure(figsize=(8, 6))
plt.imshow(mean_depth_map, cmap='jet')
plt.title('Mean Depth Map')
plt.axis('off')
plt.show()

1b32de06ed9913c45fa573d4f5631e8c.jpeg

解释:这段代码通过对深度图进行累加来计算平均深度图。然后,通过将总和除以深度图的数量来计算平均值。最后,使用Jet颜色映射来可视化显示平均深度图。

计算平均深度图的三维点云

#converting into point cloud 
points_3D = cv2.reprojectImageTo3D(mean_depth_map.astype(np.float32), np.eye(4))

解释:该代码将包含点云中点的三维坐标,并且您可以使用这些坐标进行三维重建。

点云生成网格

安装库

!pip install numpy scipy

导入库

#importing libraries 
from scipy.spatial import Delaunay
from skimage import measure
from skimage.measure import marching_cubes

生成网格

verts, faces, normals, values = measure.marching_cubes(points_3D)

解释:该代码将Marching Cubes算法应用于3D点云以生成网格。它返回定义结果3D网格的顶点、面、顶点法线和标量值。

可视化网格

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(verts[:, 0], verts[:, 1], verts[:, 2], triangles=faces)
plt.show()

输出:

f151ba53e9d647b918eed7586832aa31.png

解释:该代码使用matplotlib可视化网格。它创建一个3D图并使用ax.plot_trisurf方法将网格添加到其中。

这段代码从Temple Ring数据集加载图像,并使用块匹配(block matching)进行每个图像的深度图计算,然后通过平均所有深度图来计算平均深度图,并使用它来计算每个像素的三维点云。最后,它使用Marching Cubes算法从点云生成网格并进行可视化。

结果比较

# importing the libraries
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# Create a figure with two subplots
fig, axs = plt.subplots(1, 2, figsize=(10, 5))# Visualize the original image in the first subplot
axs[0].imshow(images[0], cmap='gray')
axs[0].axis('off')
axs[0].set_title('Original')# Visualize the reconstructed mesh in the second subplot
ax = fig.add_subplot(1, 2, 2, projection='3d')
ax.plot_trisurf(verts[:, 0], verts[:, 1], verts[:, 2], triangles=faces)
ax.set_title('Reconstructed')# Show the figure
plt.show()

ed0badbd09152e13a56cf81dd247bdf9.jpeg

解释:在此代码中,使用matplotlib创建了包含两个子图的图形。在第一个图中,显示了来自数据集的原始图像。在第二个图中,使用3D三角形表面图可视化了重建的3D网格。

方法2

以下是执行来自TempleRing数据集图像的3D重建的另一个示例代码:

引入模块:

import cv2
import numpy as np
import matplotlib.pyplot as plt
from google.colab.patches import cv2_imshow

加载两个Temple Ring数据集图像:

# Load the PNG images (replace with your actual file paths)
image1 = cv2.imread('/content/drive/MyDrive/templeRing/templeR0001.png')
image2 = cv2.imread('/content/drive/MyDrive/templeRing/templeR0002.png'

解释:该代码使用OpenCV的cv2.imread函数从TempleRing数据集加载两个图像。

转换为灰度图:

# Convert images to grayscale
gray1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)

该代码使用OpenCV将两个图像转换为灰度图像。它们以单通道表示,其中每个像素的值表示其强度,并且没有颜色通道。

查找SIFT关键点和描述符:

# Initialize the SIFT detector
sift = cv2.SIFT_create()
# Detect keypoints and compute descriptors for both images
kp1, des1 = sift.detectAndCompute(gray1, None)
kp2, des2 = sift.detectAndCompute(gray2, None)

该代码使用尺度不变特征变换(SIFT)算法在两个图像中查找关键点和描述符。它使用OpenCV的cv2.SIFT_create()函数创建一个SIFT对象,并调用其detectAndCompute方法来计算关键点和描述符。

使用FLANN匹配器匹配描述符:

# Create a FLANN-based Matcher object
flann = cv2.FlannBasedMatcher({'algorithm': 0, 'trees': 5}, {})
# Match the descriptors using KNN (k-nearest neighbors)
matches = flann.knnMatch(des1, des2, k=2)

解释:该代码使用Fast Library for Approximate Nearest Neighbors(FLANN)匹配器对描述符进行匹配。它使用OpenCV的cv2.FlannBasedMatcher函数创建FLANN匹配器对象,并调用其knnMatch方法来找到每个描述符的k个最近邻。

使用Lowe的比率测试筛选出好的匹配项

# Apply Lowe's ratio test to select good matches
good_matches = []
for m, n in matches:if m.distance < 0.7 * n.distance:good_matches.append(m)

解释:该代码使用Lowe的比率测试筛选出好的匹配项。它使用最近邻和次近邻之间距离比的阈值来确定匹配是否良好。

提取匹配的关键点

# Extract matched keypoints
src_pts = np.float32([kp1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)

解释:该代码从两组关键点中提取匹配的关键点,这些关键点将用于估算对齐两个图像的变换。这些关键点的坐标存储在'src_pts'和'dst_pts'中。

使用RANSAC找到单应矩阵

# Find the homography matrix using RANSAC
H, _ = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)

在这段代码中,它使用RANSAC算法基于匹配的关键点计算描述两个图像之间的变换的单应矩阵。单应矩阵后来可以用于拉伸或变换一个图像,使其与另一个图像对齐。

使用单应矩阵将第一个图像进行变换

# Perform perspective transformation to warp image1 onto image2
height, width = image2.shape[:2]
result = cv2.warpPerspective(image1, H, (width, height))
# Display the result
cv2_imshow(result)

28ca168db5a14696349025da381f0a8a.jpeg

解释:该代码使用单应矩阵和OpenCV的cv2.warpPerspective函数将第一个图像进行变换。它指定输出图像的大小足够大,可以容纳两个图像,然后呈现结果图像。

显示原始图像和重建图像

# Display the original images and the reconstructed image side by side
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(12, 4))
ax1.imshow(cv2.cvtColor(image1, cv2.COLOR_BGR2RGB))
ax1.set_title('Image 1')
ax1.axis('off')
ax2.imshow(cv2.cvtColor(image2, cv2.COLOR_BGR2RGB))
ax2.set_title('Image 2')
ax2.axis('off')
ax3.imshow(cv2.cvtColor(result, cv2.COLOR_BGR2RGB))
ax3.set_title('Reconstructed Image')
ax3.axis('off')
plt.show()

输出:

84885befac51176bdd57a076d982f6e6.jpeg

解释:这段代码展示了在一个具有三个子图的单一图形中可视化原始图像和重建图像的过程。它使用matplotlib库显示图像,并为每个子图设置标题和轴属性。

不同的可能方法

有许多不同的方法和算法可用于从2D图像执行3D重建。选择的方法取决于诸如输入图像的质量、摄像机校准信息的可用性以及重建的期望准确性和速度等因素。

一些常见的从2D图像执行3D重建的方法包括立体对应、运动结构和多视图立体。每种方法都有其优点和缺点,对于特定应用来说,最佳方法取决于具体的要求和约束。

结论

总的来说,本文概述了使用Python从2D图像进行3D重建的过程。我们讨论了深度图、点云和网格等关键概念,并使用TempleRing数据集演示了使用两种不同方法逐步进行的过程。我们希望本文能帮助您更好地理解从2D图像进行3D重建以及如何使用Python实现这一过程。有许多可用于执行3D重建的不同方法和算法,我们鼓励您进行实验和探索,以找到最适合您需求的方法。

·  END  ·

HAPPY LIFE

b6791b364b263441b51c0b6b8fb520c8.png

本文仅供学习交流使用,如有侵权请联系作者删除

相关文章:

使用Python进行二维图像的三维重建

2D图像的三维重建是从一组2D图像中创建对象或场景的三维模型的过程。这个技术广泛应用于计算机视觉、机器人技术和虚拟现实等领域。 在本文中&#xff0c;我们将解释如何使用Python执行从2D图像到三维重建的过程。我们将使用TempleRing数据集作为示例&#xff0c;逐步演示这个过…...

go-zero微服务的使用

一、入门案例 1、使用goland创建一个工程 2、新建一个user.proto syntax "proto3";package user; // 这个地方表示生成的go的包名叫user option go_package "./user";message UserInfoRequest {int64 userId 1; }message UserInfoResponse {int64 user…...

Java排序算法之基数排序

基数排序&#xff08;Radix Sort&#xff09;是一种线性时间复杂度的排序算法&#xff0c;其时间复杂度为O(d(nk))&#xff0c;其中d是数字的位数&#xff0c;k是进制数。基数排序是一种非比较排序算法&#xff0c;它按照数位的大小来进行排序。它可以处理正整数、负整数和小数…...

Ubuntu20.0中安装Gradle

下载Gradle到temp文件夹 wget https://services.gradle.org/distributions/gradle-8.3-bin.zip -P /tmp 然后解压文件到/opt/gradle目录 sudo unzip -d /opt/gradle /tmp/gradle-8.3.zip 配置Gradle环境变量 接下来我们会创建一个gradle.sh文件来保存Gradle的环境变量 sudo…...

【Java并发编程六】多线程越界问题

ArrayList()越界错误 import java.util.ArrayList; public class myTest implements Runnable {static ArrayList<Integer> a new ArrayList<>(10);public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(new myTest());T…...

聊聊httpclient的disableConnectionState

序 本文主要研究一下httpclient的disableConnectionState disableConnectionState org/apache/http/impl/client/HttpClientBuilder.java /*** Disables connection state tracking.*/public final HttpClientBuilder disableConnectionState() {connectionStateDisabled t…...

Tomcat web.xml文件中的mime-mapping

在Tomcat安装目录的conf/web.xml文件中&#xff0c;定义了大量的<mime-mapping>元素&#xff0c;例如&#xff1a; 其中<extension>指定了文件的扩展名&#xff0c;<mime-type>指定了mime类型&#xff0c;放在<mime-mapping>元素中&#xff0c;就是将…...

【Java 进阶篇】JQuery 事件绑定:`on` 与 `off` 的奇妙舞曲

在前端开发的舞台上&#xff0c;用户与页面的互动是一场精彩的表演。而 JQuery&#xff0c;作为 JavaScript 的一种封装库&#xff0c;为这场表演提供了更为便捷和优雅的事件绑定方式。其中&#xff0c;on 和 off 两位主角&#xff0c;正是这场奇妙舞曲中的核心演员。在这篇博客…...

模块化Common JS 和 ES Module

目录 历程 1.几个函数&#xff1a;全局变量的污染&#xff0c;模块间没有联系 2.对象&#xff1a;暴露成员&#xff0c;外部可修改 3.立即执行函数&#xff1a;闭包实现模块私有作用域 common JS module和Module 过程 模块依赖&#xff1a;深度优先遍历、父 -> 子 -…...

基于java web个人财务管理系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…...

soc估计:DESIGN AND DEVELOPMENT OF SoC ESTIMATION MODEL USING MACHINE LEARNING

这是一篇印度那边学生的毕业论文&#xff0c;唯一要记录的是里面提到了一个特征构造的思想&#xff0c;记录如下&#xff1a; 论文思想&#xff1a; 特征选用速度、电流、电压、温度、平均电压、平均电流、平均速度&#xff0c;模型用cnnlstmlrlr 平均特征计算方式&#xff1a;…...

2、LeetCode之两数相加

给你两个非空的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照逆序的方式存储的&#xff0c;并且每个节点只能存储一位数字。请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。你可以假设除了数字0之外&#xff0c;这两个数都不会以0开头。 输入&am…...

redis三种集群方式

redis有三种集群方式&#xff1a;主从复制&#xff0c;哨兵模式和集群。 1.主从复制 主从复制原理&#xff1a; 从服务器连接主服务器&#xff0c;发送SYNC命令&#xff1b; 主服务器接收到SYNC命名后&#xff0c;开始执行BGSAVE命令生成RDB文件并使用缓冲区记录此后执行的所…...

Java --- JVM之垃圾回收相关算法

目录 一、垃圾标记算法 1.1、垃圾标记阶段&#xff1a;对象存活判断 1.2、引用计数算法 1.3、可达性分析算法 1.4、GC Roots 二、对象的finalization机制 2.1、生存还是死亡&#xff1f; 三、查看GC Roots 3.1、使用MAT查看 四、使用JProfiler分析OOM 五、清除阶段算…...

CentOS 7.9 安装 nginx

系统版本 # cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core)搜索nginx相关的软件包 yum search nginx显示已安装的与 “nginx” 相关的软件包 yum list | grep nginx列出可用的 Nginx 软件包 yum list nginx --showduplicates安装 Nginx yum install -y ng…...

Newman

近期在复习Postman的基础知识&#xff0c;在小破站上跟着百里老师系统复习了一遍&#xff0c;也做了一些笔记&#xff0c;希望可以给大家一点点启发。 一&#xff09;如何安装Newman 1、下载并安装NodeJs 在官网下载NodeJs&#xff1a; Download | Node.js&#xff08;官网的…...

Transformer中WordPiece/BPE等不同编码方式详解以及优缺点

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…...

Ubuntu20.04安装Beyond Compare 4.4.7

参考链接&#xff1a; 1.Ubuntu20.04 Beyond Compare 4.3.7 安装 2.Ubuntu20.04安装Beyond Compare 4.3.7...

制作含有音频、视频的网页

参考代码如下 <!DOCTYPE html> <html> <head><title>视频音乐网页</title> </head> <body><!-- 视频 --><video width"320" height"240" controls><source src"movie.mp4" type"…...

QPair的介绍及用法

QPair是一个模板类&#xff0c;它存储一对值&#xff08;key&#xff0c;value&#xff09;&#xff0c;可以是不同的数据类型。QPair的用法有以下几个方面&#xff1a; QPair的构造函数有以下几种形式&#xff1a; QPair()&#xff1a;默认构造函数&#xff0c;创建一个空的QP…...

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...

第7篇:中间件全链路监控与 SQL 性能分析实践

7.1 章节导读 在构建数据库中间件的过程中&#xff0c;可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中&#xff0c;必须做到&#xff1a; &#x1f50d; 追踪每一条 SQL 的生命周期&#xff08;从入口到数据库执行&#xff09;&#…...

MySQL 索引底层结构揭秘:B-Tree 与 B+Tree 的区别与应用

文章目录 一、背景知识&#xff1a;什么是 B-Tree 和 BTree&#xff1f; B-Tree&#xff08;平衡多路查找树&#xff09; BTree&#xff08;B-Tree 的变种&#xff09; 二、结构对比&#xff1a;一张图看懂 三、为什么 MySQL InnoDB 选择 BTree&#xff1f; 1. 范围查询更快 2…...