目标跟踪算法中的卡尔曼滤波学习

在使用多目标跟踪算法时,接触到卡尔曼滤波,一直没时间总结下,现在来填坑。

1. 背景知识

在理解卡尔曼滤波前,有几个概念值得考虑下:时序序列模型,滤波,线性动态系统

1. 时间序列模型

时间序列模型都可以用如下示意图表示:

这个模型包含两个序列,一个是黄色部分的状态序列,用X表示,一个是绿色部分的观测序列(又叫测量序列、证据序列、观察序列,不同的书籍有不同的叫法,在这里统一叫观测序列。)用Y表示。状态序列反应了系统的真实状态,一般不能被直接观测,即使被直接观测也会引进噪声;观测序列是通过测量得到的数据,它与状态序列之间有规律性的联系。

上面序列中,假设初始时间为t1t1, 则X1,Y1X1,Y1是t1t1时刻的状态值和观测值,X2,Y2X2,Y2是t2t2时刻的状态值和观测值…,即随着时间的流逝,序列从左向右逐渐展开。

常见的时间序列模型主要包括三个:隐尔马尔科夫模型,卡尔曼滤波,粒子滤波

2. 滤波

时间序列模型中包括预测和滤波两步

  • 预测:指用当前和过去的数据来求取未来的数据。对应上述序列图中,则是利用t1t1时刻X1,Y1X1,Y1的值,估计t2t2时刻X2X2值。
  • 滤波:是用当前和过去的数据来求取当前的数据。对应上述序列图中,则是先通过上一步的预测步骤得到X2X2的一个预测值,再利用t2t2时刻Y2Y2的值对这个预测值进行纠正,得到最终的X2X2估计值。(通俗讲,就是通过X1X1预测一个值, 通过传感器测量一个值Y2Y2, 将两者进行融合得到最终的X2X2值)

3.线性动态系统

卡尔曼滤波又称为基于高斯过程的线性动态系统(Linear Dynamic System, LDS) , 这里的高斯是指:状态变量XtXt和观测变量YtYt都符合高斯分布;这里的线性是指:XtXt可以通过Xt−1Xt−1线性表示,YtYt可以通过XtXt线性表示;如果用数学表达式来表达这两层含义如下:

Xt=FXt−1+wt−1,wt−1∼N(0,Q)Xt=FXt−1+wt−1,wt−1∼N(0,Q)

上面表达式中F是一个矩阵,常称作状态转移矩阵,保证了XtXt和Xt−1Xt−1的线性关系(线性代数中,矩阵就是线性变换);wt−1wt−1常称作噪声,其服从均值为0,方差为Q的高斯分布,保证了XtXt服从高斯分布(因为高斯分布加上一个常数后依然是高斯分布)。

同样的关于XtXt和YtYt,也可以得到如下表示, 其中矩阵H称作状态空间到观测空间的映射矩阵, rtrt称作噪声,其服从高斯分布:

Yt=HXt+rt,(rt∼N(0,R))Yt=HXt+rt,(rt∼N(0,R))

参考:https://zhuanlan.zhihu.com/p/139215491

2. 卡尔曼滤波理论知识

关于卡尔曼滤波的理论知识有很多文章讲的很好,参考下面的两个链接

https://zhuanlan.zhihu.com/p/25598462

http://www.bzarg.com/p/how-a-kalman-filter-works-in-pictures/#mjx-eqn-gaussequiv

这里简单总结下用得到数学表达式,方便实际编程时查阅和理解:

2.1 状态序列的预测

在时间序列模型图中,这一步表示的是, 在预测序列中,从Xt−1Xt−1到XtXt的预测步骤。

需要用到的变量含义如下:

  • xkxk:状态变量
  • PkPk: 状态变量的协方差矩阵
  • FkFk:状态转移矩阵
  • BkBk:控制矩阵
  • μkμk:控制向量
  • wkwk: 状态变量的噪声矩阵
  • QkQk:协方差矩阵的噪声矩阵

数学表达式如下:

xk=Fkxk−1+Bk→μk+wkPk=FkPk−1FTk+Qkxk=Fkxk−1+Bkμ→k+wkPk=FkPk−1FkT+Qk

2.2 状态序列到观测序列的转换

在时间序列模型图中,这一步表示的是, 从XtXt到YtYt的转换。

需要用到的变量含义如下:

  • HkHk:状态空间到测量空间的映射矩阵
  • xkxk: tktk时刻的状态变量
  • PkPk: tktk时刻状态变量的协方差矩阵

映射后变量的均值和方差如下:

→μexpected=HkxkΣexpected=HkPkHTkμ→expected=HkxkΣexpected=HkPkHkT

2.3 测量序列的滤波

在时间序列模型图中,这一步表示的是,测量值YtYt对预测值XtXt进行纠正,得到最终的状态向量XtXt

观测向量服从高斯分布, 假设其均值和协方差矩阵如下:

观测向量均值:→μmeasurement=→zk观测向量协方差矩阵:Σmeasurement=Rk观测向量均值:μ→measurement=z→k观测向量协方差矩阵:Σmeasurement=Rk

我们已经得到了状态序列的预测值,而且将其映射到了测量序列,也得到了测量序列的测量值,接来要做的就是将两者进行融合,由于两者都符合高斯分布,其融合过程就是两个高斯分布的混合

1. 高斯混合

单变量高斯分布方程:

N(x,μ,σ)=1σ√2πe−(x−μ)22σ2N(x,μ0,σ0)⋅N(x,μ1,σ1)?=N(x,μ′,σ′)(1)(1)N(x,μ,σ)=1σ2πe−(x−μ)22σ2N(x,μ0,σ0)⋅N(x,μ1,σ1)=?N(x,μ′,σ′)

两个单变量高斯分布混合:

μ′=μ0+k(μ1−μ0)σ′2=kσ12=σ02(1−k)其中,k=σ20σ20+σ21μ′=μ0+k(μ1−μ0)σ′2=kσ12=σ02(1−k)其中,k=σ02σ02+σ12

以上是单变量概率密度函数的计算结果,如果是多变量的,那么,就变成了协方差矩阵的形式:

K=Σ0(Σ0+Σ1)−1→μ′=→μ0+K(→μ1−→μ0)Σ′=KΣ1=Σ0(I−K)K=Σ0(Σ0+Σ1)−1μ→′=μ→0+K(μ→1−μ→0)Σ′=KΣ1=Σ0(I−K)

2. 预测值和测量值混合

预测值和测量值的均值和协方差如下:

预测值高斯分布:(μ0,Σ0)=(Hkxk,HkPkHTk)测量值高斯分布:(μ1,Σ1)=(zk,Rk)预测值高斯分布:(μ0,Σ0)=(Hkxk,HkPkHkT)测量值高斯分布:(μ1,Σ1)=(zk,Rk)

预测值和测量值混合:

Hkx′k=Hkxk+K(→zk−Hkxk)HkP′kHTk=HkPkHTk−KHkPkHTk其中,K称作卡尔曼增益:K=HkPkHTk(HkPkHTk+Rk)−1Hkxk′=Hkxk+K(zk→−Hkxk)HkPk′HkT=HkPkHkT−KHkPkHkT其中,K称作卡尔曼增益:K=HkPkHkT(HkPkHkT+Rk)−1

化简上述表达式,计算x′k,P′kxk′,Pk′,结果如下:(x′kxk′就是第k次卡尔曼预测结果, P′kPk′是该结果的协方差矩阵)

x′k=xk+K′(→zk−Hkxk)P′k=Pk−K′HkPkK′=PkHTk(HkPkHTk+Rk)−1xk′=xk+K′(zk→−Hkxk)Pk′=Pk−K′HkPkK′=PkHkT(HkPkHkT+Rk)−1

最终,可以卡尔曼滤波流程图如下:

参考:https://zhuanlan.zhihu.com/p/142044672
https://zhuanlan.zhihu.com/p/158751412
https://zhuanlan.zhihu.com/p/58675854
https://leijiezhang001.github.io/卡尔曼滤波详解/
https://zhuanlan.zhihu.com/p/166342719

