Steger算法实现结构光光条中心提取(python版本)

Steger算法原理

对结构光进行光条中心提取时,Steger算法是以Hessian矩阵为基础的。它的基础步骤如下所示:

  1. 从Hessian矩阵中求出线激光条纹的法线方向
  2. 在光条纹法线方向上将其灰度分布按照泰勒多项式展开,求取的极大值即为光条在该法线方向上的亚像素坐标。对于二维离散图像I(u,v)来说,Hessian矩阵可以表示为:

H(u,v) = \begin{bmatrix} I_{uu} &I_{uv} \\ I_{uv} & I_{vv} \end{bmatrix}

这里面的u,v表示的就是像素的行坐标和列坐标,I_{uv}代表像素(u,v)的灰度也可以称之为灰度分布函数。而I_{uu}I_{uv}I_{vv}都可以通过I_{uv}与二维高斯函数G(u,v)卷积运算得到。

G(u,v) = \frac{1}{\sigma\sqrt{2 \pi}}\cdot e^{\left ( -\frac{u^{2}+v^{2}}{2\sigma^{2}} \right )}

I_{uu}=\frac{\partial ^{2}}{\partial u\partial u}G(u,v)\bigotimes I_{uv}

I_{uv}=\frac{\partial ^{2}}{\partial u\partial v}G(u,v)\bigotimes I_{uv}

I_{vv}=\frac{\partial ^{2}}{\partial v\partial v}G(u,v)\bigotimes I_{uv} 

在这里,二维高斯函数,其主要作用是为了让光条灰度分布特性更加明显,在G(u,v)表达式中,\sigma是标准差,一般取\sigma \geq \frac{W}{\sqrt{3}},W代表光条宽度。在像素(u,v)处的Hessian矩阵有两个特征向量,其中一个绝对值较大,为该像素处的法线方向向量,而另外一个则是切向方向向量。因此可以通过求取Hessian矩阵的特征向量来计算出法线方向。某一像素点H(u_{0},v_{0}),在二阶泰勒展开式Hessian矩阵为:

H(u_{0},v_{0}) = \begin{bmatrix} I_{uu} &I_{uv} \\ I_{uv} & I_{vv} \end{bmatrix}

由该点的Hessian矩阵所求出的特征值和特征向量分别与该点的法线方向和该方向的二阶方向导数相对应。其中法线方向的单位向量为:e = [e_{u},e_{v}],并且在光条纹法线方向上的像素点(u_{0}+t\cdot e_{u},v_{0}+t\cdot e_{v}),并且在光条纹法线方向上的像素点I = (u_{0}+t\cdot e_{u},v_{0}+t\cdot e_{v})可以由像素(u0,v0)的灰度I(u0,v0)和二阶泰勒展开多项式表示为:

I (u_{0}+t\cdot e_{u},v_{0}+t\cdot e_{v}) = I(u_{0},v_{0})+t\cdot e[I_{u},I_{v}]^{T} +t\cdot e\cdot H(u,v) \cdot e^{T}

t = -\frac{e_{u}\cdot I_{u}+e_{v}\cdot I_{v}}{e_{u}^{2}\cdot I_{uu}+2\cdot e_{u}\cdot e_{v}\cdot I_{uv}+e_{v}^{2}\cdot I_{vv}}

再将t(即泰勒展开式)代入其中即可求出光条纹中心的亚像素坐标。

Steger算法Python实现

这一部分,我在网上找到了许多C++版本的Steger算法实现,本人参考了现有的C++版本Steger算法实现,在此基础上进行了改进,用Python重新去实现该算法。

计算图像的一阶导数和二阶导数

这里我采用了三种方法,分别是自定义卷积、Scharr 滤波器、Sobel 滤波器来计算图像的导数和二阶导数。

