【python计算机视觉编程——9.图像分割】

news2024/9/27 9:18:56

python计算机视觉编程——9.图像分割

  • 9.图像分割
    • 9.1 图割
      • 安装Graphviz
      • 下一步:正文
      • 9.1.1 从图像创建图
      • 9.1.2 用户交互式分割
    • 9.2 利用聚类进行分割
    • 9.3 变分法

9.图像分割

9.1 图割

可以选择不装Graphviz,因为原本觉得是要用,后面发现好像用不到。不安装可直接跳到下一步

安装Graphviz

  1. 首先需要先下载Graphviz软件(Download | Graphviz),那些包先不要下载,网上说先下载包再下载软件会报错。在安装过程中,需要注意下图中的一步,其余都是一直下一步就行
    在这里插入图片描述

  2. 检查一下环境变量的路径
    在这里插入图片描述

  3. 接着在自己创建的虚拟环境下安装包
    pip install pydotplus

    pip install graphviz

  4. 这里需要注意的是,还需要再安装一个包,否则单单安装上面的会报错
    pip install python-graphviz

  5. 测试代码

    from graphviz import Digraph
    dot = Digraph(comment='The Round Table')
    dot.node('A', 'King Arthur')
    dot.node('B', 'Sir Bedevere the Wise')
    dot.node('L', 'Sir Lancelot the Brave')
    
    dot.edges(['AB', 'AL'])
    dot.edge('B', 'L', constraint='false')
    print(dot.source)  
    
    dot.render('round-table.gv',format='jpg', view=True)  
    

    在这里插入图片描述

    在这里插入图片描述

下一步:正文

  • 图割:将一个有向图分割成两个互不相交的集合
  • 基本思想:相似且彼此相近的像素应该划分到同一区域

图割C(C是图中所有边的集合)的“代价”函数定义为所有割的边的权重求合相加:
E c u t = ∑ ( i , j ) ∈ C w i j E_{cut}=\sum_{(i,j)\in C}w_{ij} Ecut=(i,j)Cwij
w i j w_{ij} wij是图中节点i到节点j的边 ( i , j ) (i,j) (i,j)的权重,并且是对割C所有的边进行求和

我们需要用图来表示图像,并对图进行划分,以使得 E c u t E_{cut} Ecut最小。同时在用图表示图像时,需要额外增加两个节点(源点和汇点),并仅考虑那些将源点和汇点分开的割

寻找最小割等同于在源点和汇点间寻找最大流,这里需要用到python-graph工具包( 注:不是 p i p 下载 ! \color{red}{注:不是pip下载!} 注:不是pip下载!),工具包地址如下:GitHub - pmatiello/python-graph: New official repository: https://github.com/Shoobx/python-graph

下载完后,把文件夹放入导包的根目录

在这里插入图片描述

根据路径进行引包,如果引入没有报错,就说明没有问题

from python_graph.core.pygraph.classes.digraph import digraph
from python_graph.core.pygraph.algorithms.minmax import maximum_flow``

这里我是报错了:“jaraco.text"中没有drop_comment, join_continuation, yield_lines函数的问题,然后我在”_jaraco_text.py"文件里找到了这三个函数,索性就直接把他提到根目录上,发现就没报错了

在这里插入图片描述

在这里插入图片描述

另一个导包路径错误在"digraph.py"和"minmax.py"文件中

在这里插入图片描述

接着就可以运行代码了

gr = digraph()
gr.add_nodes([0,1,2,3])
gr.add_edge((0,1), wt=4)
gr.add_edge((1,2), wt=3)
gr.add_edge((2,3), wt=5)
gr.add_edge((0,2), wt=3)
gr.add_edge((1,3), wt=4)
flows,cuts = maximum_flow(gr,0,3)
print('flow is:', flows)
print('cut is:', cuts)

在这里插入图片描述

9.1.1 从图像创建图

