CV06_Canny边缘检测算法和python实现

news2024/9/9 5:55:37

1.1简介

Canny边缘检测算法是计算机视觉和图像处理领域中一种广泛应用的边缘检测技术,由约翰·F·坎尼(John F. Canny)于1986年提出。它是基于多级处理的边缘检测方法,旨在实现以下三个优化目标:

  1. 好的检测:尽可能多地检测出真正的边缘,同时尽量减少假阳性(误报)。
  2. 好的定位:检测到的边缘应该尽可能接近真实边缘的实际位置。
  3. 最小响应:对于单个边缘,只希望有一个响应,避免重复检测同一边缘。

Canny算法的步骤可以概括为以下几个阶段:

1. 高斯滤波(降噪)

算法的第一步是对原始图像进行高斯滤波,以去除图像中的噪声。高斯滤波是一种平滑处理,通过与高斯核进行卷积来实现,可以有效减少图像中的随机波动,而不模糊边缘太多。

2. 计算梯度幅度和方向

接着,算法会计算图像中每个像素点的梯度幅度和方向。梯度代表了像素值变化的强度,是边缘检测的关键。这通常通过应用Sobel算子或类似的微分算子在水平和垂直方向上进行,然后组合这些结果来得到梯度的大小和方向。梯度方向用于后续的非极大值抑制步骤。

3. 非极大值抑制(Edge thinning)

在这一步,算法沿着每个像素的梯度方向检查周围的像素,仅保留局部梯度最大的像素,即真正的边缘候选点。这样做是为了细化边缘,确保每个边缘只有单一的一行像素宽度,同时进一步减少噪声。

4. 双阈值检测和边缘连接

Canny算法采用了滞后阈值策略来区分强边缘和弱边缘。首先设定两个阈值(高阈值和低阈值),梯度幅度大于高阈值的像素被标记为强边缘,小于低阈值的像素被视为背景。介于两者之间的像素,如果与已标记的强边缘像素相连,则被视为弱边缘并最终加入到边缘集合中。这样可以有效连接断裂的边缘,同时排除孤立的噪声点。

5. 边缘跟踪与抑制

最后,通过边缘跟踪和抑制进一步优化边缘,确保边缘连续且光滑,同时减少不必要的边缘响应。

Canny算法之所以被广泛认为是最优的边缘检测算法之一,是因为它在准确性、效率和鲁棒性之间取得了很好的平衡。尽管如此,它也并非没有缺点,例如计算成本相对较高,且对阈值的选择敏感。但通过适当的参数调整和优化,Canny算法在许多应用场景中仍能提供高质量的边缘检测效果。

1.2 差分和梯度的关系

离散值的梯度计算通常涉及到差分,特别是在数字图像处理、数值分析以及某些类型的机器学习算法中。梯度本质上是一个向量,表示函数在某一点上的方向导数,即函数增长最快的方向。在连续空间中,梯度是偏导数的集合。但在离散空间(如像素网格上的图像)中,我们不能直接计算导数,而是通过有限差分近似来估计梯度。

一维情况

对于一维离散函数 𝑓(𝑥),在点 𝑥𝑖处的梯度(即导数的近似)可以通过向前差分或向后差分来估算:

这里,ℎ 是两点之间的间隔,通常代表采样间隔。

二维情况

在二维图像处理中,一个像素点 (𝑥𝑖,𝑦𝑗) 处的梯度是一个二维向量 (∂𝑓∂𝑥,∂𝑓∂𝑦),分别表示函数在 𝑥 和 𝑦 方向上变化的速率。同样使用差分近似:

最终,梯度的模(即梯度的大小)和方向常被用于边缘检测、图像增强、特征提取等应用中。在某些情况下,为了得到连续且更平滑的梯度估计,可以使用更复杂的方法,如高斯差分或其他平滑先验的梯度计算方法。

为什么离散函数的梯度用差分来表示