3. 卡尔曼滤波用于目标跟踪

对于一个小车,我们采用卡尔曼滤波来估计其位置,在进行估计的时候,有几个变量要进行定义和初始化。这里定义了六个变量的初始值:状态向量,状态向量协方差矩阵,状态向量协方差矩阵的噪声矩阵,动态转移矩阵,映射矩阵,测量值的协方差矩阵(假设小车是匀速运动,所以没有使用控制矩阵和控制变量)

1. 初始状态向量xx:(8x1的矩阵)

[xyahvxvyvavh]T[xyahvxvyvavh]T

其中对应含义和初始化值如下:

  • (x,y)表示目标的中心点,a=w/h表示目标的宽高比,h表示目标的高度,初始化值为目标第一帧的位置
  • v_x, v_y, v_a, v_h:表示对应变量随时间的变化率, 初始化值为0

2. 状态向量初始协方差矩阵PP:(8*8的矩阵, 这里如何设置,需要经验?)

⎡⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢⎣151.2900000000151.29000000000.000100000000151.290000000059.090000000059.09000000000.000010000000059.09⎤⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥⎦[151.2900000000151.29000000000.000100000000151.290000000059.090000000059.09000000000.000010000000059.09]

3.状态向量协方差矩阵的噪声矩阵QQ:(8*8的矩阵, 这里如何设置,需要经验?)

⎡⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢⎣37.820000000037.82000000000.00010000000037.82000000000.59000000000.59000000000.00001000000000.59⎤⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥⎦[37.820000000037.82000000000.00010000000037.82000000000.59000000000.59000000000.00001000000000.59]

4. 动态转移矩阵F:(8x8的矩阵)

⎡⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢ ⎢⎣1000100001000100001000100001000100001000000001000000001000000001⎤⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥ ⎥⎦[1000100001000100001000100001000100001000000001000000001000000001]

5. 映射矩阵H:(4x8的矩阵)

⎡⎢ ⎢ ⎢⎣10000000010000000010000000010000⎤⎥ ⎥ ⎥⎦[10000000010000000010000000010000]

6. 测量值的协方差矩阵RR:(4x4的矩阵, 这里如何设置,需要经验?)

⎡⎢ ⎢ ⎢⎣37.82000037.8200000.0001000037.82⎤⎥ ⎥ ⎥⎦[37.82000037.8200000.0001000037.82]

下面代码中,采用卡尔曼滤波,对小车的随机运动进行了估计,结果如图所示,绿色框表示小车的真实位置,红色框表示卡尔曼滤波的估计位置

# vim: expandtab:ts=4:sw=4
import numpy as np
import scipy.linalg
import cv2

"""
Table for the 0.95 quantile of the chi-square distribution with N degrees of
freedom (contains values for N=1, ..., 9). Taken from MATLAB/Octave's chi2inv
function and used as Mahalanobis gating threshold.
"""
chi2inv95 = {
    1: 3.8415,
    2: 5.9915,
    3: 7.8147,
    4: 9.4877,
    5: 11.070,
    6: 12.592,
    7: 14.067,
    8: 15.507,
    9: 16.919}