我们需要利用图像像素作为节点定义一个图,除了像素节点外,还有两个特定的节点——“源”点和“汇”点,来分别代表图像的前景和背景,我们需要做的是将所有像素与源点、汇点链接起来。

  • 每个像素节点都有一个从源点的传入边
  • 每个像素节点都有一个到汇点的传出边
  • 每个像素节点都有一条传入边和传出边连接到它的近邻。

接着需要用朴素贝叶斯分类器进行分类,我们将第8章的BayesClassifier类搬过来

def build_bayes_graph(im,labels,sigma=1e2,kappa=1):
    """   从像素四邻域建立一个图,前景和背景
    (前景用1标记,背景用-1标记,其他的用0标记)
    由labels决定,并用朴素贝叶斯分类器建模"""
    
    m,n = im.shape[:2]
    
    # 每行是一个像素的RGB向量
    vim = im.reshape((-1,3))
    
    # 前景和背景(RGB)
    foreground = im[labels==1].reshape((-1,3))
    background = im[labels==-1].reshape((-1,3))    
    train_data = [foreground,background]
    
    # 训练朴素贝叶斯分类器
    bc = BayesClassifier()
    bc.train(train_data)

    # 获取所有像素的概率
    bc_lables,prob = bc.classify(vim)
    prob_fg = prob[0]
    prob_bg = prob[1]
    
    # 用m*n+2 个节点创建图
    gr = digraph()
    gr.add_nodes(range(m*n+2))
    
    
    source = m*n #  倒数第二个是源点
    sink = m*n+1 # 最后一个节点是汇点

    #  归一化
    for i in range(vim.shape[0]):
        vim[i] = vim[i] / (np.linalg.norm(vim[i]) + 1e-9)
    
    # go through all nodes and add edges
    for i in range(m*n):
        # 从源点添加边
        gr.add_edge((source,i),wt=prob_fg[i]/(prob_fg[i]+prob_bg[i]))
        
        # 向汇点添加边
        gr.add_edge((i,sink),wt=prob_bg[i]/(prob_fg[i]+prob_bg[i]))
        
        # 向相邻节点添加边
        if i%n != 0: # 左边存在
            edge_wt = kappa*np.exp(-1.0*sum((vim[i]-vim[i-1])**2)/sigma)
            gr.add_edge((i,i-1),wt=edge_wt)
        if (i+1)%n != 0: # 如果右边存在
            edge_wt = kappa*np.exp(-1.0*sum((vim[i]-vim[i+1])**2)/sigma)
            gr.add_edge((i,i+1),wt=edge_wt)
        if i//n != 0: # 如果上方存在
            edge_wt = kappa*np.exp(-1.0*sum((vim[i]-vim[i-n])**2)/sigma)
            gr.add_edge((i,i-n),wt=edge_wt)
        if i//n != m-1: # 如果下方存在
            edge_wt = kappa*np.exp(-1.0*sum((vim[i]-vim[i+n])**2)/sigma)
            gr.add_edge((i,i+n),wt=edge_wt)
    return gr    
def gauss(m,v,x):
    """ Evaluate Gaussian in d-dimensions with independent 
        mean m and variance v at the points in (the rows of) x. 
        http://en.wikipedia.org/wiki/Multivariate_normal_distribution """
    
    if len(x.shape)==1:
        n,d = 1,x.shape[0]
    else:
        n,d = x.shape
            
    # covariance matrix, subtract mean
    S = np.diag(1/v)
    x = x-m
    # product of probabilities
    y = np.exp(-0.5*np.diag(np.dot(x,np.dot(S,x.T))))
    
    # normalize and return
    return y * (2*np.pi)**(-d/2.0) / (np.sqrt(np.prod(v)) + 1e-6)

写入新函数