离散函数的梯度计算之所以使用差分来表示,是因为在离散空间中(比如数字图像中的像素点),我们无法直接应用连续函数的微分概念。在连续空间中,导数定义为函数值的变化率,即无限小的区间内的变化量比上这个区间的长度趋向于零的极限。然而,在离散空间里,函数值只在离散的点上有定义,没有“无限小”的概念,因此无法直接求极限。

差分则是离散空间中导数概念的自然近似。它通过计算相邻两点间函数值之差来量化函数值的变化率。这与导数的思想相似,但适用于离散数据点。例如,在一维离散函数中,两点之间的差分可以看作是在这两个点之间函数斜率的近似。在二维图像处理中,通过计算像素间灰度值的差异,我们可以近似得到图像中亮度变化的速率和方向,从而识别边缘、纹理等特征。

因此,差分不仅提供了计算离散梯度的有效方法,而且在数值分析和图像处理等领域的实际应用中非常实用,能够以一种直观且计算上可行的方式处理和分析离散数据的局部变化特性。

1.3 三种邻域像素距离定义

Canny算法中使用欧氏距离和城市距离都可以,欧氏距离含根号计算比较慢但是比较精准,城市距离都是整数计算比较快。

1.4 Sobel(索贝尔)算子

索贝尔算子(Sobel Operator)是一种广泛应用于图像处理领域的边缘检测技术,特别适用于需要确定图像中物体边界的位置和方向的情况。它是基于离散微分的一种方法,通过对图像进行局部微分操作,来估计图像中每个像素点的梯度强度及其方向,进而发现边缘。

原理与特点

  1. 离散差分算子:索贝尔算子是一种一阶离散差分算子,能够提供图像亮度函数梯度的近似值。它通过计算像素点在水平和垂直方向上的梯度分量来工作,这两个分量分别是图像在x轴和y轴方向上的变化率。

  2. 权重分配:与简单的梯度估计方法相比,索贝尔算子在计算像素差分时考虑了邻域像素的加权平均,即距离当前像素越近的邻像素被赋予的权重越大。这种权重分配机制使得索贝尔算子对噪声具有一定的抑制作用,因为它不仅仅依赖于直接相邻的像素差异,而是综合考虑了一个小邻域内的变化。

  3. 模板结构:索贝尔算子通常使用两个3x3的卷积核(掩模)来实现,一个用于计算水平梯度(Sobel x方向),另一个用于计算垂直梯度(Sobel y方向)。这些模板的系数经过精心设计,既能捕捉到方向上的变化,又能保持对噪声的一定鲁棒性。

  4. 边缘检测与方向:通过计算每个像素点的梯度幅度(通常是x和y方向梯度平方和的平方根),可以得到边缘强度。同时,梯度的方向可以指示边缘的方向。

  5. 性能与局限:索贝尔算子因其易于实现、计算效率高且能提供较好的边缘定位而被广泛采用。但它也存在一些局限性,比如检测到的边缘可能会比较粗,并且在某些情况下可能产生伪边缘,特别是在图像噪声较大或者边缘不清晰的情况下。

1.3 算法思路 

降噪(滤波)

在对图像进行边缘检测之前我们需要对图像进行滤波,常用的一般是高斯滤波,这样能够过滤点一些噪声点,否则在后期边缘检测会出现一些斑点。

滤波也有缺点,它会使图像变得模糊,从而丢失掉一些细节信息,也会导致边缘线一定程度的变粗。

灰度化图像并计算梯度

首先,我们的RGB图需要转成灰度图才能进行边缘检测,灰度图每个点有一个灰度值,最亮是255,最暗是0。边缘和里外两侧灰度值变化比较陡峭,但边缘连线上的灰度值变化比较平滑,所以边缘都是一些突变点。

我们用亮度值来衡量边缘,把变化越剧烈的点变得越亮,变化越平缓的点越暗,最终就能得到边缘检测的效果。

