当前位置: 首页 > news >正文

【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割7(数据预处理)

在上一节:【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割6(数据预处理) 中,我们已经得到了与mhd图像同seriesUID名称的mask nrrd数据文件了,可以说是一一对应了。

并且,mask的文件,还根据结节被多少人同时标注,区分成了4个文件夹,分别是标注了一、二、三、四次,一共就4个医生参与标注。

再加上官方已经给整理好的肺实质分割的文件,我们就获得了以下这些数据:

  1. ct图像数据;
  2. 肺实质分割数据;
  3. 包含结节位置的mask数据。

一、导言

上述得到的这些,就满足了我们的需求了,都是一一对应的,无论是后续的数据预处理,还是拿过来用于训练,都非常的方便。

但是呢,对于原始的ct数据,他在Z轴上的层厚是不同的,这点可以在dicom文件里面看到,也可以在mhd文件的查询到关于层厚的信息。在这点上,不同的序列,差异是非常大的。表现在一个3维数组的结节上面,在这个维度上就是被压扁,和拉长的样子。

xy方向,其实也是存在spacing的差异的,但是这种差异没有像z轴那么夸张的,这里可以选择处理和不处理均可(有些论文进行了处理,有些没有。默认都是512x512大小,resample后会变小)。

至此,本篇的目的就很明确了,是要做下面几件事:

  1. 对原始图像进行肺实质提取,将肺区外的部分进行裁剪,或者改为固定像素值;
  2. 对图像和结节mask进行resample操作,本篇是zyx均进行resample1mm

二、具体实施

怎么做的部分,我们分三部分:

  1. 肺实质裁剪
  2. imagenodule mask进行resample操作
  3. 获取结节中心点坐标和半径

下面就一一展开

2.1、主函数部分

由于这部分数据量比较多,所以在主函数部分采用了多进程的模式,加快处理速度。需要读进来的数据也就是前面篇章已经处理好的,这里都可以直接使用。

下面就是主函数

import sys
import numpy as np
import scipy.ndimage
from skimage import measure, morphology
import SimpleITK as sitk
from multiprocessing import Pool
import os
import nrrd###############################################################################
# 将标记的mask,和ct原图,加入左右肺区分割的图像,生成去除noise的,剩下肺区的ct和结节mask
###############################################################################
def main():n_consensus = 4do_resample = Trueimg_dir = './LUNA16/image_combined'lung_mask_dir = './LUNA16/seg-lungs-LUNA16'nod_mask_dir = os.path.join('./LUNA16/nodule_masks', str(n_consensus))save_dir = os.path.join('./LUNA16/preprocessed', str(n_consensus))os.makedirs(save_dir, exist_ok=True)params_lists = []# 多进程处理for pid in os.listdir(nod_mask_dir):#                         seg-lungs-LUNA16, masks_test/3, seg-lungs-LUNA16, preprocessed_test/3, Trueparams_lists.append([pid, lung_mask_dir, nod_mask_dir, img_dir, save_dir, do_resample])pool = Pool(processes=4)pool.map(cropResample_process, params_lists)pool.close()pool.join()pool = Pool(processes=4)pool.map(generateBBoxes_label, params_lists)pool.close()pool.join()if __name__ == '__main__':main()

有两个部分,

  • cropResample_process:和名称一样,进行肺实质的cropresample操作;
  • generateBBoxes_label:将处理完毕的结节mask,得到结节中心的坐标和半径。

2.2、肺实质裁剪

这小块的步骤,大概如下:

  1. 首先,就是数据读取,这部分的详细介绍,可以参考我之前的这篇文章:【医学影像数据处理】nii、npz、npy、dcm、mhd 的数据格式互转,及多目标分割处理汇总
  2. 其次,就是将hu值,转化为0-255的值,也就是函数HU2uint8(),对于这部分,可以参考hu值是如何转为0-255的可视化部分的介绍:【医学影像数据处理】 Dicom 文件格式处理汇总
  3. 另外,就是将肺区mask作用到图像上,肺实质外采用pad valud补充
  4. 最后,将处理好的image、mask和相关参数存储到本地