def build_bayes_graph(im,labels,sigma=1e2,kappa=1):
    """   从像素四邻域建立一个图,前景和背景
    (前景用1标记,背景用-1标记,其他的用0标记)
    由labels决定,并用朴素贝叶斯分类器建模"""
    
    m,n = im.shape[:2]
    
    # 每行是一个像素的RGB向量
    vim = im.reshape((-1,3))
    
    # 前景和背景(RGB)
    foreground = im[labels==1].reshape((-1,3))
    background = im[labels==-1].reshape((-1,3))    
    train_data = [foreground,background]
    
    # 训练朴素贝叶斯分类器
    bc = BayesClassifier()
    bc.train(train_data)

    # 获取所有像素的概率
    bc_lables,prob = bc.classify(vim)
    prob_fg = prob[0]
    prob_bg = prob[1]
    
    # 用m*n+2 个节点创建图
    gr = nx.DiGraph()
    
    nodes=[]
    for i in range(m*n+2):
        nodes.append(str(i))
    gr.add_nodes_from(nodes)
    
    
    source = m*n #  倒数第二个是源点
    sink = m*n+1 # 最后一个节点是汇点

    #  归一化
    for i in range(vim.shape[0]):
        vim[i] = vim[i] / (np.linalg.norm(vim[i]) + 1e-9)
    
    # go through all nodes and add edges
    for i in range(m*n):
        # 从源点添加边
        gr.add_edge(str(source),str(i),capacity=prob_fg[i]/(prob_fg[i]+prob_bg[i]))
        
        # 向汇点添加边
        gr.add_edge(str(i),str(sink),capacity=prob_bg[i]/(prob_fg[i]+prob_bg[i]))
        
        # 向相邻节点添加边
        if i%n != 0: # 左边存在
            edge_wt = kappa*np.exp(-1.0*sum((vim[i]-vim[i-1])**2)/sigma)
            gr.add_edge(str(i),str(i-1),capacity=edge_wt)
        if (i+1)%n != 0: # 如果右边存在
            edge_wt = kappa*np.exp(-1.0*sum((vim[i]-vim[i+1])**2)/sigma)
            gr.add_edge(str(i),str(i+1),capacity=edge_wt)
        if i//n != 0: # 如果上方存在
            edge_wt = kappa*np.exp(-1.0*sum((vim[i]-vim[i-n])**2)/sigma)
            gr.add_edge(str(i),str(i-n),capacity=edge_wt)
        if i//n != m-1: # 如果下方存在
            edge_wt = kappa*np.exp(-1.0*sum((vim[i]-vim[i+n])**2)/sigma)
            gr.add_edge(str(i),str(i+n),capacity=edge_wt)
    return gr    
def show_labeling(im,labels):
    """显示图像的前景和背景区域。前景labels=1,背景labels=-1,其他labels=0 """
    
    imshow(im)
    contour(labels,[-0.5,0.5])
    contourf(labels,[-1,-0.5],colors='b',alpha=0.25)
    contourf(labels,[0.5,1],colors='r',alpha=0.25)
    #axis('off')
    xticks([])
    yticks([])
def cut_graph(gr,imsize):
    """    Solve max flow of graph gr and return binary 
        labels of the resulting segmentation."""
#     print(gr)
    m,n=imsize
    source=m*n # second to last is source
    sink=m*n+1 # last is sink
    
    # cut the graph
    flows,cuts = maximum_flow(gr,source,sink)
#     print(cuts)
    # convert graph to image with labels
    res = np.zeros(m*n)
    for pos,label in list(cuts.items())[:-2]: # 遍历所有节点,忽略源节点和汇节点
        # 但因为cuts.items()返回的是元组,需先转成列表再进行切片
        res[pos] = label

    return res.reshape((m,n))

其中书本中from scipy.misc import imresize模块,已经不存在于imresize中,这里使用Pillow库中的resize函数进行替代 resize_image_pillow

def resize_image_pillow(image_path, output_path, scale_factor):
    # 打开图像文件
    with Image.open(image_path) as img:
        # 计算新的尺寸
        new_width = int(img.width * scale_factor)
        new_height = int(img.height * scale_factor)
        
        # 使用双线性插值调整图像大小
        img_resized = img.resize((new_width, new_height), resample=Image.BILINEAR)
        
        # 保存调整后的图像