import cv2
import numpy as npdef _derivation_with_Filter(Gaussimg):dx = cv2.filter2D(Gaussimg,-1, kernel=np.array([[1], [0], [-1]]))dy = cv2.filter2D(Gaussimg,-1, kernel=np.array([[1, 0, -1]]))dxx = cv2.filter2D(Gaussimg,-1, kernel=np.array([[1], [-2], [1]]))dyy = cv2.filter2D(Gaussimg,-1, kernel=np.array([[1, -2, 1]]))dxy = cv2.filter2D(Gaussimg,-1, kernel=np.array([[1, -1], [-1, 1]]))return dx, dy, dxx, dyy, dxydef _derivation_with_Scharr(Gaussimg):dx = cv2.Scharr(Gaussimg, cv2.CV_32F, 1, 0)dy = cv2.Scharr(Gaussimg, cv2.CV_32F, 0, 1)dxx = cv2.Scharr(dx, cv2.CV_32F, 1, 0)dxy = cv2.Scharr(dx, cv2.CV_32F, 0, 1)dyy = cv2.Scharr(dy, cv2.CV_32F, 0, 1)return dx, dy, dxx, dyy, dxydef _derivation_with_Sobel(Gaussimg):dx = cv2.Sobel(Gaussimg, cv2.CV_32F, 1, 0, ksize=3)dy = cv2.Sobel(Gaussimg, cv2.CV_32F, 0, 1, ksize=3)dxx = cv2.Sobel(dx, cv2.CV_32F, 1, 0, ksize=3)dxy = cv2.Sobel(dx, cv2.CV_32F, 0, 1, ksize=3)dyy = cv2.Sobel(dy, cv2.CV_32F, 0, 1, ksize=3)return dx, dy, dxx, dyy, dxyif __name__=="__main__":from pyzjr.dlearn import RuncodessigmaX, sigmaY = 1.1, 1.1img = cv2.imread(r"D:\PythonProject\net\line\linedata\Image_1.jpg")gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)Gaussimg = cv2.GaussianBlur(gray_img, ksize=(0, 0), sigmaX=sigmaX, sigmaY=sigmaY)with Runcodes("Filter"):dx, dy, dxx, dyy, dxy = _derivation_with_Filter(Gaussimg)print(type(dx[0][0]))with Runcodes("Scharr"):dx1, dy1, dxx1, dyy1, dxy1 = _derivation_with_Scharr(Gaussimg)print(type(dx1[0][0]))with Runcodes("Sobel"):dx2, dy2, dxx2, dyy2, dxy2 = _derivation_with_Sobel(Gaussimg)print(type(dx2[0][0]))

在控制台中输出为:

<class 'numpy.uint8'>
Filter: 0.00602 sec
<class 'numpy.float32'>
Scharr: 0.00770 sec
<class 'numpy.float32'>
Sobel: 0.01025 sec

从运算时间上来看,自定义的Filter速度最快,scharr滤波器居中,sobel滤波器最慢;从元素类型上来看,第一种为uint8,另外两种为float32类型。

通过选择计算方法可以去创建Hessian矩阵。

def Magnitudefield(dxx, dyy):"""计算幅度和相位"""dxx = dxx.astype(float)dyy = dyy.astype(float)mag = cv2.magnitude(dxx, dyy)phase = mag*180./np.pireturn mag, phasedef derivation(gray_img, sigmaX, sigmaY, method="Scharr", nonmax=False):"""计算图像的一阶导数 dx 和 dy,以及二阶导数 dxx、dyy 和 dxy:param gray_img: 灰度图:param sigmaX: 在水平方向的高斯核标准差,用于激光线提取建议取1-2:param sigmaY: 在垂直方向上的高斯核标准差,用于激光线提取建议取1-2:param method:"Scharr"  or  "Filter"  or  "Sobel"选择什么方式获取dx, dy, dxx, dyy, dxy,提供了卷积与Scharr和Sobel滤波器三种方式计算,Scharr滤波器通常会产生更平滑和准确的结果,所以这里默认使用"Scharr"方法,虽然"Sobel"运行比另外两种要慢,但在使用的时候,建议自己试试:return: dx, dy, dxx, dyy, dxy"""Gaussimg = cv2.GaussianBlur(gray_img, ksize=(0, 0), sigmaX=sigmaX, sigmaY=sigmaY)dx, dy, dxx, dyy, dxy = _derivation_with_Scharr(Gaussimg)if method == "Filter":dx, dy, dxx, dyy, dxy = _derivation_with_Filter(Gaussimg)elif method == "Sobel":dx, dy, dxx, dyy, dxy =_derivation_with_Sobel(Gaussimg)if nonmax:normal, phase = Magnitudefield(dxx, dyy)dxy = nonMaxSuppression(normal, phase)return dx, dy, dxx, dyy, dxydef nonMaxSuppression(det, phase):"""非最大值抑制"""gmax = np.zeros(det.shape)# thin-out evry edge for angle = [0, 45, 90, 135]for i in range(gmax.shape[0]):for j in range(gmax.shape[1]):if phase[i][j] < 0:phase[i][j] += 360if ((j+1) < gmax.shape[1]) and ((j-1) >= 0) and ((i+1) < gmax.shape[0]) and ((i-1) >= 0):# 0 degreesif (phase[i][j] >= 337.5 or phase[i][j] < 22.5) or (phase[i][j] >= 157.5 and phase[i][j] < 202.5):if det[i][j] >= det[i][j + 1] and det[i][j] >= det[i][j - 1]:gmax[i][j] = det[i][j]# 45 degreesif (phase[i][j] >= 22.5 and phase[i][j] < 67.5) or (phase[i][j] >= 202.5 and phase[i][j] < 247.5):if det[i][j] >= det[i - 1][j + 1] and det[i][j] >= det[i + 1][j - 1]:gmax[i][j] = det[i][j]# 90 degreesif (phase[i][j] >= 67.5 and phase[i][j] < 112.5) or (phase[i][j] >= 247.5 and phase[i][j] < 292.5):if det[i][j] >= det[i - 1][j] and det[i][j] >= det[i + 1][j]:gmax[i][j] = det[i][j]# 135 degreesif (phase[i][j] >= 112.5 and phase[i][j] < 157.5) or (phase[i][j] >= 292.5 and phase[i][j] < 337.5):if det[i][j] >= det[i - 1][j - 1] and det[i][j] >= det[i + 1][j + 1]:gmax[i][j] = det[i][j]return gmax

