Canny边缘检测原理及其python实现

Canny边缘检测原理及其python实现

转载请注明出处:©️ Sylvan Ding

Canny边缘检测算法

多数分割算法均基于灰度值的两个基本性质之一:不连续性和相似性。图像的边缘检测就是基于灰度的不连续性(灰度突变)来实现图像分割的。

边缘检测器是设计用来检测边缘像素的局部图像处理方法。一条线可视为一条边缘线段,该线两侧的背景灰度要么远亮于该线像素的灰度,要么远暗于该线像素的灰度,这样的线称之为“屋顶边缘”。

虽然Canny[1968]算法复杂,但其边缘检测的表现却相当优秀。

工具介绍

为了方便计算,我们将所有灰度都标定到 [0,1](归一化),这样就无需考虑系数的问题了。

二阶偏微分

∂f∂x=f(x+1)−f(x)\frac{\partial f}{\partial x}=f(x+1)-f(x)xf=f(x+1)f(x)

∂2f∂x2=f(x+1)+f(x−1)−2f(x)\frac{\partial^{2} f}{\partial x^{2}}=f(x+1)+f(x-1)-2 f(x)x22f=f(x+1)+f(x1)2f(x)

在实验3: 拉普拉斯锐化中曾讨论过用差分定义的导数来表征和检测灰度的突变,同时得到了如下结论:

  1. 二阶导数仅在“灰度斜坡”的开始、结尾处不为零,一阶导数在整个“灰度斜坡”上均不为零,因此一阶导数产生的边缘粗于二阶导数
  2. 同时,二阶导数变化的激烈度明显高于一阶导数,因此二阶导数更能增强细节(包括噪声、孤立点、边缘等)
  3. 在“斜坡”和“台阶”边缘二阶导数的符号相反,导致了“双边缘效应”,也可用于确定边缘是从亮到暗过渡还是从暗到亮过渡

对于一条边缘来说,二阶导数具有如下性质:

  1. 对图像中的边缘,二阶导数生成两个值(双边缘效应)
  2. 二阶导数的零交叉点可用于定位粗边缘中心

在这里插入图片描述

在这里插入图片描述

高斯低通滤波

不难证明,微弱的可见噪声会对边缘检测的上述两个关键导数产生严重影响,特别是对二阶偏导数的影响非常剧烈。所以在执行边缘检测前,需要对图像进行平滑处理(降噪)。

高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。

二维高斯函数(μ=0\mu=0μ=0, 中心点为原点)的定义如下:

G(x,y)=e−x2+y22σ2G(x, y)=\mathrm{e}^{-\frac{x^{2}+y^{2}}{2 \sigma^{2}}}G(x,y)=e2σ2x2+y2

注:G(x,y)G(x,y)G(x,y) 的系数 12πσ2\frac{1}{2\pi\sigma^2}2πσ21 可忽略,因为在计算得到权重矩阵后,还要对这个矩阵进行归一化。

GGG 和输入图像 fff 卷积形成平滑后的图像 fsf_sfs

fs(x,y)=G(x,y)∗f(x,y)f_s(x,y)=G(x,y)\ast f(x,y)fs(x,y)=G(x,y)f(x,y)

梯度和梯度方向

为了在 fff 中寻找边缘的强度和方向,所以引入梯度 ∇f\nabla ff,定义如下:

∇f≡grad⁡(f)≡[gxgy]=[∂f∂x∂f∂y]\nabla f \equiv \operatorname{grad}(f) \equiv\left[\begin{array}{l} g_{x} \\ g_{y} \end{array}\right]=\left[\begin{array}{l} \frac{\partial f}{\partial x} \\ \frac{\partial f}{\partial y} \end{array}\right]fgrad(f)[gxgy]=[xfyf]

∇f\nabla ff 表征了 fff 在该点 (x,y)(x,y)(x,y) 处最大变化率方向,其大小用 MMM 表示,方向角用 α\alphaα 表示(方向角是与以左上角为原点的坐标轴 x 轴之间的夹角):

M(x,y)=gx2+gy2M(x, y)=\sqrt{g_{x}^{2}+g_{y}^{2}}M(x,y)=gx2+gy2

α(x,y)=arctan⁡[gygx]\alpha(x, y)=\arctan \left[\frac{g_{y}}{g_{x}}\right]α(x,y)=arctan[gxgy]