#         return img_resized
        img_resized.save(output_path)
import numpy as np
from PIL import Image
from pylab import *

# resize_image_pillow('empire.jpg', 'empire.jpg', 0.07)
im=np.array(Image.open('empire.jpg'))
size=im.shape[:2]
labels=np.zeros(size)
labels[3:18,3:18]=-1
labels[-18:-3,-18:-3]=1

# 对图进行分割
g = build_bayes_graph(im,labels,kappa=1)
res=cut_graph(g,size)

figure()
show_labeling(im,labels)

figure()
imshow(res)
gray()
axis('off')

show()

在这里插入图片描述

9.1.2 用户交互式分割

def create_msr_labels(m, lasso=False):
    """ Create label matrix for training from
    user annotations. """
    labels = np.zeros(im.shape[:2])
    # background
    labels[m == 0] = -1
    labels[m == 64] = -1
    # foreground
    if lasso:
        labels[m == 255] = 1
    else:
        labels[m == 128] = 1
    return labels

# load image and annotation map
im = array(Image.open('empire.jpg'))
m = array(Image.open('empire.bmp'))
# resize
scale = 0.1
im = imresize(im, scale, interp='bilinear')
m = imresize(m, scale, interp='nearest')
# create training labels
labels = create_msr_labels(m, False)
# build graph using annotations
g = build_bayes_graph(im, labels, kappa=2)

# cut graph
res = cut_graph(g, im.shape[:2])
# remove parts in background
res[m == 0] = 1
res[m == 64] = 1

# plot the result
figure()
imshow(res)
gray()
xticks([])
yticks([])
savefig('labelplot.pdf')

9.2 利用聚类进行分割

def ncut_graph_matrix(im,sigma_d=1e2,sigma_g=1e-2):
    """  创建用于归一化割的矩阵,其中 sigma_d 和 sigma_g 是像素距离和像素相似性的权重参数 """
    
    m,n = im.shape[:2] 
    N = m*n
    
    # 归一化,并创建 RGB 或灰度特征向量
    if len(im.shape)==3:
        for i in range(3):
            im[:,:,i] = im[:,:,i] / im[:,:,i].max()
        vim = im.reshape((-1,3))
    else:
        im = im / im.max()
        vim = im.flatten()
    
    # x,y 坐标用于距离计算
    xx,yy = meshgrid(range(n),range(m))
    x,y = xx.flatten(),yy.flatten()
    
    # 创建边线权重矩阵
    W = zeros((N,N),'f')
    for i in range(N):
        for j in range(i,N):
            d = (x[i]-x[j])**2 + (y[i]-y[j])**2 
            W[i,j] = W[j,i] = exp(-1.0*sum((vim[i]-vim[j])**2)/sigma_g) * exp(-d/sigma_d)
    
    return W
from scipy.cluster.vq import *
def cluster(S,k,ndim):
    """ 从相似性矩阵进行谱聚类 """
    
    # 检查对称性
    if sum(abs(S-S.T)) > 1e-10:
        print('not symmetric')
    
    # 创建拉普拉斯矩阵
    rowsum = sum(abs(S),axis=0)
    D = diag(1 / sqrt(rowsum + 1e-6))
    L = dot(D,dot(S,D))
    
    # 计算 L 的特征向量
    U,sigma,V = linalg.svd(L,full_matrices=False)

    # 从前 ndim 个特征向量创建特征向量
    # 堆叠特征向量作为矩阵的列
    features = array(V[:ndim]).T

    # k-means
    features = whiten(features)
    centroids,distortion = kmeans(features,k)
    code,distance = vq(features,centroids)
        
    return code,V

在运行下面代码之前,需要安装scikit-image,记得在自己的虚拟环境下安装(我用pip安装不了,后面改用conda,只要在虚拟环境下,用哪个(pip或conda)都是安装在虚拟环境下)

conda install scikit-image