Magnitudefield(dxx, dyy)函数计算梯度的幅度和相位,使用给定的 x 和 y 导数 (dxx 和 dyy)。幅度代表梯度的强度,相位代表梯度的方向;nonMaxSuppression(det, phase)函数根据梯度的相位 (phase) 对梯度幅度 (det) 执行非最大值抑制。它有助于在梯度方向上仅保留局部最大值,从而细化检测到的边缘;然后应用于derivation函数中去调控。

二阶泰勒展开式Hessian矩阵

def HessianMatrix(self, dx, dy, dxx, dyy, dxy, threshold=0.5):"""HessianMatrix = [dxx    dxy][dxy    dyy]compute hessian:[dxx   dxy]         [00    01]====>[dxy   dyy]         [10    11]"""point=[]direction=[]value=[]for x in range(0, self.col):for y in range(0, self.row):if dxy[y,x] > 0:hessian = np.zeros((2,2))hessian[0,0] = dxx[y,x]hessian[0,1] = dxy[y,x]hessian[1,0] = dxy[y,x]hessian[1,1] = dyy[y,x]# 计算矩阵的特征值和特征向量_, eigenvalues, eigenvectors = cv2.eigen(hessian)if np.abs(eigenvalues[0,0]) >= np.abs(eigenvalues[1,0]):nx = eigenvectors[0,0]ny = eigenvectors[0,1]else:nx = eigenvectors[1,0]ny = eigenvectors[1,1]# Taylor展开式分子分母部分,需要避免为0的情况Taylor_numer = (dx[y, x] * nx + dy[y, x] * ny)Taylor_denom = dxx[y,x]*nx*nx + dyy[y,x]*ny*ny + 2*dxy[y,x]*nx*nyif Taylor_denom != 0:T = -(Taylor_numer/Taylor_denom)# Hessian矩阵最大特征值对应的特征向量对应于光条的法线方向if np.abs(T*nx) <= threshold and np.abs(T*ny) <= threshold:point.append((x,y))direction.append((nx,ny))value.append(np.abs(dxy[y,x]+dxy[y,x]))return point, direction, value

这一部分我定义在steger类下了

绘制中心线在背景与原图中

def centerline(self,img, sigmaX, sigmaY, method="Scharr", usenonmax=True, color=(0, 0, 255)):dx, dy, dxx, dyy, dxy = derivation(self.gray_image, sigmaX, sigmaY, method=method, nonmax=usenonmax)point, direction, value = self.HessianMatrix(dx, dy, dxx, dyy, dxy)for point in point:self.newimage[point[1], point[0]] = 255img[point[1], point[0], :] = colorreturn img, self.newimage