代码如下,就该说明的部分都进行注释,相信能轻易看懂。

def load_itk_image(filename):"""Return img array and [z,y,x]-ordered origin and spacing"""itkimage = sitk.ReadImage(filename)numpyImage = sitk.GetArrayFromImage(itkimage)numpyOrigin = np.array(list(reversed(itkimage.GetOrigin())))numpySpacing = np.array(list(reversed(itkimage.GetSpacing())))return numpyImage, numpyOrigin, numpySpacingdef HU2uint8(image, HU_min=-1200.0, HU_max=600.0, HU_nan=-2000.0):"""Convert HU unit into uint8 values. First bound HU values by predfined minand max, and then normalizeimage: 3D numpy array of raw HU values from CT series in [z, y, x] order.HU_min: float, min HU value.HU_max: float, max HU value.HU_nan: float, value for nan in the raw CT image."""image_new = np.array(image)image_new[np.isnan(image_new)] = HU_nan# normalize to [0, 1]image_new = (image_new - HU_min) / (HU_max - HU_min)image_new = np.clip(image_new, 0, 1)image_new = (image_new * 255).astype('uint8')return image_newdef convex_hull_dilate(binary_mask, dilate_factor=1.5, iterations=10):"""Replace each slice with convex hull of it then dilate. Convex hulls usedonly if it does not increase area by dilate_factor. This applies mainly tothe inferior slices because inferior surface of lungs is concave.binary_mask: 3D binary numpy array with the same shape of the image,that only region of interest is True. One side of the lung in thisspecifical case.dilate_factor: float, factor of increased area after dilationiterations: int, number of iterations for dilationreturn: 3D binary numpy array with the same shape of the image,that only region of interest is True. Each binary mask is ROI of oneside of the lung."""binary_mask_dilated = np.array(binary_mask)for i in range(binary_mask.shape[0]):slice_binary = binary_mask[i]if np.sum(slice_binary) > 0:slice_convex = morphology.convex_hull_image(slice_binary)if np.sum(slice_convex) <= dilate_factor * np.sum(slice_binary):binary_mask_dilated[i] = slice_convexstruct = scipy.ndimage.generate_binary_structure(3, 1)binary_mask_dilated = scipy.ndimage.binary_dilation(binary_mask_dilated, structure=struct, iterations=10)return binary_mask_dilateddef apply_lung_mask(image, binary_mask1, binary_mask2, pad_value=170,bone_thred=210, remove_bone=False):"""Apply the binary mask of each lung to the image. Regions out of interestare replaced with pad_value.image: 3D uint8 numpy array with the same shape of the image.binary_mask1: 3D binary numpy array with the same shape of the image,that only one side of lung is True.binary_mask2: 3D binary numpy array with the same shape of the image,that only the other side of lung is True.pad_value: int, uint8 value for padding image regions that is notinterested.bone_thred: int, uint8 threahold value for determine parts of image isbone.return: D uint8 numpy array with the same shape of the image afterapplying the lung mask."""binary_mask = binary_mask1 + binary_mask2binary_mask1_dilated = convex_hull_dilate(binary_mask1)binary_mask2_dilated = convex_hull_dilate(binary_mask2)binary_mask_dilated = binary_mask1_dilated + binary_mask2_dilatedbinary_mask_extra = binary_mask_dilated ^ binary_mask# replace image values outside binary_mask_dilated as pad valueimage_new = image * binary_mask_dilated + pad_value * (1 - binary_mask_dilated).astype('uint8')# set bones in extra mask to 170 (ie convert HU > 482 to HU 0;# water).if remove_bone:image_new[image_new * binary_mask_extra > bone_thred] = pad_valuereturn image_newdef cropResample_process(params):#    seg-lungs-LUNA16, masks_test/3, seg-lungs-LUNA16, preprocessed_test/3, Truepid, lung_mask_dir, nod_mask_dir, img_dir, save_dir, do_resample = paramsprint('Preprocessing %s...' % (pid))img_org, origin, spacing = load_itk_image(os.path.join(img_dir, '%s.mhd' % (pid)))lung_mask, _, _ = load_itk_image(os.path.join(lung_mask_dir, '%s.mhd' % (pid)))nodule_mask, _ = nrrd.read(os.path.join(nod_mask_dir, '%s.nrrd' % (pid)))# 4-右肺   3-左肺   5-气管binary_mask_r = lung_mask == 4binary_mask_l = lung_mask == 3binary_mask = binary_mask_r + binary_mask_limg_org = HU2uint8(img_org)img_lungRL = apply_lung_mask(img_org, binary_mask_r, binary_mask_l)