import cv2
import numpy as np
from pylab import  *
from PIL import Image
from skimage.transform import resize

im = Image.open('empire.jpg')
m,n = np.array(im).shape[:2]
# 调整图像的尺寸大小为(wid,wid)
wid = 50


rim = im.resize((50,50),Image.BILINEAR)
rim = array(rim,'f')
# 创建归一化割矩阵
# print(rim.shape[:2] )
A = ncut_graph_matrix(rim,sigma_d=1,sigma_g=1e-2)
# 聚类
code,V=cluster(A,k=3,ndim=3)
# 变换到原来的图像大小


image=code.reshape(wid,wid)
print(image)


codeim = resize(image,(m,n),mode='reflect',anti_aliasing=False,order=0)
# 绘制分割结果
figure()
imshow(codeim)
gray()
show()

在这里插入图片描述

9.3 变分法

当优化的对象是函数时,该问题称为变分问题,需要使用ROF进行降噪。

denoise函数需要传入以下参数

  • im: 输入的噪声图像(灰度图像)。
  • U_init: 对 U(去噪图像)的初始猜测。
  • tolerance: 收敛的容忍度,用于判断迭代是否结束。
  • tau: 步长(或称为步伐),用于控制更新的幅度。
  • tv_weight: 总变差正则化项的权重,控制去噪程度。

denoise函数返回参数

  • U: 去噪后的图像。
  • im - U: 图像的纹理残差,即原始图像中未被去噪部分的残余。
def denoise(im,U_init,tolerance=0.1,tau=0.125,tv_weight=100):
    """ 这个函数实现了 Rudin-Osher-Fatemi (ROF) 去噪模型,
    ROF 模型是一个常用的图像去噪方法,基于总变差(Total Variation, TV)
    正则化来去除噪声,同时保留图像的边缘信息"""
        
    m,n=im.shape  #获取图像的高度和宽度
    
    #初始化
    U=U_init
    Px=im      # 对偶域的x分量
    Py=im      # 对偶域的y分量
    error=1
    while(error>tolerance):
        Uold=U

        #原始变量的梯度
        GradUx=roll(U,-1,axis=1)-U       #变量U梯度的x分量
        GradUy=roll(U,-1,axis=0)-U       #变量U梯度的y分量

        #更新对偶变量
        PxNew=Px+(tau/tv_weight)*GradUx  #更新Px
        PyNew=Py+(tau/tv_weight)*GradUy  #更新Py
        NormNew=maximum(1,sqrt(PxNew**2+PyNew**2))#计算PxNew和PyNew的范数,确保其最小值为1

        
        Px=PxNew/NormNew    #更新x分量
        Py=PyNew/NormNew    #更新y分量
        
        RxPx=roll(Px,1,axis=1)#计算Px在x方向上的右移
        RyPy=roll(Py,1,axis=0)#计算Px在y方向上的下移
        
        DivP=(Px-RxPx)+(Py-RyPy)#计算Px和Py的梯度
        
        U=im+tv_weight*DivP # 更新去噪后的图像U
        
        error=linalg.norm(U-Uold)/sqrt(n*m)# 计算当前误差
    return U,im-U            #返回去噪后的图像U和噪声图像

因为 scipy.misc.imsave 已被弃用,所以需要用其他库来完成,这里使用Pillow库来保存图像

import numpy as np
from PIL import Image
im = np.array(Image.open('ceramic-houses_t0.png').convert('L'))
U,T=denoise(im,im,tolerance=0.001)
t=0.4


# 基于阈值生成二值图像
binary_image = U < t * U.max()

# 将布尔数组转换为 uint8 格式(0 或 255)
binary_image_uint8 = (binary_image * 255).astype(np.uint8)

# 创建 Image 对象
img = Image.fromarray(binary_image_uint8)

# 保存图像为 PDF
img.save('result.pdf')
from pylab import  *
gray()
subplot(121)
imshow(U)
subplot(122)
imshow(img)