M(x,y)M(x,y)M(x,y)α(x,y)\alpha (x,y)α(x,y)fff 的尺寸相同,∇f\nabla ff 和该点处的边缘正交,故梯度向量也称边缘法线。

通过 M(x,y)M(x,y)M(x,y)α(x,y)\alpha (x,y)α(x,y),可以分别构造梯度幅值矩阵和方向矩阵。梯度幅值矩阵是梯度的大小,表征了边缘的强度。而梯度方向矩阵则表征了梯度的方向。但是在计算 M(x,y)M(x,y)M(x,y) 时,涉及平方和平方根操作,计算开销大,所以经常使用绝对值来近似梯度幅值:

M(x,y)≈∣gx∣+∣gy∣M(x, y) \approx\left|g_{x}\right|+\left|g_{y}\right|M(x,y)gx+gy

Sobel算子

梯度中偏导数 gxg_xgxgyg_ygy 的计算需要使用模版(算子)对 fff 进行滤波。

一维模版对x方向、y方向分别求偏导数,即求x方向、y方向的边缘,但未考虑对角线方向的偏导数。Roberts[1965]交叉梯度算子以求对角像素(45∘,−45∘45^\circ,-45^\circ45,45)之差为基础,但 2×22\times 22×2 大小的模版对于用关于中心点对称的模版来计算边缘方向不是很有用,为了考虑中心点对称数据的性质、并携带有关边缘方向的更多信息,Prewitt[1970] 算子被提出:

Prewittx=[−1−1−1000111],Prewitty=[−101−101−101]Prewitt_x = \begin{bmatrix} -1 & -1 & -1 \\ 0 & 0 & 0 \\ 1 & 1 & 1 \end{bmatrix}, Prewitt_y = \begin{bmatrix} -1 & 0 & 1 \\ -1 & 0 & 1 \\ -1 & 0 & 1 \end{bmatrix}Prewittx=101101101,Prewitty=111000111

索贝尔算子(Sobel operator)[1970]主要用作边缘检测,本质上是一阶离散性差分算子,用来计算图像亮度函数的偏导数的近似值,因为它可以反应出灰度值剧烈变化的区域,而平滑灰度值变化缓慢的区域。Sobel 算子在中心位置使用 2 以平滑图像,更好的抑制噪声,Sobel 算子如下:

Sobelx=[−1−2−1000121],Sobely=[−101−202−101]Sobel_x = \begin{bmatrix} -1 & -2 & -1 \\ 0 & 0 & 0 \\ 1 & 2 & 1 \end{bmatrix}, Sobel_y = \begin{bmatrix} -1 & 0 & 1 \\ -2 & 0 & 2 \\ -1 & 0 & 1 \end{bmatrix}Sobelx=101202101,Sobely=121000121

那么,

Gx=Sobelx∗fs,Gy=Sobely∗fsG_x=Sobel_x\ast f_s\ ,\ G_y=Sobel_y\ast f_sGx=Sobelxfs , Gy=Sobelyfs

M=Gx2+Gy2M=\sqrt{G_{x}^{2}+G_{y}^{2}}M=Gx2+Gy2

α=arctan⁡[GyGx]\alpha=\arctan \left[\frac{G_{y}}{G_{x}}\right]α=arctan[GxGy]

梯度阈值处理

为了减小噪声对梯度幅值矩阵的影响,即可以在计算梯度前,对图像进行低通滤波(平滑),也可以在计算梯度后,对梯度图像进行阈值处理,可以设置大于或等于梯度图像的最大值的 xx% 的像素显示为白色,而低于该阈值的像素则显示为黑色,以减小噪声的影响。但是,在阈值处理后,可能会导致部分边缘的断线。

Canny边缘检测核心思想

在Canny[1968]之前,Marr和Hildreth[1980]就用高斯拉普拉斯(LoG)函数生成模版来进行边缘检测,他们论证了滤波器 ∇2G\nabla ^2G2G 的有效性。

Canny的三个目标:

  1. 低错误率。所有边缘都应被找到,并且没有伪响应;
  2. 边缘点被很好地定位。由检测器标记为边缘的点和真实边缘的中心之间的距离尽可能小;
  3. 单一的边缘点响应。对于真实的边缘点,检测器仅返回一个点,对于仅存一个单一边缘点的位置,检测器不应指出多个边缘像素