对于一维的离散函数,我们用梯度差分来表示亮度值,即 Dx = Ax+1 - Ax。比如我们有一列离散值1,2,10,100,100,这些是灰度值。对它们求差分,得到1,8,90,0,这些是亮度值。显然亮度值为90的点是边缘。

对于二维的离散函数,就比如图像的像素值,我们可以用前向水平和垂直差分表示:

\overrightarrow{D}=\begin{bmatrix}D^{\prime}x\\D^{\prime}y\end{bmatrix}=\begin{bmatrix}a_{x+1,y}-a_{x,y}\\a_{x,y+1}-a_{x,y}\end{bmatrix}

D的模值就当作亮度值,写作\overrightarrow{D}=\sqrt{D_{x}^{2}+D_{y}^{2}},D的方向角θ,记作\theta=\arctan(\frac{D'y}{D'x})

但是我们在Canny边缘检测时,梯度用的不是前向差分而是中心差分

\overrightarrow{D}_{xy}=\begin{bmatrix}D_{'x}\\D_{'y}\end{bmatrix}=\begin{bmatrix}\frac{a_{x+1,y}-a_{x-1,y}}{2}\\\\\frac{a_{x,y+1}-a_{x,y-1}}{2}\end{bmatrix}

a1a2a3
a4a5a6
a7a8a9

但是我们可以发现,用这种方法算中心点a5的梯度,a1,a3,a7,a9是没有作用的,但实际上它们对边缘检测是有影响的。这就引入了Sobel算子。

对于a5使用索贝尔算子后,采用城市距离,的中心差分梯度为:

\left.Da_{5}=\left[\begin{matrix}D_{5}^{\prime}x\\D_{5}^{\prime}y\end{matrix}\right.\right]=\left[\begin{matrix}\frac{a_{6}-a_{4}}{2\times1}+\frac{a_{9}-a_{1}}{2\times2}&-\frac{a_{7}-a_{3}}{2\times2}\\\frac{a_{8}-a_{2}}{2\times1}&+\frac{a_{9}-a_{1}}{2\times2}&+\frac{a_{7}-a_{3}}{2\times2}\end{matrix}\right],计算求模再向下取整。

公式如下:

这里第一行最后一个是减法的原因是根据sobel算子和XY轴正方向,a7到a3的方向在X轴的分量是负的。

得到θ角(范围-180°,180°)以后,我们规定X轴正方向为0°。假如θ角是45度,那么说明从a5到a9这个方向亮度值变化最剧烈。

计算图像中每一个像素点的亮度值(梯度),比较像素点与梯度方向相邻点的梯度值,最大的那个即为边缘。

非极大值抑制

如果只求梯度会导致一个问题,就是导致求出的图像边缘比较模糊而且线条比较暗且线条比较粗。

我们放大原图可以看到,边缘有几行像素只有最中间是最黑的,我们假设灰度值为0,旁边的像素灰度值可能是10,15,20,也就是说,边缘到非边缘其实是一个渐进的变化,不是突然从0到200的,这就导致了边缘的线条比较粗。

如何解决这个问题?就是用NMS。我们再看这个图,我们已经找到了最大梯度值的边缘,但是其他的值得到了保留,例如第三列的7,上面的5和下面的4还是保留着的,这时候我们就用NMS,将他们置为零,这样真正的边缘就出现了。

可以明显看到线条变细了。

双阈值检测

比如上面的图,如果某些像素点灰度值大于180,那么标记为强边缘,直接置为255,相对的,比如某些像素点的灰度值小于70,标记为背景,那么直接置为0.

孤立弱边缘抑制

什么是弱边缘,就是灰度值介于背景和强边缘之间的那些像素点的集合。弱边缘分为有用的和无用的,有用的大多与强边缘相近,无用的大多是孤立的。所以,我们要抑制这种孤立的弱边缘。

那么怎么才算孤立呢?假如一个弱边缘像素点,它周围一圈八个点不含强边缘的像素点,那么这个像素点就是孤立的,我们就置为0.

思考

在计算sobel算子下的离散函数梯度时,图像最边缘的像素点缺少相邻像素,该怎么办?