在这里插入图片描述

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

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

相关文章

大模型教程:使用 Milvus、vLLM 和 Llama 3.1 搭建 RAG 应用

vLLM 是一个简单易用的 LLM 推理服务库。加州大学伯克利分校于 2024 年 7 月将 vLLM 作为孵化项目正式捐赠给 LF AI & Data Foundation 基金会。欢迎 vLLM 加入 LF AI & Data 大家庭&#xff01;&#x1f389; 在主流的 AI 应用架构中&#xff0c;大语言模型&#xff…

数据清洗-缺失值处理-缺失值可视化图(竖线)

目录 一、安装所需的python包二、缺失值可视化分析2.1 可直接运行代码2.2 以某个缺失值数据进行可视化实战2.2.1 代码运行过程截屏&#xff1a;2.2.2 缺失图可视化&#xff1a; 感觉大家对原理性的东西不太感兴趣&#xff0c;那我就直接举例提供代码&#xff0c;以及详细的注释…

13、Python如何设置文件缓冲

什么是I/O操作&#xff0c;看一下百度百科的说法&#xff1a;I/O操作是指对设备与cpu连接的接口电路的操作&#xff0c;不是对外围设备直接进行操作。宏观上讲&#xff0c;I/O是信息处理系统&#xff08;例如计算机&#xff09;与外部世界&#xff08;可能是人或其他信息处理系…

Flutter之SystemChrome全局设置

一、简介 SystemChrome作为一个全局属性&#xff0c;很像 Android 的 Application&#xff0c;功能很强大。 二、使用详解 2.1 setPreferredOrientations 设置屏幕方向 在我们日常应用中可能会需要设置横竖屏或锁定单方向屏幕等不同要求&#xff0c;通过 setPreferredOrien…

阿里云镜像报错 [Errno 14] HTTP Error 302 - Found 问题解决记录

1、问题背景和解决思路 在本地安装 CentOS7 后&#xff0c;网络已调通可正常上网&#xff0c;但切换阿里云镜像后&#xff0c;使用 yum 安装软件时出现 “[Errno 14] HTTPS Error 302 - Found Trying other mirror.” 报错&#xff0c;原因是 yum 源配置问题。给出了详细的解决…

分布式可信认证:数据安全与隐私保护新范式

文章目录 前言一、可信数字身份成数据要素流通的关键二、分布式可信认证成数据安全与隐私保护新范式1、分布式可信认证很好地解决传统数字身份认证的痛点问题2、可信数字身份上升为国家战略三、安全是未来数字身份的基础1、有效的威胁建模策略是确保这些系统安全性的基石前言 …

数据清洗-缺失值填充-随机森林搜寻最优参数填充

目录 一、安装所需的python包二、采用随机森林算法进行缺失值填充2.1可直接运行代码2.2以某个缺失值数据进行实战代码运行过程截屏&#xff1a;填充后的数据截屏&#xff1a; 三、随机森林算法 (Random Forest) 介绍3.1随机森林的定义3.2随机森林的基本思想3.3随机森林的工作原…

语言模型中的多模态链式推理(论文复现)

语言模型中的多模态链式推理&#xff08;论文复现&#xff09; 本文所涉及所有资源均在传知代码平台可获取 文章目录 语言模型中的多模态链式推理&#xff08;论文复现&#xff09;简介摘要引言多模态思维链推理的挑战多模态CoT框架多模态CoT模型架构细节编码模块融合模块解码模…

redis短信登录模型

基于Session实现登录 &#xff0c;

Unity程序基础框架

概述 单例模式基类 没有继承 MonoBehaviour 继承了 MonoBehaviour 的两种单例模式的写法 缓存池模块 &#xff08;确实挺有用&#xff09; using System.Collections; using System.Collections.Generic; using UnityEngine;/// <summary> /// 缓存池模块 /// 知识点 //…

数据结构基础详解:哈希表【C语言代码实践篇】开放地址法__拉链法_哈希表的创建_增删查操作详解