有一个点前面从没有说明过,那就是官方提供的lung mask数组,在这里简要的记录下:

  • 数字3,表示左肺
  • 数字4,表示右肺
  • 数字5,表示气管

还是第一次看到这个按位异或运算符(^),简单的学习了下:

按位异或运算符(^)用于将两个操作数的每个对应位进行逻辑异或操作。如果两个对应位的值相同,则结果为0,否则为1。异或的本质是没有进位的加法。

dilate膨胀后的binary mask和原始的binary mask求异或运算,对应位的值相同,结果为0,否则为1。那么,得到的结果也就是膨胀出来的那部分,就是bone,这部分在去除bone阶段使用到。

可能会有这样的疑问:为什么不直接imagelung mask相乘,得到一个分割肺实质后留下来的image呢?反而需要采用凸包优化的方式,多此一举呢?

:在lung mask里面,肺实质的分割是有误差的。也就是肺实质的分割是沿着肺区边缘的,但是某些结节的位置,恰好在肺区的边界上,且密度很大。那么mask就会呈现一个内凹的一个状态。如果采用上面的方法,这样结节就被抠除了。采用凸包优化,就可以利用稍微扩展肺实质边缘,达到将更多肺区留下来的效果。

但是,对于肺结核等等大病灶的疾病,采用上述取出肺实质的方法就不行。主要是因为肺结核的病种范围比较大,尽管采用了凸包优化,最终还是会切除很大一块肺区位置,这样肺区就不完整了,有些得不偿失。

下面是skimage.morphology.convex_hull_image官方给出的实例,如下:点击直达
0作用到我们项目里面,切割后的样子如下:

2

2.3、resample操作

本篇对resample的操作,在zyx的各个维度上,就雨露均沾,通通调整到1mm的状态,这样得到的一个像素大小,表示的也就是物理大小,不会引起任何一个维度上变形的情况。

代码如下所示:

def resample(image, spacing, new_spacing=[1.0, 1.0, 1.0], order=1):"""Resample image from the original spacing to new_spacing, e.g. 1x1x1image: 3D numpy array of raw HU values from CT series in [z, y, x] order.spacing: float * 3, raw CT spacing in [z, y, x] order.new_spacing: float * 3, new spacing used for resample, typically 1x1x1,which means standardizing the raw CT with different spacing all into1x1x1 mm.order: int, order for resample function scipy.ndimage.interpolation.zoomreturn: 3D binary numpy array with the same shape of the image after,resampling. The actual resampling spacing is also returned."""# shape can only be int, so has to be rounded.new_shape = np.round(image.shape * spacing / new_spacing)# the actual spacing to resample.resample_spacing = spacing * image.shape / new_shaperesize_factor = new_shape / image.shapeimage_new = scipy.ndimage.zoom(image, resize_factor, mode='nearest', order=order)return (image_new, resample_spacing)if do_resample:print('Resampling...')img_lungRL, resampled_spacing = resample(img_lungRL, spacing, order=3)seg_nod_mask = np.zeros(img_lungRL.shape, dtype=np.uint8)for i in range(int(nodule_mask.max())):# 一个结节,一个结节的resamplemask = (nodule_mask == (i + 1)).astype(np.uint8)mask, _ = resample(mask, spacing, order=3)seg_nod_mask[mask > 0.5] = i + 1

其中在resample函数里面,使用到了scipy.ndimage.zoom操作,直接将原始数据,zoom到新的shape

scipy.ndimage.zoom(input, zoom, output=None, order=3, mode='constant', cval=0.0, prefilter=True, *, grid_mode=False)[source]

函数中:

  • input:The input array
  • zoom:The zoom factor along the axes