Canny基本步骤:

  1. 高斯滤波平滑输入图像
  2. 计算梯度幅值图像和角度图像
  3. 对梯度幅值图像应用非最大抑制(NMS)
  4. 双阈值处理,划分强、弱边缘
  5. 滞后边界跟踪,消除干扰(孤立弱边缘)

NMS

非最大值抑制(NMS)可以细化得到的边缘(梯度幅值),该方法本质上将边缘按梯度方向的范围进行离散化,定义了四个离散方向,分别是水平、垂直、45∘45^\circ45−45∘-45^\circ45. 以梯度幅值矩阵上每个点为中心,寻找其对于梯度方向最靠近的离散方向,若 M(x,y)M(x,y)M(x,y) 至少小于沿该方向的两个邻居之一,则抑制(gN(x,y)=0g_N(x,y)=0gN(x,y)=0),否则 gN(x,y)=M(x,y)g_N(x,y)=M(x,y)gN(x,y)=M(x,y).

NMS 的本质是对各点的由边缘法线确定的边缘进行细化,在该点处边缘的两侧和中心选取最大值,其余相邻像素位置零。

注意,查阅资料得知,NMS 也可以使用插值方法来精确计算,这里就用本书中提到的方法进行近似计算。

在这里插入图片描述

双阈值处理

最后对 gNg_NgN 进行双阈值处理,以减少伪边缘点(噪声)。

在用梯度幅值表征边缘时,用单阈值处理梯度幅值,若阈值过低,则会存在一些伪边缘,若阈值过高,则会删除有效边缘点,造成断线。

改进方式是设置两个阈值:LTL_TLTHTH_THT.

创建高、低阈值图像:

gNH(x,y)=gN(x,y)≥THg_{N H}(x, y)=g_{N}(x, y) \ge T_{H}gNH(x,y)=gN(x,y)TH

gNL(x,y)=gN(x,y)≥TLg_{N L}(x, y)=g_{N}(x, y) \geq T_{L}gNL(x,y)=gN(x,y)TL

此时,gNHg_{N H}gNH 中的所有非零像素都包含在 gNLg_{N L}gNL 中,则做如下运算得到“纯净的” gNLg_{N L}gNL(其像素点的灰度值在两阈值之间):

gNL(x,y)=gNL(x,y)−gNH(x,y)g_{N L}(x, y)=g_{N L}(x, y)-g_{N H}(x, y)gNL(x,y)=gNL(x,y)gNH(x,y)

gNHg_{N H}gNH 中的所有强像素均被认定为有效边缘像素,立即标记。而由于 THT_HTH 通常较大,故 gNHg_{N H}gNH 中的边缘会有缝隙。

滞后边界跟踪

弱边缘点则可能是真的边缘,也可能是噪声或颜色变化引起的。为得到精确的结果,后者引起的弱边缘点应该去掉。通常认为真实边缘引起的弱边缘点和强边缘点是连通的,而噪声引起的弱边缘点则不会。

滞后边界跟踪算法检查一个弱边缘点的 8 连通领域像素,只要有强边缘点存在,那么这个弱边缘点被认为是真是边缘保留下来。

这个算法搜索所有连通的弱边缘,如果一条连通的弱边缘的任何一个点和强边缘点连通,则保留这条弱边缘,否则抑制这条弱边缘。搜索时可以用广度优先或者深度优先算法。

算法说明如下:

  1. 输入:图像,计算其 gNL,gNHg_{NL},g_{NH}gNL,gNH
  2. 建立visited矩阵(和输入图像同形),表征每个像素是否在 DFS 中被访问,初始化该矩阵为零矩阵
  3. 建立 gnl_filtered矩阵,表征 gNLg_{NL}gNL 中连通的弱边缘,且该弱边缘也和 gNHg_{NH}gNH 中任意强边缘连通,即过滤调不符合条件的弱边缘后所剩下的符合条件的弱边缘(被认为是真边缘)。初始化该矩阵为零矩阵,不符合条件的弱边缘被抑制(置零)
  4. 从上到下,自左向右,遍历所有强边缘 gNHg_{NH}gNH,若该像素已经被访问,则继续访问访问下一个像素,直到所有强边缘都被访问。若像素未被访问,进入 DFS.
  5. DFS 中,搜索该强边缘的连通弱边缘。先标记该点已被访问,如果该点的 gNL(x,y)>0g_{NL}(x,y)\gt 0gNL(x,y)>0 ,即该点是弱边缘,将gnl_filtered对应位置改为该点的灰度值(弱边缘符合条件保留),再一次递归搜索该点的8领域(寻找连通弱边缘)。DFS 的退出条件为已被标记(即visited矩阵对应位置为True)或访问的点超出边界。
  6. 输出:经过双阈值处理的强边缘矩阵、弱边缘矩阵,滞后边界跟踪的连通弱边缘矩阵