文章目录 1.哈希表代码实现之开放地址法1.1 开放地址法创建哈希表1.2 开放地址法之查找1.3 开放地址法之插入1.4 开放地址法之删除 2.哈希表代码实现之链地址法(拉链法)2.1 链地址法之创建哈希表2.2 链地址法之查找2.3 链地址法之插入2.4 链地址法之删除 1.哈希表代码实现之开放…

Stable diffusion生图原理

简介 Stable diffusion 是一种基于扩散技术的深度学习模型&#xff0c;于2022年发布&#xff0c;是Stability AI公司推出的首要产品&#xff0c;它主要用于生成以文本描述为条件的详细图像&#xff0c;同时也可以进行补绘、外绘、重绘等任务&#xff0c;但原理都和文生图原理…

C++中矩阵的介绍及相关应用扩展详解

1. 矩阵概念 在数学中&#xff0c;矩阵&#xff08;Matrix&#xff09;是一个按照长方阵列排列的复数或实数集合&#xff0c;最早来自于方程组的系数及常数所构成的方阵。这一概念由19世纪英国数学家凯利首先提出。 矩阵是高等代数学中的常见工具&#xff0c;也常见于统计分析…

Qt-QPushButton按钮类控件(22)

目录 描述 使用 给按钮添加图片 给按钮添加快捷键 添加槽函数 添加快捷键 添加组合键 开启鼠标的连发功能 描述 经过上面的一些介绍&#xff0c;我们也尝试的使用过了这个控件&#xff0c;接下来我们就要详细介绍这些比较重要的控件了 使用 给按钮添加图片 我们创建…

线性表之单链表

在上一节我们学习了线性表中的顺序表&#xff0c;今天我们来学习一下线性表中的另一种结构——单链表 前言 我们在之前已经初步了解了数据结构中的两种逻辑结构&#xff0c;但线性结构中并非只有顺序表一种&#xff0c;它还有不少兄弟姐妹&#xff0c;今天我们再来学习一下单链…

RealityCapture全面讲解:摄影测量软件的新纪元

随着数字化技术的迅猛发展&#xff0c;摄影测量软件在各行各业中的应用日益广泛。其中&#xff0c;RealityCapture作为一款领先的摄影测量解决方案&#xff0c;以其卓越的速度、精度和易用性&#xff0c;赢得了全球众多专业人士的青睐。本文将全面讲解RealityCapture的功能特点…

演示:基于WPF自绘的中国省份、城市、区县矢量地图

一、目的&#xff1a;演示一个基于WPF自绘的中国省份、城市、区县矢量地图 二、效果 国 省 市 三、功能 支持实际经纬度显示 支持平移&#xff0c;缩放等功能 显示中国地图 显示各个省份地图 显示各个省份地图&#xff08;包含在表格中&#xff0c;包含缩率图&#xff09; 显…

UE4_后期处理五—饱和度调整、隔离、扭曲、重影

一、色彩饱和度调整&#xff1a; 原图 后期处理材质节点&#xff1a; 效果图&#xff1a; 可以根据参数saturation调整饱和还是去饱和。 当saturation为1时&#xff1a;去饱和度&#xff0c;如下图&#xff1a; 当saturation为0时&#xff1a;原始的一个状态&#xff0c;如下…

JS import export export default ES6 modules 玩的明白吗

export (ES6) 导出 一个文件可以有多个&#xff0c;不可重名 命名导出&#xff1a; 使用export关键字导出变量、函数、类或值时&#xff0c;需要为它们指定名称。这些名称将在其他模块中用于导入。 export default 单一导出&#xff1a; export default 只能用于导出一个模块、…

python 读取excel

一、安装依赖&#xff1a; pandas 二、新建excel 示例数据&#xff1a;students.xlsx 三、定义类&#xff1a;student.py Student class Student:def __init__(self, name, sex):self.name nameself.sex sexdef show(self):print(f姓名&#xff1a;{self.name} 性别&#…