下面是一段官方案例,展示了zoom前后的变化,可以参考:点击链接直达

from scipy import ndimage, datasets
import matplotlib.pyplot as pltfig = plt.figure()
ax1 = fig.add_subplot(121)  # left side
ax2 = fig.add_subplot(122)  # right side
ascent = datasets.ascent()
result = ndimage.zoom(ascent, 3.0)
ax1.imshow(ascent, vmin=0, vmax=255)
ax2.imshow(result, vmin=0, vmax=255)
plt.show()

zoom前后的变化,如下所示:
1

发现这个scipy库还真是好用,后续找时间全面的补充下这块的知识。

2.4、存储到本地

这部分就比较的简单了,主要就是说下数组存储的一些新的:

  • npy文件存储一些简单的数组,比如下文的spacing、坐标等等;
  • nrrd文件存储多维数组,比如下面的imagemask数组图像,大小是240x320x320大小的;
    以前喜欢用nii作为存储文件,现在发现不太好用,nrrd也可以存储数组,还能存储header头。

下面是代码:

lung_box = get_lung_box(binary_mask, img_lungRL.shape)  # 获取肺区分割的外轮廓z_min, z_max = lung_box[0]
y_min, y_max = lung_box[1]
x_min, x_max = lung_box[2]# 裁剪操作,去除肺区外的
img_lungRL = img_lungRL[z_min:z_max, y_min:y_max, x_min:x_max]
if do_resample:seg_nod_mask = seg_nod_mask[z_min:z_max, y_min:y_max, x_min:x_max]
else:seg_nod_mask = nodule_mask[z_min:z_max, y_min:y_max, x_min:x_max]np.save(os.path.join(save_dir, '%s_origin.npy' % (pid)), origin)  # origin (3,) 记录三维图像origin坐标信息
if do_resample:np.save(os.path.join(save_dir, '%s_spacing.npy' % (pid)), resampled_spacing)  # 记录了resample前后x\y\z三个维度的scale系数
np.save(os.path.join(save_dir, '%s_ebox_origin.npy' % (pid)), np.array((z_min, y_min, x_min)))nrrd.write(os.path.join(save_dir, '%s_clean.nrrd' % (pid)), img_lungRL)  # 去除掉非肺区后的CT图像
nrrd.write(os.path.join(save_dir, '%s_mask.nrrd' % (pid)), seg_nod_mask)  # 去除掉非肺区后的结节MASK图像

2.5、获取结节中心点坐标和半径

这里获取标记结节的中心点坐标和半径,目的还是为了在裁剪patch等操作时候,能够直接从已经获得的结节里面拿取,直接进行crop操作。

这块的步骤和前面get_lung_box差不多,唯一的区别在于保存下来的是中心点,而不是上面的最大、最小边界坐标。

代码如下:

def generateBBoxes_label(params):pid, lung_mask_dir, nod_mask_dir, img_dir, save_dir, do_resample = paramsmasks, _ = nrrd.read(os.path.join(save_dir, '%s_mask.nrrd' % (pid)))bboxes = []instance_nums = [num for num in np.unique(masks) if num]for i in instance_nums:mask = (masks == i).astype(np.uint8)zz, yy, xx = np.where(mask)d = max(zz.max() - zz.min() + 1, yy.max() - yy.min() + 1, xx.max() - xx.min() + 1)bboxes.append(np.array([(zz.max() + zz.min()) / 2., (yy.max() + yy.min()) / 2., (xx.max() + xx.min()) / 2., d]))bboxes = np.array(bboxes)if not len(bboxes):print('%s does not have any nodules!!!' % (pid))print('Finished masks to bboxes %s' % (pid))np.save(os.path.join(save_dir, '%s_bboxes.npy' % (pid)), bboxes)

三、总结

到这里,本篇内容,结合上一篇的内容,我们对Luna16的数据处理基本上就完成了,也完成了我们最早希望得到的内容:

  1. imagesmask数组,文件名一一对应;
  2. resample操作到1mm
  3. 肺实质外的部分丢弃;