之后可对该灰度图像进行二值化并展示。

编码实现和结果分析

import cv2
import numpy as np
import matplotlib.pyplot as pltimg0 = 'house.tif'
f = cv2.imread(img0, cv2.IMREAD_GRAYSCALE)
plt.imshow(f, cmap='gray')
plt.show()

在这里插入图片描述

def gauss_seperate_kernel(kernel_size, sigma=1):"""create gaussian kernel use separable vector, because gaussian kernel is symmetric and separable.param: kernel_size: input, the kernel size you want to create, normally is uneven number, such as 1, 3, 5, 7param: sigma: input, sigma of the gaussian function, default is 1return a desired size 2D gaussian kernel"""m = kernel_size[0]n = kernel_size[1]x_m = np.arange(m) - m // 2y_m = np.exp(-(x_m ** 2) / (2 * sigma ** 2)).reshape(-1, 1)x_n = np.arange(n) - n // 2y_n = np.exp(-(x_n ** 2) / (2 * sigma ** 2)).reshape(-1, 1)kernel = y_m * y_n.Treturn kerneln = 3  # gauss kernel size
sigma = 1  # sigma of the gaussian functiongauss_kernel = gauss_seperate_kernel((n, n), sigma=sigma)
fs = cv2.filter2D(f, ddepth=cv2.CV_32FC1, kernel=gauss_kernel, borderType=cv2.BORDER_DEFAULT)
plt.imshow(fs, cmap='gray')
plt.show()

在这里插入图片描述

sobelx = [[-1, -2, -1], [0, 0, 0], [1, 2, 1]]
sobelx = np.asarray(sobelx)
sobely = sobelx.TGx = cv2.filter2D(fs, -1, kernel=sobelx, borderType=cv2.BORDER_DEFAULT)
Gy = cv2.filter2D(fs, -1, kernel=sobely, borderType=cv2.BORDER_DEFAULT)fig, axs = plt.subplots(1, 2, figsize=(10, 5))
axs[0].set_title('Gx')
axs[0].imshow(Gx, cmap='gray')
axs[1].set_title('Gy')
axs[1].imshow(Gy, cmap='gray')plt.show()

在这里插入图片描述

很明显,GxG_xGx 表征 xxx 方向上的边界,GyG_yGy 表征 yyy 方向上的边界.

M = np.sqrt(np.square(Gx) + np.square(Gy))
alpha = np.arctan(np.divide(Gy, Gx, where=Gx!=0))fig, axs = plt.subplots(1, 2, figsize=(10, 5))
axs[0].set_title('M')
axs[0].imshow(M, cmap='gray')
axs[1].set_title(r'\alpha')
axs[1].imshow(alpha, cmap='gray')plt.show()

在这里插入图片描述

左图为梯度幅值,右图为梯度方向。

梯度幅值表征了边缘强度,梯度方向较好地识别了背景和房子,背景的梯度方向一致。

t = .33 # single thresholdMt = M.copy()
Mt[Mt < t * np.max(Mt)] = np.min(Mt)plt.imshow(Mt, cmap='gray')
plt.show()

在这里插入图片描述

可以看到,用单阈值直接处理梯度赋值图像得到的边缘中,一部分砖瓦的缝隙(我们不希望的)消失了,但也造成了部分边缘断线,且此时边缘仍然较粗。