代码以及效果展示

import cv2
import numpy as npdef _derivation_with_Filter(Gaussimg):dx = cv2.filter2D(Gaussimg,-1, kernel=np.array([[1], [0], [-1]]))dy = cv2.filter2D(Gaussimg,-1, kernel=np.array([[1, 0, -1]]))dxx = cv2.filter2D(Gaussimg,-1, kernel=np.array([[1], [-2], [1]]))dyy = cv2.filter2D(Gaussimg,-1, kernel=np.array([[1, -2, 1]]))dxy = cv2.filter2D(Gaussimg,-1, kernel=np.array([[1, -1], [-1, 1]]))return dx, dy, dxx, dyy, dxydef _derivation_with_Scharr(Gaussimg):dx = cv2.Scharr(Gaussimg, cv2.CV_32F, 1, 0)dy = cv2.Scharr(Gaussimg, cv2.CV_32F, 0, 1)dxx = cv2.Scharr(dx, cv2.CV_32F, 1, 0)dxy = cv2.Scharr(dx, cv2.CV_32F, 0, 1)dyy = cv2.Scharr(dy, cv2.CV_32F, 0, 1)return dx, dy, dxx, dyy, dxydef _derivation_with_Sobel(Gaussimg):dx = cv2.Sobel(Gaussimg, cv2.CV_32F, 1, 0, ksize=3)dy = cv2.Sobel(Gaussimg, cv2.CV_32F, 0, 1, ksize=3)dxx = cv2.Sobel(dx, cv2.CV_32F, 1, 0, ksize=3)dxy = cv2.Sobel(dx, cv2.CV_32F, 0, 1, ksize=3)dyy = cv2.Sobel(dy, cv2.CV_32F, 0, 1, ksize=3)return dx, dy, dxx, dyy, dxydef Magnitudefield(dxx, dyy):"""计算幅度和相位"""dxx = dxx.astype(float)dyy = dyy.astype(float)mag = cv2.magnitude(dxx, dyy)phase = mag*180./np.pireturn mag, phasedef derivation(gray_img, sigmaX, sigmaY, method="Scharr", nonmax=False):"""计算图像的一阶导数 dx 和 dy,以及二阶导数 dxx、dyy 和 dxy:param gray_img: 灰度图:param sigmaX: 在水平方向的高斯核标准差,用于激光线提取建议取1-2:param sigmaY: 在垂直方向上的高斯核标准差,用于激光线提取建议取1-2:param method:"Scharr"  or  "Filter"  or  "Sobel"选择什么方式获取dx, dy, dxx, dyy, dxy,提供了卷积与Scharr和Sobel滤波器三种方式计算,Scharr滤波器通常会产生更平滑和准确的结果,所以这里默认使用"Scharr"方法,虽然"Sobel"运行比另外两种要慢,但在使用的时候,建议自己试试:return: dx, dy, dxx, dyy, dxy"""Gaussimg = cv2.GaussianBlur(gray_img, ksize=(0, 0), sigmaX=sigmaX, sigmaY=sigmaY)dx, dy, dxx, dyy, dxy = _derivation_with_Scharr(Gaussimg)if method == "Filter":dx, dy, dxx, dyy, dxy = _derivation_with_Filter(Gaussimg)elif method == "Sobel":dx, dy, dxx, dyy, dxy =_derivation_with_Sobel(Gaussimg)if nonmax:normal, phase = Magnitudefield(dxx, dyy)dxy = nonMaxSuppression(normal, phase)return dx, dy, dxx, dyy, dxydef nonMaxSuppression(det, phase):"""非最大值抑制"""gmax = np.zeros(det.shape)# thin-out evry edge for angle = [0, 45, 90, 135]for i in range(gmax.shape[0]):for j in range(gmax.shape[1]):if phase[i][j] < 0:phase[i][j] += 360if ((j+1) < gmax.shape[1]) and ((j-1) >= 0) and ((i+1) < gmax.shape[0]) and ((i-1) >= 0):# 0 degreesif (phase[i][j] >= 337.5 or phase[i][j] < 22.5) or (phase[i][j] >= 157.5 and phase[i][j] < 202.5):if det[i][j] >= det[i][j + 1] and det[i][j] >= det[i][j - 1]:gmax[i][j] = det[i][j]# 45 degreesif (phase[i][j] >= 22.5 and phase[i][j] < 67.5) or (phase[i][j] >= 202.5 and phase[i][j] < 247.5):if det[i][j] >= det[i - 1][j + 1] and det[i][j] >= det[i + 1][j - 1]:gmax[i][j] = det[i][j]# 90 degreesif (phase[i][j] >= 67.5 and phase[i][j] < 112.5) or (phase[i][j] >= 247.5 and phase[i][j] < 292.5):if det[i][j] >= det[i - 1][j] and det[i][j] >= det[i + 1][j]:gmax[i][j] = det[i][j]# 135 degreesif (phase[i][j] >= 112.5 and phase[i][j] < 157.5) or (phase[i][j] >= 292.5 and phase[i][j] < 337.5):if det[i][j] >= det[i - 1][j - 1] and det[i][j] >= det[i + 1][j + 1]:gmax[i][j] = det[i][j]return gmaxclass Steger():def __init__(self, gray_image):self.gray_image = gray_imageself.row, self.col = self.gray_image.shape[:2]self.newimage = np.zeros((self.row, self.col), np.uint8)def centerline(self,img, sigmaX, sigmaY, method="Scharr", usenonmax=True, color=(0, 0, 255)):dx, dy, dxx, dyy, dxy = derivation(self.gray_image, sigmaX, sigmaY, method=method, nonmax=usenonmax)point, direction, value = self.HessianMatrix(dx, dy, dxx, dyy, dxy)for point in point:self.newimage[point[1], point[0]] = 255img[point[1], point[0], :] = colorreturn img, self.newimagedef HessianMatrix(self, dx, dy, dxx, dyy, dxy, threshold=0.5):"""HessianMatrix = [dxx    dxy][dxy    dyy]compute hessian:[dxx   dxy]         [00    01]====>[dxy   dyy]         [10    11]"""point=[]direction=[]value=[]for x in range(0, self.col):for y in range(0, self.row):if dxy[y,x] > 0:hessian = np.zeros((2,2))hessian[0,0] = dxx[y,x]hessian[0,1] = dxy[y,x]hessian[1,0] = dxy[y,x]hessian[1,1] = dyy[y,x]# 计算矩阵的特征值和特征向量_, eigenvalues, eigenvectors = cv2.eigen(hessian)if np.abs(eigenvalues[0,0]) >= np.abs(eigenvalues[1,0]):nx = eigenvectors[0,0]ny = eigenvectors[0,1]else:nx = eigenvectors[1,0]ny = eigenvectors[1,1]# Taylor展开式分子分母部分,需要避免为0的情况Taylor_numer = (dx[y, x] * nx + dy[y, x] * ny)Taylor_denom = dxx[y,x]*nx*nx + dyy[y,x]*ny*ny + 2*dxy[y,x]*nx*nyif Taylor_denom != 0:T = -(Taylor_numer/Taylor_denom)# Hessian矩阵最大特征值对应的特征向量对应于光条的法线方向if np.abs(T*nx) <= threshold and np.abs(T*ny) <= threshold:point.append((x,y))direction.append((nx,ny))value.append(np.abs(dxy[y,x]+dxy[y,x]))return point, direction, valuedef threshold(mask, std=127.5):"""阈值法"""mask[mask > std] = 255mask[mask < std] = 0return mask.astype("uint8")def Bessel(xi: list):"""贝塞尔公式"""xi_array = np.array(xi)x_average = np.mean(xi_array)squared_diff = (xi_array - x_average) ** 2variance = squared_diff / (len(xi)-1)bessel = np.sqrt(variance)return besseldef test_Steger():img = cv2.imread(r"D:\PythonProject\net\line\data\Image_20230215160728679.jpg")gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)gray_img = threshold(gray_img)steger = Steger(gray_img)img,newimage=steger.centerline(img,sigmaX=1.1,sigmaY=1.1,method="Sobel")# point, direction, value = HessianMatrix(gray_img, 1.1, 1.1, usenonmax=True)cv2.imwrite("result/main3.png", newimage)cv2.imwrite("result/main3_img.png", img)def test_derivation_methods_time():from pyzjr.dlearn import Runcodesimg = cv2.imread(r"D:\PythonProject\net\line\data\Image_20230215160728411.jpg")img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)with Runcodes(description="Filter"):print(derivation(gray_img,1.1,1.1,"Filter"))# Filter: 0.01344 secwith Runcodes(description="Scharr"):print(derivation(gray_img, 1.1, 1.1))# Scharr: 0.00959 secwith Runcodes(description="Sobel"):print(derivation(gray_img, 1.1, 1.1,"Sobel"))# Sobel: 0.01820 secif __name__=="__main__":# test_derivation_methods_time()test_Steger()

