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 np

def _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, dxy

def _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, dxy

def _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, dxy

if __name__=="__main__":
    from pyzjr.dlearn import Runcodes
    sigmaX, sigmaY = 1.1, 1.1

    img = 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.pi
    return mag, phase

def 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, dxy

def 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] += 360
            if ((j+1) < gmax.shape[1]) and ((j-1) >= 0) and ((i+1) < gmax.shape[0]) and ((i-1) >= 0):
                # 0 degrees
                if (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 degrees
                if (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 degrees
                if (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 degrees
                if (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*ny
                if 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]] = 255
        img[point[1], point[0], :] = color

    return img, self.newimage

代码以及效果展示

import cv2
import numpy as np

def _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, dxy

def _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, dxy

def _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, dxy

def Magnitudefield(dxx, dyy):
    """计算幅度和相位"""
    dxx = dxx.astype(float)
    dyy = dyy.astype(float)
    mag = cv2.magnitude(dxx, dyy)
    phase = mag*180./np.pi
    return mag, phase

def 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, dxy

def 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] += 360
            if ((j+1) < gmax.shape[1]) and ((j-1) >= 0) and ((i+1) < gmax.shape[0]) and ((i-1) >= 0):
                # 0 degrees
                if (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 degrees
                if (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 degrees
                if (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 degrees
                if (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


class Steger():
    def __init__(self, gray_image):
        self.gray_image = gray_image
        self.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]] = 255
            img[point[1], point[0], :] = color
    
        return img, self.newimage

    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*ny
                    if 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


def threshold(mask, std=127.5):
    """阈值法"""
    mask[mask > std] = 255
    mask[mask < std] = 0
    return mask.astype("uint8")

def Bessel(xi: list):
    """贝塞尔公式"""
    xi_array = np.array(xi)
    x_average = np.mean(xi_array)
    squared_diff = (xi_array - x_average) ** 2
    variance = squared_diff / (len(xi)-1)
    bessel = np.sqrt(variance)

    return bessel

def 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 Runcodes
    img = 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 sec

    with Runcodes(description="Scharr"):
        print(derivation(gray_img, 1.1, 1.1))
        # Scharr: 0.00959 sec

    with Runcodes(description="Sobel"):
        print(derivation(gray_img, 1.1, 1.1,"Sobel"))
        # Sobel: 0.01820 sec



if __name__=="__main__":
    # test_derivation_methods_time()
    test_Steger()

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Flutter】自定义分段选择器Slider

【Flutter】ZFJ自定义分段选择器Slider 前言 在开发一个APP的时候&#xff0c;需要用到一个分段选择器&#xff0c;系统的不满足就自己自定义了一个&#xff1b; 可以自定义节点的数量、自定义节点的大小、自定义滑竿的粗细&#xff0c;自定义气泡的有无等等… 基本上满足你…

Springboot的Container Images,docker加springboot

Spring Boot应用程序可以使用Dockerfiles容器化&#xff0c;或者使用Cloud Native Buildpacks来创建优化的docker兼容的容器映像&#xff0c;您可以在任何地方运行。 1. Efficient Container Images 很容易将Spring Boot fat jar打包为docker映像。然而&#xff0c;像在docke…

合肥中科深谷嵌入式项目实战——人工智能与机械臂(三)

订阅&#xff1a;新手可以订阅我的其他专栏。免费阶段订阅量1000 python项目实战 Python编程基础教程系列&#xff08;零基础小白搬砖逆袭) 作者&#xff1a;爱吃饼干的小白鼠。Python领域优质创作者&#xff0c;2022年度博客新星top100入围&#xff0c;荣获多家平台专家称号。…

信号去噪之卡尔曼滤波

在前面的文章 卡尔曼滤波 中曾讲解过卡尔曼滤波在惯性导航和飞行姿态控制中的应用&#xff0c;今天来聊一聊卡尔曼滤波在信号去噪中的应用。 卡尔曼滤波&#xff08;Kalman Filtering&#xff09;是一种用于估计系统状态的数学方法&#xff0c;它通过考虑系统的动态模型和传感…

86 最小栈

最小栈 题解1 STL大法好题解2 辅助最小栈&#xff08;直观&#xff0c;空间换时间&#xff09;题解3 不需要额外空间(!!!差值!!!) 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初…

树莓派 qt 调用multimedia、multimediawidgets、serialport、Qchats

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、测试11.命令安装出现错误 二、测试21. 安装 Qt Charts&#xff1a;2. 安装 Qt Multimedia 和 Qt MultimediaWidgets&#xff1a;3. 安装 Qt SerialPort&…

重磅新闻-国内首家八类网线认证分析仪上市了

伴随USA对国内某些敏感企业的非常不友好&#xff0c;设置层层障碍&#xff0c;技术堡垒。使得一些网线基础制造研发、线缆线束厂、汽车生产生产厂、军工用途的线缆品质的认证、以及相关高校的研发受到了不同的程度的阻碍。重磅消息&#xff0c;国内首家八类网线认证测仪-维信仪…

几个常用的nosql数据库的操作方式

dynamoDB 键 partition key&#xff1a;分区键 定义&#xff1a;分区键是用于分布数据存储的主键&#xff0c;每个项&#xff08;Item&#xff09;在表中都必须有一个唯一的分区键值。 特点&#xff1a; 唯一性&#xff1a;每个分区键值在表中必须是唯一的&#xff0c;这是因为…

【Java 进阶篇】Java HTTP 请求消息详解

HTTP&#xff08;Hypertext Transfer Protocol&#xff09;是一种用于传输超文本的应用层协议&#xff0c;广泛用于构建互联网应用。在Java中&#xff0c;我们经常需要发送HTTP请求来与远程服务器进行通信。本文将详细介绍Java中HTTP请求消息的各个部分&#xff0c;包括请求行、…

基于纵横交叉算法的无人机航迹规划-附代码

基于纵横交叉算法的无人机航迹规划 文章目录 基于纵横交叉算法的无人机航迹规划1.纵横交叉搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用纵横交叉算法来优化无人机航迹规划。 …

vscode 通过ssh 连接虚拟机vmware(ubuntu)

1.网络连接是否ping的通&#xff08;ubuntu虚拟机使用的是net 连接方式&#xff09; 2.配置环境 ubuntu 需要安装ssh server 服务 &#xff08;1&#xff09;&#xff1a; 安装&#xff08;Ubuntu安装ssh server) apt-get install openssh-server 检查是否ssh server 是否启动…

PostMan 之 Mock 接口测试

在测试的时候经常会碰到后端开发工程师的接口还没有开发完成&#xff0c;但是测试任务已经分配过来。没有接口怎么测试呢&#xff1f; 测试人员可以通过 mock server 自己去造一个接口来访问。mock server 可用于模拟真实的接口。收到请求时&#xff0c;它会根据配置返回对应的…

图解Kafka高性能之谜(五)

高性能的多分区、冗余副本集群架构 高性能网络模型NIO 简单架构设计&#xff1a; 详细架构设计&#xff1a; 高性能的磁盘写技术 高性能的消息查找设计 索引文件定位使用跳表的设计 偏移量定位消息时使用稀疏索引&#xff1a; 高响应的磁盘拷贝技术 kafka采用sendFile()的…

Linux:KVM虚拟化

本章操作基于centos7系统 简介 KVM是Kernel Virtual Machine的简写&#xff0c;目前Redhat只支持在64位的Rhel5.4以上的系统运行KVM&#xff0c;同时硬件需要支持VT技术。KVM的前身是QEMU&#xff0c;在2008年被redhat公司收购并获得了一项hypervisor技术&#xff0c;不过redh…

一文浅析Instagram网红经济为什么远远超出其他社媒平台

根据数据显示&#xff0c;网红营销市场规模在短短五年时间内从2016年的17亿美元增长至2022年的164亿美元&#xff0c;累计增速超过了712%。未来&#xff0c;有专家预计该市场预计将进一步增长&#xff0c;将在2023年突破210亿美元。这种惊人的增长趋势源于社交媒体的快速发展以…

SpringBoot整合Gateway 的Demo(附源码)

源码&#xff0c;可直接下载 Gateway模块 Gateway 的父pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:sc…

【图像分类】基于计算机视觉的坑洼道路检测和识别(ResNet网络,附代码和数据集)

写在前面: 首先感谢兄弟们的关注和订阅,让我有创作的动力,在创作过程我会尽最大能力,保证作品的质量,如果有问题,可以私信我,让我们携手共进,共创辉煌。 本篇博文,我们将使用PyTorch深度学习框架搭建ResNet实现钢轨缺陷识别,附完整的项目代码和数据集,可以说是全网…

基于单片机的智能清洁小车设计—控制系统设计

收藏和点赞&#xff0c;您的关注是我创作的动力 文章目录 概要 一、研究的主要内容和目标二、总体方案设计2.1智能清洁小车的硬件系统组成2.2智能清洁小车的硬件结构图 三、 小车结构设计5.1基本布局和功能分析5.2小车二维及三维图小车三维图&#xff1a; 四、 原理图程序 五、…

JAVA反射机制及动态代理

反射机制 反射机制是什么 1、Java反射机制的核心是在程序运行时动态加载类并获取类的详细信息&#xff0c;从而操作类或对象的属性和方法。本质是JVM得到class对象之后&#xff0c; 再通过class对象进行反编译&#xff0c;从而获取对象的各种信息。 2、Java属于先编译再运行的…

gurobi 安装/license激活 记录

前言&#xff1a;花了好久&#xff0c;被嫌弃惹ww&#xff0c;记录一下踩过的坑 至于为何没安装gurobi也能跑一段时间&#xff0c;直到显示需要license激活&#xff0c;还是未解之迷&#xff0c;需要教教。 首先这是官方给的gurobi license激活教程 我们一步步来复现吧&#…
最新文章