def NMS(gradients, direction):""" Non-maxima suppressionArgs:gradients: the gradients of each pixeldirection: the direction of the gradients of each pixelReturns:the output image"""W, H = gradients.shapenms = np.copy(gradients)for i in range(1, W - 1):for j in range(1, H - 1):theta = direction[i, j]if np.abs(theta) < np.pi / 8:d = [0, 1]  # d1elif np.abs(theta) > np.pi * 3 / 8:d = [1, 0]  # d3elif np.pi / 8 <= theta:d = [1, 1]  # d2else:d = [1, -1]  # d4g1 = gradients[i + d[0], j + d[1]]g2 = gradients[i - d[0], j - d[1]]if g1 > gradients[i, j] or g2 > gradients[i, j]:nms[i, j] = 0return nmsMn = NMS(M, alpha)# binarization
Mn_b = np.copy(Mn)
threshold = 0.3 * np.max(Mn_b)
Mn_b[Mn_b < threshold] = 0
Mn_b[Mn_b >= threshold] = 1fig, axs = plt.subplots(1, 2, figsize=(10, 5))
axs[0].set_title('Mn')
axs[0].imshow(Mn, cmap='gray')
axs[1].set_title('Mn_binarized')
axs[1].imshow(Mn_b, cmap='gray')
plt.show()

在这里插入图片描述

上图为经过 NMS 后的边缘梯度图像,边缘被细化了。接下来进行双阈值处理和滞后边缘跟踪,进一步细化边缘。

def double_threshold(gn, tl, th):""" Double ThresholdUse two thresholds to compute the edge.Args:gn: the input imagetl: the low thresholdth: the high thresholdReturns:gnh, gnl, and true_gnl"""gnh, gnl = np.copy(gn), np.copy(gn)tl = np.max(gn) * tlth = np.max(gn) * thgnh[gnh < th] = .0gnl[gnl < tl] = .0gnl = gnl - gnhvisited = np.zeros_like(gn)gnl_filtered = np.zeros_like(gn).astype('float')W, H = gn.shapedef dfs(i, j):if i >= W or i < 0 or j >= H or j < 0 or visited[i, j] == 1:returnvisited[i, j] = 1if gnl[i, j] > 0 or gnh[i, j] > 0:gnl_filtered[i, j] = gnl[i, j]dfs(i - 1, j - 1)dfs(i - 1, j)dfs(i - 1, j + 1)dfs(i, j - 1)dfs(i, j + 1)dfs(i + 1, j - 1)dfs(i + 1, j)dfs(i + 1, j + 1)for w in range(W):for h in range(H):if visited[w, h] == 1:continueif gnh[w, h] > 0:dfs(w, h)return gnh, gnl, gnl_filtereddef draw_double_threshold(gn, tl, th):"""draw result pictures:return: gNH_b+gNL_true_b"""gNH, gNL, gNL_true = double_threshold(gn=gn, tl=tl, th=th)gNH_b = gNH.copy()gNL_b = gNL.copy()gNL_true_b = gNL_true.copy()gNH_b[gNH_b > 0] = np.max(gNH_b)gNL_b[gNL_b > 0] = np.max(gNL_b)gNL_true_b[gNL_true_b > 0] = np.max(gNL_true_b)combination = gNH_b + gNL_true_bcombination[combination > 0] = np.max(combination)fig, axs = plt.subplots(2, 2, figsize=(10, 10))axs[0][0].set_title('gNH_b')axs[0][0].imshow(gNH_b, cmap='gray')axs[0][1].set_title('gNL_b')axs[0][1].imshow(gNL_b, cmap='gray')axs[1][0].set_title('gNL_true_b')axs[1][0].imshow(gNL_true_b, cmap='gray')axs[1][1].set_title('combination: gNH_b+gNL_true_b')axs[1][1].imshow(combination, cmap='gray')plt.suptitle('tl={}, th={}'.format(tl, th))plt.show()return combinationtl0 = 0.05
th0 = 0.4
binarized_res0 = draw_double_threshold(Mn, tl0, th0)tl1 = 0.1
th1 = 0.5
binarized_res1 = draw_double_threshold(Mn, tl1, th1)

在这里插入图片描述

在这里插入图片描述

适当提高双阈值后((0.05, 0.4)->(0.1, 0.5)),对噪声的过滤增强,对强边缘的要求提高,故强边缘像素减少、弱边缘中噪声也减少。

过滤弱边缘中非连通边缘,再将过滤后的弱边缘和强边缘二值化图相加,得到最终的二值化边缘结果gNH_b+gNL_true_b.

# 和cv2库Canny函数对比
tl2 = 255 * 0.1
th2 = 255 * 0.5
g = cv2.Canny(f, tl2, th2)
plt.imshow(g, cmap='gray')
plt.show()

在这里插入图片描述