6 和 7 这两个篇章,都是对前面几个章节数据部分的补充,你参考这两篇进行数据处理也行,参考其他的数据处理也行,最终得到的数据形式,只要是一样的就行。

相关文章:

【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割7(数据预处理)

在上一节&#xff1a;【3D 图像分割】基于 Pytorch 的 VNet 3D 图像分割6&#xff08;数据预处理&#xff09; 中&#xff0c;我们已经得到了与mhd图像同seriesUID名称的mask nrrd数据文件了&#xff0c;可以说是一一对应了。 并且&#xff0c;mask的文件&#xff0c;还根据结…...

极米科技H6 Pro 4K、H6 4K高亮定焦版——开启家用投影4K普及时代

智能投影产业经过几年发展&#xff0c;市场规模正在快速扩大。洛图数据显示&#xff0c;预计今年中国投影出货量有望超700万台&#xff0c;2027年达950万台&#xff0c;可见智能投影产业规模将逐渐壮大&#xff0c;未来可期。2023年&#xff0c;投影行业呈现出全新面貌&#xf…...

软考系统架构师知识点集锦九:数据库系统

一、考情分析 二、考点精讲 2.1数据库概述 2.1.1数据库模式 (1)三级模式:外模式对应视图&#xff0c;模式(也称为概念模式)对应数据库表&#xff0c;内模式对应物理文件。(2)两层映像:外模式-模式映像&#xff0c;模式-内模式映像;两层映像可以保证数据库中的数据具有较高的…...

IOC课程整理-6 Spring IoC 依赖注入

1 依赖注入的模式和类型 模式 类型 2 自动绑定&#xff08;Autowiring&#xff09; 官方定义 “自动装配是Spring框架中一种机制&#xff0c;用于自动解析和满足bean之间的依赖关系。通过自动装配&#xff0c;Spring容器可以根据类型、名称或其他属性来自动连接协作的bean&…...

FANUC机器人PRIO-621和PRIO-622设备和控制器没有运行故障处理

FANUC机器人PRIO-621和PRIO-622设备和控制器没有运行故障处理 如下图所示&#xff0c;新的机器人开机后提示报警&#xff1a; PRIO-621 设备没有运行 PRIO-622 控制器没有运行 我们首先查看下手册上的报警代码说明&#xff0c;如下图所示&#xff0c; 如下图所示&#xff0c…...

《动手深度学习》线性回归简洁实现实例

&#x1f388; 作者&#xff1a;Linux猿 &#x1f388; 简介&#xff1a;CSDN博客专家&#x1f3c6;&#xff0c;华为云享专家&#x1f3c6;&#xff0c;Linux、C/C、云计算、物联网、面试、刷题、算法尽管咨询我&#xff0c;关注我&#xff0c;有问题私聊&#xff01; &…...

国家数据局正式揭牌,数据专业融合型人才迎来发展良机

&#x1f4d5;作者简介&#xff1a;热爱跑步的恒川&#xff0c;致力于C/C、Java、Python等多编程语言&#xff0c;热爱跑步&#xff0c;喜爱音乐的一位博主。 &#x1f4d7;本文收录于恒川的日常汇报系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏C语言初阶、C…...

基于springboot实现休闲娱乐代理售票平台系统项目【项目源码+论文说明】

基于springboot实现休闲娱乐代理售票系统演示 摘要 网络的广泛应用给生活带来了十分的便利。所以把休闲娱乐代理售票管理与现在网络相结合&#xff0c;利用java技术建设休闲娱乐代理售票系统&#xff0c;实现休闲娱乐代理售票的信息化。则对于进一步提高休闲娱乐代理售票管理发…...

3.AUTOSAR OS分析(一)

1. AUTOSAR OS诞生背景 在最初接触汽车ECU开发时,提到最多的还是OSEK,比如OSEK NM、OSEK OS等等;而OSEK/VDK操作系统也是最先引入汽车行业;OSEK OS是基于事件触发的操作系统,有以下特性: 固定优先级调度中断处理函数StartOS和StartupHook作为启动阶段的通用接口函数Shutd…...

AB试验(七)利用Python模拟A/B试验