在使用Sobel算子计算图像边缘的离散函数梯度时,确实会遇到边界问题,因为图像的边缘像素缺少完整的邻域来应用3x3的卷积核。处理这种情况有几种常见方法:

  1. 边界扩展(Padding)

    • 镜像扩展(Mirror Padding):缺失的像素值由其对称位置的像素值镜像复制而来。
    • 常数扩展(Constant Padding):缺失的像素值填充为一个常数值,如0或图像边缘的像素值。
    • 重复最后一个像素值(Replicate Padding):边界像素值直接复制作为扩展。
    • 反射扩展(Reflect Padding):类似于镜像,但更像是物理反射,比如最后一个像素值的“前面”像素就是它自己。
  2. 忽略边界像素

    • 直接不计算图像边缘像素的梯度,这样会导致最终处理后的图像比原图小2个像素宽和高。
  3. 循环移位(Cyclic Padding)

    • 将图像视为周期性的,即图像的右侧与左侧相连,上边与下边相连,从而形成一个循环的边界条件。
  4. 使用专门针对边缘的算法变体

    • 有些算法对边界进行了特殊处理,设计了特殊的边界滤波器或者调整了边界处的卷积操作,以减少边缘效应。

在实际应用中,选择哪种方法取决于具体需求和对边缘效应的容忍度。镜像扩展是常用且效果较好的方法之一,因为它能够保持图像边缘的连续性,减少因边界处理引入的人工痕迹。在一些图像处理库中,如OpenCV,提供了对边界处理的选择项,允许用户根据具体情况选择合适的边界处理方式。

Python实现

1,rgb转灰度图

2,滤波(要注意滤波强度,滤波会使图像变模糊,图像太模糊会失去细节信息。 但是滤波可以去除噪声点,也可以用边缘强化滤波强化边缘)

3,求梯度(sobel算子)

4,非极大值抑制(使边缘更清晰)

5,双阈值(消去噪点,强化边缘)

6,抑制孤立弱边缘

from PIL import Image
from matplotlib import pyplot as plt
import math
from PIL import ImageFilter

im = Image.open("pic.jpg")
im_gray = im.convert('L')   #rgb转灰度图
# im_gray.show()  #显示灰度图

# im_gray = im_gray.filter(ImageFilter.SMOOTH)

#Image转为list类型
im_array = im_gray.load()
im_list = [[0 for i in range(im.size[0])] for j in range(im.size[1])]
for i in range(im.size[1]):
    for j in range(im.size[0]):
        im_list[i][j] = im_array[j, i]
plt.figure(1)
plt.imshow(im_list, cmap='gray')
# plt.show()


#求梯度 (梯度模值和方向)
#方向:  0:0度(x)    1: 45度   2: 90度(y) 3: 135度
grad = [[[0, 0] for i in range(im.size[0])] for j in range(im.size[1])]  #170 * 200 * 2 每个像素点的梯度大小和方向
for j in range(1, im.size[1] - 1):
    for i in range(1, im.size[0] - 1):
        #x方向梯度
        grad_x = im_list[j + 1][i + 1] + im_list[j - 1][i + 1] + 2 * im_list[j][i + 1] - \
                 im_list[j - 1][i - 1] - im_list[j + 1][i - 1] - 2 * im_list[j][i - 1]
        #y方向梯度
        grad_y = im_list[j + 1][i - 1] + im_list[j + 1][i + 1] + 2 * im_list[j + 1][i] - \
                 im_list[j - 1][i - 1] - im_list[j - 1][i + 1] - 2 * im_list[j - 1][i]
        grad_x = math.floor(grad_x / 4)
        grad_y = math.floor(grad_y / 4)
        #合梯度
        grad[j][i][0] = math.floor(math.sqrt(grad_x * grad_x + grad_y * grad_y))
        if(grad[j][i][0] > 255):
            grad[j][i][0] = 255
        # if(grad[j][i][0] < 50):
        #     grad[j][i][0] = 0
        #梯度方向
        if(grad_x == 0):
            grad[j][i][1] = 2  #y方向
        else:
            theta = math.atan2(grad_y, grad_x)
            if(math.fabs(theta) < math.pi / 8):
                grad[j][i][1] = 0 #x方向
            elif(theta > 0):
                if(math.fabs(theta) <math.pi * 3 / 8):
                    grad[j][i][1] = 1  #45度方向
                else:
                    grad[j][i][1] = 2#y方向
            else:
                if (math.fabs(theta) < math.pi * 3 / 8):
                    grad[j][i][1] = 3  # 135度方向
                else:
                    grad[j][i][1] = 2  # y方向