参考文献

  1. 数字图像处理:第3版,北京:电子工业出版社
  2. 图像滤波之高斯滤波
  3. 边缘检测之Sobel检测算子
  4. Canny边缘检测算法的python实现
  5. 常用测试数据集下载:“Standard” test images

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

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

相关文章

离奇的梦境,能够防范大脑过拟合

来源&#xff1a;混沌巡洋舰 1 )梦让我们对世界的理解不再那么简单化关于为什么大脑进化出夜间做梦&#xff1f;神经科学界提出了各种假说&#xff0c;诸如通过梦来调节情绪&#xff0c;巩固记忆&#xff0c;或梦可以帮助我们选择性的遗忘&#xff0c;对我们应对现实世界的问题…

RGB空间中的彩色图像分割原理及其python实现

RGB空间中的彩色图像分割 ⭐️ 为尊重原创性&#xff01;转载请注明出处&#xff1a;©️ Sylvan Ding’s Blog 概述 本文论述了基于欧式距离和曼哈顿距离的彩色图像分割算法&#xff0c;并用python实现了各个算法。之后将二者的优势结合&#xff0c;提出了改进后的曼哈顿…

路飞学城Python-Day171

Evernote Export 线性结构&#xff1a;python的列表操作列表是如何存储的&#xff1a;顺序存储的&#xff0c;是一块连续的内存&#xff0c;内存是一堆格子&#xff0c;列表是一串连续的编号32位机器上一个整数占4个字节数组和列表有2点不同&#xff0c;1.数组的元素类型要求是…

HarmonyOS 2面世!是没有退路还是时机成熟?中国操作系统崛起元年或已到来

来源&#xff1a;21Tech(News-21)作者&#xff1a;倪雨晴编辑&#xff1a;张星6月2日晚间&#xff0c;华为鸿蒙操作系统HarmonyOS迎来重要时刻&#xff0c;华为正式发布多款搭载HarmonyOS 2的新产品&#xff0c;包括HUAWEI Mate 40系列新版本、Mate X2新版本、HUAWEI WATCH 3系…

操作系统:线程同步

操作系统&#xff1a;线程同步 使用Linux无名信号量实现了读写者线程的互斥和同步。 实验环境 环境&#xff1a;Linux语言&#xff1a;CCMake&#xff1a;3.17.1GCC&#xff1a;7.5.0IDE&#xff1a;Clion 2020.3.1 实验目标 理解进程同步的两种制约关系&#xff1a;互斥与…

中国工程院2021年院士增选第二轮候选人名单公布

来源&#xff1a;先进制造业中国工程院2021年院士增选进入第二轮评审候选人名单&#xff08;按候选人姓名拼音排序&#xff09;未来智能实验室的主要工作包括&#xff1a;建立AI智能系统智商评测体系&#xff0c;开展世界人工智能智商评测&#xff1b;开展互联网&#xff08;城…

vsftpd部署流程和常见问题详解

vsftpd部署流程和常见问题详解 ⭐️ 网上关于在云服务器里配置vsftpd的文章鱼龙混杂&#xff0c;没有一篇是可以彻底解决问题的&#xff0c;有些问题虽简单&#xff0c;但也让初学者感到困惑。本文详细说明vsftpd的部署流程和一些常见问题的解决方法&#xff0c;详述用户创建过…

谷歌发布史上最强人类大脑「地图」,1.3亿个突触,在线可视3D神经元「森林」!...

来源&#xff1a;Google AI Blog编辑&#xff1a;yaxin, LQ &#xff08;新智元&#xff09;突触&#xff0c;是神经网络的「桥梁」。我们知道&#xff0c;人类大脑有860亿个神经元&#xff0c;因为有了突触&#xff0c;才可以把神经元上的电信号传递到下一个神经元。长久以来&…

智慧食堂项目策划书(商业计划书/立项计划)

金鹰物联智慧食堂项目策划书&#xff08;商业计划书/立项计划&#xff09; ©️ 金鹰物联项目组&#xff0c;转载请注明出处&#xff01; ⭐️ 技术部分请参考博文&#xff1a;基于YOLOv5的中式快餐店菜品识别系统 文章目录金鹰物联智慧食堂项目策划书&#xff08;商业计划…

pipelineDB学习笔记-2. Stream (流)