class KalmanFilter(object):
    """
    A simple Kalman filter for tracking bounding boxes in image space.

    The 8-dimensional state space

        x, y, a, h, vx, vy, va, vh

    contains the bounding box center position (x, y), aspect ratio a, height h,
    and their respective velocities.

    Object motion follows a constant velocity model. The bounding box location
    (x, y, a, h) is taken as direct observation of the state space (linear
    observation model).

    """

    def __init__(self):
        ndim, dt = 4, 1.

        # Create Kalman filter model matrices.
        self._motion_mat = np.eye(2 * ndim, 2 * ndim)  # 初始化动态转移矩阵, shape(8, 8)
        for i in range(ndim):
            self._motion_mat[i, ndim + i] = dt
        self._update_mat = np.eye(ndim, 2 * ndim)   # 初始化映射矩阵,shape(4, 8)

        # Motion and observation uncertainty are chosen relative to the current
        # state estimate. These weights control the amount of uncertainty in
        # the model. This is a bit hacky.
        self._std_weight_position = 1. / 20
        self._std_weight_velocity = 1. / 160

    def initiate(self, measurement):
        """Create track from unassociated measurement.

        Parameters
        ----------
        measurement : ndarray
            Bounding box coordinates (x, y, a, h) with center position (x, y),
            aspect ratio a, and height h.

        Returns
        -------
        (ndarray, ndarray)
            Returns the mean vector (8 dimensional) and covariance matrix (8x8
            dimensional) of the new track. Unobserved velocities are initialized
            to 0 mean.

        """
        mean_pos = measurement
        mean_vel = np.zeros_like(mean_pos)
        mean = np.r_[mean_pos, mean_vel]   # 状态向量,shape(1, 8)

        std = [
            2 * self._std_weight_position * measurement[3],
            2 * self._std_weight_position * measurement[3],
            1e-2,
            2 * self._std_weight_position * measurement[3],
            10 * self._std_weight_velocity * measurement[3],
            10 * self._std_weight_velocity * measurement[3],
            1e-5,
            10 * self._std_weight_velocity * measurement[3]]
        covariance = np.diag(np.square(std))    # 状态向量协方差矩阵, shape(8, 8)
        return mean, covariance

    def predict(self, mean, covariance):
        """Run Kalman filter prediction step.

        Parameters
        ----------
        mean : ndarray
            The 8 dimensional mean vector of the object state at the previous
            time step.
        covariance : ndarray
            The 8x8 dimensional covariance matrix of the object state at the
            previous time step.

        Returns
        -------
        (ndarray, ndarray)
            Returns the mean vector and covariance matrix of the predicted
            state. Unobserved velocities are initialized to 0 mean.

        """
        std_pos = [
            self._std_weight_position * mean[3],
            self._std_weight_position * mean[3],
            1e-2,
            self._std_weight_position * mean[3]]
        std_vel = [
            self._std_weight_velocity * mean[3],
            self._std_weight_velocity * mean[3],
            1e-5,
            self._std_weight_velocity * mean[3]]
        motion_cov = np.diag(np.square(np.r_[std_pos, std_vel]))

        mean = np.dot(self._motion_mat, mean)  # 动态转移矩阵*状态向量
        covariance = np.linalg.multi_dot((
            self._motion_mat, covariance, self._motion_mat.T)) + motion_cov   # 动态转移矩阵*状态向量协方差矩阵 + 噪声矩阵

        return mean, covariance

    def project(self, mean, covariance):
        """Project state distribution to measurement space.

        Parameters
        ----------
        mean : ndarray
            The state's mean vector (8 dimensional array).
        covariance : ndarray
            The state's covariance matrix (8x8 dimensional).

        Returns
        -------
        (ndarray, ndarray)
            Returns the projected mean and covariance matrix of the given state
            estimate.

        """
        std = [
            self._std_weight_position * mean[3],
            self._std_weight_position * mean[3],
            1e-1,
            self._std_weight_position * mean[3]]
        innovation_cov = np.diag(np.square(std))

        mean = np.dot(self._update_mat, mean)   # 映射矩阵*状态向量
        covariance = np.linalg.multi_dot((
            self._update_mat, covariance, self._update_mat.T))
        return mean, covariance + innovation_cov         # 映射矩阵*状态向量 + 噪声矩阵

    def update(self, mean, covariance, measurement):
        """Run Kalman filter correction step.

        Parameters
        ----------
        mean : ndarray
            The predicted state's mean vector (8 dimensional).
        covariance : ndarray
            The state's covariance matrix (8x8 dimensional).
        measurement : ndarray
            The 4 dimensional measurement vector (x, y, a, h), where (x, y)
            is the center position, a the aspect ratio, and h the height of the
            bounding box.

        Returns
        -------
        (ndarray, ndarray)
            Returns the measurement-corrected state distribution.

        """
        projected_mean, projected_cov = self.project(mean, covariance)

        chol_factor, lower = scipy.linalg.cho_factor(
            projected_cov, lower=True, check_finite=False)    # Cholesky分解
        kalman_gain = scipy.linalg.cho_solve(
            (chol_factor, lower), np.dot(covariance, self._update_mat.T).T,
            check_finite=False).T                             # 求解卡尔曼增益矩阵
        innovation = measurement - projected_mean

        new_mean = mean + np.dot(innovation, kalman_gain.T)    # 预测值和测量值融合后,新的状态向量
        new_covariance = covariance - np.linalg.multi_dot((
            kalman_gain, projected_cov, kalman_gain.T))        # 预测值和测量值融合后,新状态向量的协方差矩阵
        return new_mean, new_covariance

    def gating_distance(self, mean, covariance, measurements,
                        only_position=False):
        """Compute gating distance between state distribution and measurements.

        A suitable distance threshold can be obtained from `chi2inv95`. If
        `only_position` is False, the chi-square distribution has 4 degrees of
        freedom, otherwise 2.

        Parameters
        ----------
        mean : ndarray
            Mean vector over the state distribution (8 dimensional).
        covariance : ndarray
            Covariance of the state distribution (8x8 dimensional).
        measurements : ndarray
            An Nx4 dimensional matrix of N measurements, each in
            format (x, y, a, h) where (x, y) is the bounding box center
            position, a the aspect ratio, and h the height.
        only_position : Optional[bool]
            If True, distance computation is done with respect to the bounding
            box center position only.

        Returns
        -------
        ndarray
            Returns an array of length N, where the i-th element contains the
            squared Mahalanobis distance between (mean, covariance) and
            `measurements[i]`.

        """
        mean, covariance = self.project(mean, covariance)
        if only_position:
            mean, covariance = mean[:2], covariance[:2, :2]
            measurements = measurements[:, :2]

        cholesky_factor = np.linalg.cholesky(covariance)
        d = measurements - mean
        z = scipy.linalg.solve_triangular(
            cholesky_factor, d.T, lower=True, check_finite=False,
            overwrite_b=True)
        squared_maha = np.sum(z * z, axis=0)
        return squared_maha