#显示梯度图
img = [[0 for i in range(im.size[0])] for j in range(im.size[1])]
for i in range(im.size[1]):
    for j in range(im.size[0]):
        img[i][j] = grad[i][j][0]
plt.figure(2)
plt.imshow(img, cmap='gray')
# plt.show()


#非极大值抑制,使边缘更清晰和细
img2 = img
for j in range(1, im.size[1] - 1):
    for i in range(1, im.size[0] - 1):
        dir = grad[j][i][1]
        grad_now = grad[j][i][0]
        if (dir == 0):  #梯度方向为x
            if(grad_now < grad[j][i + 1][0] or grad_now < grad[j][i - 1][0]):
                # grad[j][i][0] == 0
                img2[j][i] = 0
                print('0')
        elif(dir == 1):#45度方向
            if(grad_now < grad[j + 1][i + 1][0] or grad_now < grad[j - 1][i - 1][0]):
                # grad[j][i][0] == 0
                img2[j][i] = 0
                print('1')
        elif(dir == 2): #y方向
            if(grad_now < grad[j + 1][i][0] or grad_now < grad[j - 1][i][0]):
                # grad[j][i][0] == 0
                img2[j][i] = 0
                print('2')
        else:  #145度
            if(grad_now < grad[j + 1][i - 1][0] or grad_now < grad[j - 1][i + 1][0]):
                # grad[j][i][0] == 0
                img2[j][i] = 0
                print('3')

#显示非极大值抑制后的图像
plt.figure(3)
plt.imshow(img2, cmap='gray')
# plt.show()




#双阈值检测
low = 30
high = 60

for i in range(im.size[1]):
    for j in range(im.size[0]):
        if(img2[i][j] < low):
            img2[i][j] = 0
        elif(img2[i][j] > high):
            img2[i][j] = 255

#双阈值检测后的图像
plt.figure(4)
plt.imshow(img2, cmap='gray')
# plt.show()



#抑制孤立的弱边缘
listx = [-1, 0, 1]
listy = [-1, 0, 1]
img3 = img2
for j in range(1, im.size[1] - 1):
    for i in range(1, im.size[0] - 1):
        flag = 1
        for dx in range(len(listx)):
            for dy in range(len(listy)):
                j = j + listy[dy]
                i = i + listx[dx]
                if(img2[j][i] == 255):
                    flag = 0
                    break
            if(not flag):
                break
        if(flag):
            img3[j][i] = 0

#抑制孤立的弱边缘后的图像
# print('ssssssss')
plt.figure(5)
plt.imshow(img3, cmap='gray')
plt.show() 

Canny 的目标是找到一个最优的边缘检测算法,最优边缘检测的含义是:

(1)最优检测:算法能够尽可能多地标识出图像中的实际边缘,漏检真实边缘的概率和误检非边缘的概率都尽可能小;

(2)最优定位准则:检测到的边缘点的位置距离实际边缘点的位置最近,或者是由于噪声影响引起检测出的边缘偏离物体的真实边缘的程度最小;

(3)检测点与边缘点一一对应:算子检测的边缘点与实际边缘点应该是一一对应。 

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

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

相关文章

如何录制屏幕视频?4款软件,轻松录屏