一、流的定义&#xff1a; 所谓的“流”&#xff08;stream&#xff09;在pipelineDB中是指那些被允许的数据库客服端推送到 Continuous View&#xff08;连续视图&#xff09; 的时序化数据的一种“抽象”。流中的每一个raw(数据列)或者event(事件)&#xff0c;看起来是和普通…

银行家算法之Python实现[操作系统实验]

银行家算法 银行家算法是著名的死锁避免算法&#xff0c;其思想是&#xff1a;把操作系统视为银行家&#xff0c;操作系统管理的资源相当于银行家管理的资金&#xff0c;进程向操作系统请求分配资源相当于用户向银行家贷款。操作系统按照银行家制定的规则为进程分配资源。进程…

城市智能化发展中,AI公司应该做什么?

来源&#xff1a;虎嗅APP题图来源:视觉中国在上海长宁区的部分区域&#xff0c;你会发现共享单车总是能够整整齐齐的排列&#xff0c;并且在每一个你需要的街道路边&#xff0c;都能找到空闲的单车&#xff0c;既不会车辆爆满&#xff0c;也不会无车可骑。这些城市细微之处的体…

getchar(),putchar()用法

1.getchar函数可以接收用户输入的多个字符&#xff0c;只用等用户按下回车键后&#xff0c;getchar()函数才会从键盘缓冲区依次读出字符&#xff1b; 2.getchar()和putchar()结合使用&#xff0c;可以将读取的字符输出到屏幕&#xff1b; 3.函数原型&#xff1a; int getchar…

[操作系统]页面置换算法实验及C++实现(OPT、FIFO、LRU)

虚拟内存页面置换算法实验&#xff08;OPT、FIFO、LRU&#xff09; 进程运行时&#xff0c;若其访问的页面不再内存中而需将其调入&#xff0c;但内存已无空闲空间时&#xff0c;就需要从内存中调出一页程序或数据&#xff0c;送入磁盘的对换区。选择调出页面的算法就称为页面…

智谱AI多项成果惊艳亮相2021北京智源大会

来源&#xff1a;学术头条2021 年 6 月 1 日&#xff0c;由北京智源人工智能研究院&#xff08;以下简称 “智源”&#xff09;主办的 2021 北京智源大会在北京中关村国家自主创新示范区会议中心成功开幕。包括 Yoshua Bengio、David Patterson 等图灵奖获得者在内的两百余位国…

python-字典方法

1.字典的格式化字符串在转换说明符%后面加上键(圆括号括起来)&#xff1b;phonebook{"A":45,"B":"56"} s"As phone number is %(A)s." print(s%phonebook) 运行结果&#xff1a; #字典方法&#xff1a; #clear():清楚字典中的所有的项…

获得诺贝尔奖的底层小职员 | 从来没有一个高手,是在一夜之间强大起来的

来源&#xff1a;Pinterest优选2019年初NHK的一个访谈纪录片&#xff0c;看哭了很多网友。“感动&#xff0c;这才是真正的大神啊&#xff01;”纪录片的主人公&#xff0c;是2002年的诺贝尔化学奖得主——田中耕一。十九年前&#xff0c;他的获奖几乎是“都市传说”般的爆炸新…

光辉岁月:人工智能的那些人和事(1)

来源&#xff1a;图灵人工智能源头茫昧虽难觅&#xff0c;活水奔流喜不休。——法国数学家亨利庞加莱&#xff08;Henri Poincare&#xff09;目前&#xff0c;人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;正在迅速崛起。现已面世的AI应用&#xff…

MySQL主从架构及读写分离实战

​​​​​​ 目录 一、实验目的与环境 二、基础环境介绍 三、搭建主从集群 1、理论基础 2、同步的原理 3、搭建主从集群 3.1 配置master主服务器 3.2 配置slave从服务 3.3 主从集群测试 3.4 集群搭建扩展&#xff1a; 3.5、GTID同步集群 4、集群扩容 5、半同步复…

编译原理课程实践——实现一个初等函数运算语言的解释器或编译器

编译原理课程实践——实现具有初等函数运算语言的解释器或编译器 作者&#xff1a;Sylvan Ding &#xff5c;转载请注明文章出处&#xff01; 摘要&#xff1a;本文主要内容是设计词法分析器、语法分析器&#xff08;LL(1)、SLR(1)&#xff09;和语义分析器&#xff08;基于SL…