我目前也没有弄明白为什么会出现三条线,似乎是中心线和轮廓,后续如果有改进会再次的更新

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

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

相关文章

鸡尾酒学习——薄荷夏日

1、材料&#xff1a;冰块&#xff08;或者雪莲&#xff09;、牛奶、朗姆酒、绿薄荷糖浆&#xff1b; 2、口感&#xff1a;有点像是再吃薄荷奶糖口味的酒心奶糖。 3、视觉效果&#xff1a;白色加上一点点绿色&#xff1b; 4、步骤&#xff1a; &#xff08;1&#xff09;向摇壶内…

【java学习—十】异常(1)

文章目录 1. 概念1.1. 前言1.2. java中的异常 2. java运行时异常举例3. 总结 1. 概念 1.1. 前言 任何一种程序设计语言设计的程序在运行时都有可能出现错误&#xff0c;例如除数为 0 &#xff0c;数组下标越界&#xff0c;要读写的文件不存在等等。     捕获错误最理想的是…

AWTK 液体流动效果控件发布

液体流动效果控件。 主要特色&#xff1a; 支持水平和垂直方向。支持正向和反向流动。支持设置头尾的图片。支持设置流动的图片。支持设置速度的快慢。支持启停操作。 准备 获取 awtk 并编译 git clone https://github.com/zlgopen/awtk.git cd awtk; scons; cd -运行 生成…