在数字化飞速发展的时代&#xff0c;如何录制屏幕视频已经成为我们工作、学习和娱乐中不可省略的一个重要问题。无论是制作教学教程还是录制游戏视频等&#xff0c;屏幕视频录制都为我们提供了极大的便利。今天&#xff0c;就让我们一起探索如何录制屏幕视频的精彩方式&#xf…

记录文字视差背景学习

效果图 文字背景会随鼠标上下移动变成红色或透明 html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><titl…

Hydra

Intro Hydra是一个用来动态创建配置的python开源框架&#xff0c;使做研究和复杂的应用更便利&#xff0c;配置信息可以通过配置文件或者运行参数来覆盖。Hydra的名字来源于其可以运行多个相似任务&#xff0c;就像Hydra&#xff08;九头蛇&#xff09;有多个头一样。 Run 安…

初学51单片机之UART串口通信

CSDN其他博主的博文&#xff08;自用&#xff09;嵌入式学习笔记9-51单片机UART串口通信_51uart串口通讯-CSDN博客 CSDN其他博主的博文写的蛮好&#xff0c;如果你想了解51单片机UART串口可以点进去看看&#xff1a; UART全称Universal Asynchronous Receiver/Transmitter即通…

agents 分类

一、分类 自动agent、半自动agent、领域、自定义sop和支持人为干预的agent。 先泼个冷水&#xff0c;目前这些agent项目都是实验品&#xff0c;发展还没有做知识库问答相关开源项目那么成熟&#xff0c; 二、全自动agent autoGPT、loopGPT、babyAGI 全自动agent就是人类不可…

设计模式8-桥模式

设计模式8-Bridge 桥模式 由来与目的模式定义结构代码推导1. 类和接口的定义2. 平台实现3. 业务抽象4. 使用示例总结1. 类数量过多&#xff0c;复杂度高2. 代码重复3. 不符合单一职责原则4. 缺乏扩展性改进后的设计1. 抽象和实现分离&#xff08;桥接模式&#xff09;2. 抽象类…

Python爬虫:BeautifulSoup的基本使用方法!

1.简介 Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析“标签树”等功能。它是一个工具箱&#xff0c;通过解析文档为用户提供需要抓取的数据&#xff0c;因为简单&#xff0c;所以不需要多少代码就可以写出一个完整的应用程序。 Beautiful Soup…

一款面向程序员群体的AI问答产品火了!主打专业、正确率保障,消灭AI回答不可靠的问题

一直以来&#xff0c;无论是GPT、Claude还有国内的AI对话产品&#xff0c;都一直被诟病“AI回答不可靠”&#xff0c;尤其是在程序员这类对AI回答的可靠性要求极高的场景&#xff08;毕竟AI给代码里埋个bug&#xff0c;背锅的还是程序员&#xff09;。 而且当AI给的代码不可靠…

Androd 12 (MTK)修改屏幕物理分辨率Physical Size

1.需求说明 Android目前显示分辨率为480*800&#xff0c;立项表中像素为720*1280。请修改屏幕分辨率到指定大小。 2.思路分析 如果从手机修改对应的分辨率&#xff0c;必须自上而下的进行修改分为两个层面进行修改。 1.驱动底层 2.软件上层 3.结局方法与相关说明 查看当…

Vue打包文件dist放在SpringBoot项目下运行(正确实现全过程)(下)

在上一篇中&#xff0c;实现了Vue打包文件dist放在SpringBoot项目下运行。 Vue打包文件dist放在SpringBoot项目下运行&#xff08;正确实现全过程&#xff09;&#xff08;上&#xff09; 问题 路由刷新会产生404的问题。 原因 vue开发的应用&#xff0c;采用的是SPA单页…

c语言的简易教法—— 函数递归

文章目录 一、什么是递归&#xff1f;1.1递归的思想1.2递归的限制条件 二、递归案例2.1 案例1&#xff1a;求n的阶层2.1.1分析2.1.2 递归函数&#xff08;Fact&#xff09;的代码实现2.1.3 测试&#xff1a;main函数实现2.1.4 运行结果和画图推演2.1.5 扩展&#xff1a;迭代方法…