if __name__ == "__main__":
    kf = KalmanFilter()
    img = cv2.imread("./car.png")
    m = np.array([108.5, 360.5, 1.618, 123])   # 小车的初始化测量值,分别表示小车的x_center, y_center, w/h, h
    mean_ini, covariance_ini = kf.initiate(m)  # 初始化卡尔曼的动态转移矩阵,映射矩阵



    for i in range(30):
        mean_pre, covariance_pre = kf.predict(mean_ini, covariance_ini)  # 预测状态变量
        dx = np.random.randint(0, 120)
        dy = np.random.randint(-30, 30)
        m = m + np.array([dx, dy, 0, 0])   # 随机向左,和上下移动
        cv2.rectangle(img, (int(m[0]-m[2]*m[3]/2), int(m[1]-m[3]/2)),
                      (int(m[0]+m[2]*m[3]/2), int(m[1]+m[3]/2)), (0, 255, 0), 2)  # 用绿色框,绘制小车移动后的真实位置

        mean_upd, covariance_upd = kf.update(mean_pre, covariance_pre, m+np.random.randn(4))   # 利用测量值,更新状态变量
        mean_ini = mean_upd
        covariance_ini = covariance_upd

        # 用红色框,绘制小车移动后的估计位置
        cv2.rectangle(img, (int(mean_ini[0] - mean_ini[2] * mean_ini[3] / 2), int(mean_ini[1] - mean_ini[3] / 2)),
                      (int(mean_ini[0] + mean_ini[2] * mean_ini[3] / 2), int(mean_ini[1] + mean_ini[3] / 2)), (0, 0, 255), 2)

        cv2.namedWindow("img", cv2.WINDOW_NORMAL)
        cv2.resizeWindow("img", 960, 540)
        cv2.imshow("img", img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()

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

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

相关文章

AspectJ入门(二)— 应用

AspectJ便于调试、测试和性能调整工作。定义的行为范围从简单的跟踪到分析,再到应用程序内部一致性到测试。AspectJ可以干净地模块化这类功能,从而可以在需要时轻松地启用和禁用这些功能。 1 基础 本节将继续介绍AspectJ到一些基础功能,为后…

负载均衡案例:如何只用2GB内存统计20亿个整数中出现次数最多的整数

基于python实现。 如果是常规的小型文件&#xff0c;我们可以迅速地想到要建立字典。 以数字为key&#xff0c;以数字的出现次数为value&#xff0c;建立<int,int>类型的键值对存入字典&#xff0c;然后使用 max 函数结合字典的 items 方法来找到一个字典中 value 最大的…

2023 波卡年度报告选读:Polkadot SDK 与开发者社区

原文&#xff1a;https://dashboards.data.paritytech.io/reports/2023/index.html#section6 编译&#xff1a;OneBlock 编者注&#xff1a;Parity 数据团队发布的 2023 年 Polkadot 年度数据报告&#xff0c;对推动生态系统的关键数据进行了深入分析。报告全文较长&#xff…

一键减低PNG像素,轻松优化图片质量!

在数字时代&#xff0c;我们每天都要处理大量的图片文件&#xff0c;从网站设计、广告素材到社交媒体图片等。PNG作为一种常用的无损压缩格式&#xff0c;在保证图片质量的同时&#xff0c;也占用了较大的存储空间。为了优化存储空间和提高加载速度&#xff0c;我们需要对PNG图…

数据结构学习笔记——查找算法中的树形查找(B树、B+树)

目录 前言一、B树&#xff08;一&#xff09;B树的概念&#xff08;二&#xff09;B树的性质&#xff08;三&#xff09;B树的高度&#xff08;四&#xff09;B树的查找&#xff08;五&#xff09;B树的插入&#xff08;六&#xff09;B树的删除 二、B树&#xff08;一&#xf…

科技助力教育:数字化如何改变家校社协同育人?

近年来,随着社会的快速发展,教育的责任已不再仅局限于学校。家庭、学校和社会协同育人理念,正成为促进教育高质量发展的关键要素。 2023年初,教育部等十三部门联合印发《关于健全学校家庭社会协同育人机制的意见》,提出到“十四五”时期末,形成更加完善的由“学校积极主导、家…

Excel如何将单元格设为文本

文章目录 一、打开excel文件二、选中单元格三、右键设置单元格格式四、设置界面选择文本后点确定五、其他问题 在caa开发过程中遇到从CATUnicodeString转成CString时&#xff0c;通过SetItemText写入将ID号写入单元格&#xff0c;无法保存ID号中的数字0&#xff0c;故将单元格格…

统信UOS_麒麟KYLINOS修改图标显示名称

原文链接&#xff1a;统信UOS/麒麟KYLINOS修改图标显示名称 hello&#xff0c;大家好啊&#xff01;今天我要给大家介绍的是在统信UOS及麒麟KYLINOS操作系统上如何修改软件的名称。这种自定义可以帮助您更快地识别和访问常用的应用程序&#xff0c;也可以使您的桌面环境更加个性…

【MATLAB】CEEMD_LSTM神经网络时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 CEEMD-LSTM神经网络时序预测算法是一种结合了完全扩展经验模态分解&#xff08;CEEMD&#xff09;和长短期记忆神经网络&#xff08;LSTM&#xff09;的时间序列预测方法。 CEEMD是一种改…

基于MyCat2.0实现MySQL分库分表方案

目录 一、MyCat概述 二、MyCat作用 2.1 数据分片 2.1.1 垂直拆分 2.1.1.1 垂直分库 2.1.1.2 垂直分表 2.1.1.3 总结 2.1.2 水平拆分 2.1.2.1 水平分库 2.1.2.2 水平分表 2.1.2.3 总结 2.2 读写分离 2.3 多数据源整合 三、MyCat 与ShardingJDBC的区别 3.1 MyCat …

易基因:ChIP-seq等揭示Runx2通过转录调控Itgav表达激活肝星状细胞以促进肝纤维化|科研进展

这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 肌成纤维细胞&#xff08;myofibroblasts&#xff09;主要由肝脏中活化的肝星状细胞(hepatic stellate cells HSC)组成&#xff0c;在肝纤维化进展中发挥着核心作用。由于肌成纤维细胞主要负责细胞外基质蛋…

代码随想录刷题第三十六天| 435. 无重叠区间 ● 763.划分字母区间 ● 56. 合并区间

代码随想录刷题第三十六天 无重叠区间 (LC 435) 题目思路&#xff1a; 代码实现&#xff1a; class Solution:def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int:intervals.sort(keylambda x: (x[0],x[1]))count 0right intervals[0][1]for i in ra…

拼题A 跨年挑战赛 2024 赛后提交入口 + 题目 + 题解

赛后也想提交&#xff1f;点击进入 拼题A教育超市 周三&#xff0c;搞学长&#xff1a;“小柳进前十了&#xff01;想要奖品过来拿&#xff01;” 等了好几天的比赛结果终于出来了&#xff0c;四年来的跨年挑战赛第一次做满分&#xff0c;第一次进前十&#xff01;&#xff0…

MyBatis学习二:Mapper代理开发、配置文件完成增删改查、注解开发

前言 公司要求没办法&#xff0c;前端也要了解一下后端知识&#xff0c;这里记录一下自己的学习 学习教程&#xff1a;黑马mybatis教程全套视频教程&#xff0c;2天Mybatis框架从入门到精通 文档&#xff1a; https://mybatis.net.cn/index.html Mapper代理开发 目的 解决…

【nginx】linux(centos版本)安装nginx

目录 一、下载安装包1.1 官网下载1.2 linux命令下载 二、安装2.1 安装依赖包2.2 安装nginx 三、启动四、访问五、关停六、重载配置 一、下载安装包 1.1 官网下载 1.官网地址 https://nginx.org/en/download.html2.版本说明 1.Mainline version-主线版本 2.Stable version-稳…

剪映业务的大前端实践:创新以用户需求为导向

近日&#xff0c;由51CTO主办的WOT全球技术创新大会2023深圳站成功举办&#xff0c;众多企业CTO、技术团队负责人在会场分享了优秀的技术实践。其中&#xff0c;剪映前端开发工程师赵培霏分享了主题为《剪映业务的大前端实践》的演讲。 近日&#xff0c;由51CTO主办的WOT全球技…

如何给6000微信好友打好标签? 快速操作技巧!

微信好友一多&#xff0c;管理起来就变得麻烦。要管理好好友&#xff0c;就必须要给好友打好标签。今天分享一个快速给微信好友打标签的方法。 一、微信电脑端给好友打标签的操作方法&#xff1a; 桌面端打标签速度是很快的&#xff0c;不仅仅是好操作&#xff0c;而且搜索功能…

Spark调优解析-GC调优3(七)

1 GC调优 Spark立足内存计算&#xff0c;常常需要在内存中存放大量数据&#xff0c;因此也更依赖JVM的垃圾回收机制。与此同时&#xff0c;它也兼容批处理和流式处理&#xff0c;对于程序吞吐量和延迟都有较高要求&#xff0c;因此GC参数的调优在Spark应用实践中显得尤为重要。…

2023 IoTDB Summit:清华大学软件学院长聘副教授龙明盛《IoTDB 新组件:内生机器学习》...

12 月 3 日&#xff0c;2023 IoTDB 用户大会在北京成功举行&#xff0c;收获强烈反响。本次峰会汇集了超 20 位大咖嘉宾带来工业互联网行业、技术、应用方向的精彩议题&#xff0c;多位学术泰斗、企业代表、开发者&#xff0c;深度分享了工业物联网时序数据库 IoTDB 的技术创新…

Starknet 开发实战训练营邀你挑战,1000 美元大奖等你赢取!

Starknet 免费公开课来啦&#xff01;&#x1f680; ZK L2 明星项目 Starknet 不久前透露其 STRK 空投计划引发了诸多关注&#xff0c;而全链游戏同样是今年 Web3 行业的热门领域之一&#xff0c;Starknet 便是全链游戏领域中的重要生态&#xff0c;开发者借助其链上游戏引擎 D…