不一样的网络协议-------KCP协议

1、kcp 的协议特点 1.1、RTO 不翻倍 RTO(Retransmission TimeOut)&#xff0c;重传超时时间。tcp x 2&#xff0c;kcp x 1.5&#xff0c;提高传输速度 1.2、选择重传 TCP丢包时会全部重传从该包开始以后的数据&#xff0c;而KCP选择性重传&#xff0c;只重传真正丢失的数据包…

2-多媒体数据压缩国际标准

文章目录 多媒体数据压缩编码的重要性和分类为什么要压缩?计算: 未压缩音频的数据率简答: 环绕声系统-作业题9(简述7.4.3全景声)计算: 未压缩图像的数据量-作业题10(估计尺寸及容量)计算: 未压缩视频的数据率 为什么能压缩?数据压缩编码的两大类无损压缩算法: LZ77-作业题6-(…

《动手学深度学习 Pytorch版》 10.3 注意力评分函数

上一节使用的高斯核的指数部分可以视为注意力评分函数&#xff08;attention scoring function&#xff09;&#xff0c;简称评分函数&#xff08;scoring function&#xff09;。 后续把评分函数的输出结果输入到softmax函数中进行运算。最后&#xff0c;注意力汇聚的输出就是…

表的约束【MySQL】

文章目录 什么是约束DEFAULT&#xff08;默认约束&#xff09;NULL 与 NOT NULL&#xff08;非空约束&#xff09;COMMENT&#xff08;注释约束&#xff09;ZEROFILL&#xff08;零填充约束&#xff09;UNIQUE&#xff08;唯一键约束&#xff09;*PRIMARY KEY&#xff08;主键约…

Linux常用命令——chown命令

在线Linux命令查询工具 chown 用来变更文件或目录的拥有者或所属群组 补充说明 chown命令改变某个文件或目录的所有者和所属的组&#xff0c;该命令可以向某个用户授权&#xff0c;使该用户变成指定文件的所有者或者改变文件所属的组。用户可以是用户或者是用户D&#xff0…

Vuex模块化(modules)与namespaced(命名空间)的搭配

Vuex模块化&#xff08;modules&#xff09;与namespaced&#xff08;命名空间&#xff09;的搭配 Vuex模块化&#xff08;modules&#xff09;格式 原理&#xff1a;可以对Vuex的actions&#xff0c;mutations&#xff0c;state&#xff0c;getters四个属性综合成一个部分&a…

对Happens-Before的理解

Happens-Before Happens-Before 是一种可见性模型&#xff0c;也就是说&#xff0c;在多线程环境下。原本因为指令重排序的存在会导致数据的可见性问题&#xff0c;也就是 A 线程修改某个共享变量对 B 线程不可见。因此&#xff0c;JMM 通过 Happens-Before 关系向开发人员提供…

2023年香水行业数据分析:国人用香需求升级,高端香水高速增长

在人口结构变迁的背景下&#xff0c;“Z世代”作为当下我国的消费主力&#xff0c;正在将“悦己”消费推动成为新潮流。具备经济基础的“Z世代”倡导“高颜值”、“个性化”、“精致主义”&#xff0c;这和香水、香氛为代表的“嗅觉经济”的特性充分契合&#xff0c;因此&#…

【Docker从入门到入土 6】Consul详解+Docker https安全认证(附证书申请方式)

Part 6 一、服务注册与发现的概念1.1 cmp问题1.2 服务注册与发现 二、Consul ----- 服务自动发现和注册2.1 简介2.2 为什么要用consul&#xff1f;2.3 consul的架构2.3 Consul-template 三、consul架构部署3.1 Consul服务器Step1 建立 Consul 服务Step2 查看集群信息Step3 通过…

Flutter笔记:完全基于Flutter绘图技术绘制一个精美的Dash图标(中)

Flutter笔记 完全基于Flutter绘图技术绘制一个精美的Dart语言吉祥物Dash&#xff08;中&#xff09; 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://…

Android framework服务命令行工具框架 - Android13

Android framework服务命令行工具框架 - Android13 1、framework服务命令行工具简介2、cmd 执行程序2.1 目录和Android.bp2.2 cmdMain 执行入口2.3 cmd命令 3、am命令工具&#xff0c;实质脚本执行cmd activity3.1 sh脚本3.2 activity服务注册3.3 onShellCommand执行 4、简易时…

《从零开始大模型开发与微调 :基于PyTorch与ChatGLM》简介

内 容 简 介 大模型是深度学习自然语言处理皇冠上的一颗明珠&#xff0c;也是当前AI和NLP研究与产业中最重要的方向之一。本书使用PyTorch 2.0作为学习大模型的基本框架&#xff0c;以ChatGLM为例详细讲解大模型的基本理论、算法、程序实现、应用实战以及微调技术&#xff0c;…

Chapter1:C++概述

此专栏为移动机器人知识体系的 C {\rm C} C基础&#xff0c;基于《深入浅出 C {\rm C} C》(马晓锐)的笔记&#xff0c; g i t e e {\rm gitee} gitee链接: 移动机器人知识体系. 1.C概述 1.1 C概述 计算机系统分为硬件系统和软件系统。 硬件系统&#xff1a;指组成计算机的电子…

通过阿里云创建accessKeyId和accessKeySecret

我们想实现服务端向个人发送短信验证码 需要通过accessKeyId和accessKeySecret 这里可以白嫖阿里云的 这里 我们先访问阿里云官网 阿里云地址 进入后搜索并进入短信服务 如果没登录 就 登录一下先 然后在搜索框搜索短信服务 点击进入 因为我也是第一次操作 我们一起点免费开…

2017年上半年上午易错题(软件设计师考试)

CPU 执行算术运算或者逻辑运算时&#xff0c;常将源操作数和结果暂存在&#xff08; &#xff09;中。 A &#xff0e; 程序计数器 (PC) B. 累加器 (AC) C. 指令寄存器 (IR) D. 地址寄存器 (AR) 某系统由下图所示的冗余部件构成。若每个部件的千小时可靠度都为 R &…

深度学习之基于YoloV8的行人跌倒目标检测系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、行人跌倒目标检测系统四. 总结 一项目简介 世界老龄化趋势日益严重&#xff0c;现代化的生活习惯又使得大多数老人独居&#xff0c;统计数据表…

美术如何创建 skybox 贴图资源?

文章目录 目的PS手绘Panorama To CubemapPS手绘Pano2VRSkybox & Cubemap Tutorial (Maya & Photoshop)Unity 中使用 ReflectionProbe 生成 Cubemap 然后再 PS 调整PS直接手绘 cubemapBlender 导入 Panorama&#xff0c;然后烘焙到 cubemap&#xff0c;再导入unity中使用…