AB试验&#xff08;七&#xff09;利用Python模拟A/B试验 到现在&#xff0c;我相信大家理论已经掌握了&#xff0c;轮子也造好了。但有的人是不是总感觉还差点什么&#xff1f;没错&#xff0c;还缺了实战经验。对于AB实验平台完善的公司 &#xff0c;这个经验不难获得&#…...

Go语言入门-流程控制语句

流程控制 Go语言中有以下几种常见的流程控制语句&#xff1a; 条件语句&#xff08;Conditional Statements&#xff09;&#xff1a; if语句&#xff1a;用于根据条件执行代码块。else语句&#xff1a;在if条件不满足时执行的语句块。else if语句&#xff1a;用于在多个条件之…...

深入探究ASEMI肖特基二极管MBR60100PT的材质

编辑-Z 在电子零件领域中&#xff0c;肖特基二极管MBR60100PT因其出色的性能和广泛的应用而显得尤为关键。理解其材质不仅有助于我们深入理解其运作原理&#xff0c;也有助于我们做出更合适的电子设计。那么&#xff0c;肖特基二极管MBR60100PT是什么材质呢? 首先&#xff0c…...

python类模拟“对战游戏”

Game类含玩家昵称、生命值、攻击力(整数)&#xff0c;暴击率、闪避率(小数)&#xff0c;在魔术方法init定义&#xff1b;attack方法中实现两个Game实例对战模拟。 (本笔记适合初通Python类class的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.py…...

Maven第二章:Maven基本概念与生命周期

Maven第二章&#xff1a;Maven基本概念与生命周期 前言 本章主要内容&#xff0c;介绍Maven基本概念&#xff0c;包括maven坐标含义&#xff0c;命名规则&#xff0c;继承与聚合、了解与理解生命周期&#xff0c;如何通过Maven进行依赖和版本管理。 什么是Maven的坐标&#xf…...

<蓝桥杯软件赛>零基础备赛20周--第3周--填空题

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 每周发1个博客&#xff0c;共20周&#xff08;读者可以按…...

【Linux】VM及WindowsServer安装

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是Java方文山&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的专栏《微信小程序开发实战》。&#x1f3af;&#x1f3a…...

【实用教程】MySQL内置函数

1 背景 在MySQL查询等操作过程中&#xff0c;我们需要根据实际情况&#xff0c;使用其提供的内置函数。今天我们就来一起来学习下这些函数&#xff0c;在之后的使用过程中更加得心应手。 2 MySQL函数 2.1 字符串函数 常用的函数如下&#xff1a; concat(s1,s2,…sn)字符串…...

第十二节——ref

一、概念 ref 被用来给DOM元素或子组件注册引用信息。引用信息会根据父组件的 $refs 对象进行注册。如果在普通的DOM元素上使用&#xff0c;引用信息就是元素; 如果用在子组件上&#xff0c;引用信息就是组件实例。 注意&#xff1a;只要想要在Vue中直接操作DOM元素&#xff…...

少儿编程 2023年9月中国电子学会图形化编程等级考试Scratch编程四级真题解析(判断题)

2023年9月scratch编程等级考试四级真题 判断题(共10题,每题2分,共20分) 11、运行程序后,变量"result"的值是6 答案:对 考点分析:考查积木综合使用,重点考查自定义积木的使用 图中自定义积木实现的功能是获取两个数中最大的那个数并存放在result变量中,左…...

【设计模式三原则】

设计模式三原则 单一职责原则开放封闭原则依赖倒转原则里氏代换原则 我们在进行程序设计的时候&#xff0c;要尽可能地保证程序的可扩展性、可维护性和可读性&#xff0c;所以需要使用一些设计模式&#xff0c;这些设计模式都遵循了以下三个原则&#xff0c;下面来依次为大家介…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...

全面解析数据库:从基础概念到前沿应用​

在数字化时代&#xff0c;数据已成为企业和社会发展的核心资产&#xff0c;而数据库作为存储、管理和处理数据的关键工具&#xff0c;在各个领域发挥着举足轻重的作用。从电商平台的商品信息管理&#xff0c;到社交网络的用户数据存储&#xff0c;再到金融行业的交易记录处理&a…...