纹波电流与ESR:解析电容器重要参数与应用挑战

电解电容纹波电流与ESR&#xff08;Equivalent Series Resistance&#xff09;是电容器的重要参数&#xff0c;用来描述电容器对交流信号的响应能力和能量损耗。电解电容纹波电流是指电容器在工作时承受的交流信号电流&#xff0c;而ESR则是电容器内部等效电阻&#xff0c;影响…

2024年PMP报考需要什么条件?怎么报名?

PMP报名条件要求不高&#xff0c;只要满足下面两个条件&#xff1a; 1、35个PDU &#xff08;需要有 PMI 授权的机构颁发&#xff09; 2、项目经验 学士学位需要 4500 个小时的项目管理经验&#xff0c;3年工作经验&#xff1b; 非学士学位需要 7500 个小时的 项目管理经验&…

机器视觉:(1) 初识Roboflow(使用详解一)获取数据集(最新)

一&#xff1a;访问地址 [1] Roboflow官网&#xff1a;官网地址 [2]YOLOv8 项目地址github源码地址 [3]YOLOv8 官方教程官网教程地址 二&#xff1a;获取数据集步骤 1.访问官网地址&#xff1a;进入首页面&#xff0c;点击登录 2.注册过程省略了&#xff0c;按步骤走就可以…

Qt:18.状态栏(状态栏介绍、代码方式创建状态栏、在状态栏显示临时信息、在状态栏创建控件)

目录 1.状态栏介绍&#xff1a; 2.代码方式创建状态栏&#xff1a; 3. 在状态栏显示临时信息&#xff1a; 4.在状态栏创建控件&#xff1a; 1.状态栏介绍&#xff1a; Qt 状态栏是 QMainWindow 窗口的一部分&#xff0c;通常用于显示临时信息&#xff0c;如应用程序的状态、…

myeclipse开发ssm框架项目图书管理系统 mysql数据库web计算机毕业设计项目

摘 要 随着计算机的广泛应用&#xff0c;其逐步成为现代化的标志。图书馆的信息量也会越来越大&#xff0c;因此需要对图书信息、借书信息、还书信息等进行管理&#xff0c;及时了解各个环节中信息的变更&#xff0c;要对因此而产生的单据进行及时的处理&#xff0c;为了提高高…

【YashanDB知识库】YashanDB 开机自启

【问题分类】 YashanDB 开机自启 【关键字】 开机自启&#xff0c;依赖包 【问题描述】 数据库所在服务器重启后只拉起monit、yasom、yasom进程&#xff0c;缺少yasdb进程&#xff1a; 【问题原因分析】 数据库安装的时候未启动守护进程 【解决 / 规避方法】 进入数据库之前…

分别通过LS和RML进行模型参数辨识matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 4.1 最小二乘法(LS)参数辨识 4.2 递归最大似然估计(RML)参数辨识 5.完整程序 1.程序功能描述 分别通过LS和RML进行模型参数辨识matlab仿真&#xff0c;仿真输出参数辨识的误差&#xff0c…

【Linux】Linux背景历史

Linux背景历史 Linux背景Linux是什么&#xff1f;计算机的发展unix发展史Linux发展史开源Linux官网以及版本更替Linux企业应用现状 Linux环境的安装 Linux背景 Linux是什么&#xff1f; Linux(Linux Is Not UniX)&#xff0c;一般指GNU/Linux&#xff0c;是一种免费使用和自由…

边缘计算网关:一种高效安全的工业物联网解决方案-天拓四方

在工业物联网&#xff08;IIoT&#xff09;领域&#xff0c;数据处理和实时响应的需求日益增长&#xff0c;尤其是在智能制造、远程监控和预测性维护等场景中。边缘计算网关作为一种前端数据处理和决策设备&#xff0c;正逐渐成为满足这些需求的理想解决方案。 在一个大型制造…