人工智能——Opencv图像色彩空间转换、灰度实验、图像二值化处理、仿射变化

一、图像色彩空间转换

(一)颜色加法

        1、直接相加

        1、直接相加

        2、调用cv.add()函数进行饱和操作        

在OpenCV中进行颜色的加法,我们说图像即数组,所以从数据类型来说我们可以直接用numpy的知识来进行直接相加,但是存在溢出错误。

因为如果直接numpy进行直接相加,会进行取模运算,对256取模,相加后超出的值会又从0开始向上,例如250+10最后的值是4,导致色彩失真

#如果直接numpy进行直接相加,会进行取模运算,对256取模,相加后超出的值会又从0开始向上,例如250+10最后的值是4
dst2=pig+cao
#举例子
x=np.uint8([[250]])
y=np.uint8([[10]])
print(x+y)
print(cv.add(x,y))

 正常进行图像颜色加法时,调用库中的API:饱和操作cv.add(img1,img2)        类型是np.uint8 0~255 例如250+10最后到255就饱和不加了

#饱和操作cv.add(img1,img2)    np.uint8 0~255 例如250+10最后只能到255到饱和
dst1=cv.add(pig,cao)

        2、颜色加权加法:cv.addWeighted(img1,α,img2,β,,γ)

       α、β分别是img1和img2的权重参数

         γ是亮度调整值,

                γ>0时,整体亮度增加

                γ<0时,整体亮度降低

                γ=0时,亮度不变

#颜色加权加法 cv.addWeighted(img1,α,img2,β,,γ)     其中γ是亮度调整值,γ>0时,整体亮度增加,γ<0时,整体亮度降低,γ=0时,亮度不变
dst3 =cv.addWeighted(pig,0.7,cao,0.3,0)

(二)色彩空间转换

图像的颜色表示有很多方式,除了RGB外,还有HCV,Gray(灰度)等。

        HSV颜色空间使用色调(Hue)、饱和度(Saturation)和亮度(Value)三个参数来表示颜色,色调H表示颜色的种类,如红色、绿色、蓝色等;饱和度表示颜色的纯度或强度,如红色越纯,饱和度就越高;亮度表示颜色的明暗程度,如黑色比白色亮度低

H: 0— 180

S: 0— 255

V: 0— 255

        Gray灰度图像在进行二值化处理时需要使用,也经常需要对彩色图像进行转换

cv2.cvtColor:是OpenCV中的一个函数,用于图像颜色空间的转换。可以将一个图像从一个颜色空间转换为另一个颜色空间,比如从RGB到灰度图,或者从RGB到HSV的转换等

语法:cv2.cvtColor(img,code)

        img:输入图像

        code:指定转换的类型,比如cv.COLOR_RGB2GRAY表示从rgb到灰度图像的转换

        cv.COLOR_RGB2HSV表示从GGB图像转换到HSV图像

import cv2 as cv
#读取图像
img = cv.imread("../images/1.jpg")
cv.imshow("img",img)#颜色转换cv.cvtcolor(img,code)  (得到的是一个新的图像数组,所以是有返回值的)
#转灰度
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
cv.imshow("gray",gray)
#转HSV
hsv = cv.cvtColor(img,cv.COLOR_BGR2HSV)
cv.imshow("hsv",hsv)
#转RGB
rgb = cv.cvtColor(img,cv.COLOR_BGR2RGB)
cv.imshow("rgb",rgb)cv.waitKey(0)
cv.destroyAllWindows()

二、灰度实验

        灰度图与彩色图最大的不同就是:彩色图是由R、G、B三个通道组成,而灰度图只有一个通道,也称为单通道图像,所以彩色图转成灰度图的过程本质上就是将R、G、B三通道合并成一个通道的过程

(一)最大值法

对于彩色图像的每个像素,它会从R、G、B三个通道的值中选出最大的一个,并将其作为灰度图像中对应位置的像素值

创建的思路:

  1. 首先需要读取一张图片
  2. 然后创建一个和图片一样大小的全0的图像用来存储图片中的像素值
  3. 通过依次遍历行列,然后取到每个像素对应三通道的值,用max小函数取出来赋值给当前像素即可

代码实现:

import cv2 as cv
import numpy as npimg = cv.imread('../images/pig.png')#创一个一样大小的全0图像
img1 = np.zeros((img.shape[0],img.shape[1]),dtype=np.uint8)#循环遍历每一行,img[0,0,0]
for  i in range(img.shape[0]): # 遍历行for j in range(img.shape[1]): # 遍历列img1[i,j]=max(img[i,j,0],img[i,j,1],img[i,j,2]) # 取最大值cv.imshow('img1',img1)
cv.waitKey(0)
cv.destroyAllWindows()

(二)平均值法

对于彩色图像的每个像素,它会将R、G、B三个通道的像素值全部加起来,然后再除以三,得到的平均值就是灰度图像中对应位置的像素值

方法:

  1. 读取一张图片
  2. 创建一样大的全0的图像存放新的像素点
  3. 依次遍历行列,然后取到每个像素对应三通道的值,加起来整除3(注意,此处取到的三通道的值都是uint8(无符号8为整数,数值范围在0~255)直接这样相加可能存中值溢出,所以我们需要先将读取到的图片转为int类型后再进行相加)
  4. 最后再把计算得到的int类型的通道值转为uint8

代码实现:

import cv2 as cv
import numpy as npimg = cv.imread('../images/pig.png')#创一个一样大小的全0图像
img1 = np.zeros((img.shape[0],img.shape[1]),dtype=np.uint8)#循环遍历每一行,img[0,0,0]
for  i in range(img.shape[0]): # 遍历行for j in range(img.shape[1]): # 遍历列#为什么要先转换为int类型呢?因为图像数组通常都是uint8(无符号 8 位整数)取值范围是 0 - 255,# 三个数直接相加可能会溢出,所以需要转为int有符号的整数避免溢出,再用np.uint8给转回来#//3 整除3是因为我们的像素值的通道都是整数img1[i,j]=np.uint8((int(img[i,j,0])+int(img[i,j,1])+int(img[i,j,2]))//3)cv.imshow('img1',img1)
cv.waitKey(0)
cv.destroyAllWindows()

(三 )加权平均值法

对于彩色图像的每个像素,它会按照一定的权重去乘以每个通道的像素值,并将其相加,得到最后的值就是灰度图像中对应位置的像素值

权重可以自行设定,所使用的权重之和应该等于1,方法与平均值法相似只是多了

  1. 读取一张图片
  2. 创建一样大的全0的图像存放新的像素点
  3. 依次遍历行列,然后取到每个像素对应三通道的值,加起来整除3(注意,此处和权重相乘后通常会出现小数,但像素值又只能为整数,系统会自动向下或向上取整,为了让结果更准确,所以会用round()函数进行四舍五入)
  4. 最后再把计算得到的int类型的通道值转为uint8

代码实现:

import cv2 as cv
import numpy as npimg = cv.imread('../images/pig.png')#创一个一样大小的全0图像
img1 = np.zeros((img.shape[0],img.shape[1]),dtype=np.uint8)# 定义权重
wb,wg,wr = 0.114,0.587,0.299#循环遍历每一行,img[0,0,0]
for  i in range(img.shape[0]): # 遍历行for j in range(img.shape[1]): # 遍历列#为什么要先转换为int类型呢?因为图像数组通常都是uint8(无符号 8 位整数)取值范围是 0 - 255,# 三个数直接相加可能会溢出,所以需要转为int有符号的整数避免溢出,再用np.uint8给转回来#//3 整除3是因为我们的像素值的通道都是整数#round()四舍五入img1[i,j]=np.uint8(round(wb*img[i,j,0]+wg*img[i,j,1]+wr*img[i,j,2])//3)cv.imshow('img1',img1)
cv.waitKey(0)
cv.destroyAllWindows()

三、图像二值化处理

二值图像的二维矩阵仅由0、1两个值构成,“0”代表黑色,“1”代白色(也就是255的值),其操作的图像是必须是灰度图

(一)全局阈值法

语法:_,binary = cv2.threshold(img,thresh,maxval,type)

  • img:输入图像,要进行二值化处理的灰度图。

  • thresh:设定的阈值。当像素值大于(或小于,取决于阈值类型)thresh时,该像素被赋予的值。

  • type:阈值处理的类型,

    包括:
    • 阈值法:cv.threshold(img, thresh, max_value, cv.THRESH_BINARY)

    • 反阈值法:cv.threshold(img, thresh, max_value, cv.THRESH_BINARY_INV)

    • 截断阈值法:cv.threshold(img, thresh, max_value, cv.THRESH_TRUNC)

    • 低阈值零处理法:cv.threshold(img, thresh, max_value, cv.THRESH_TOZERO)

    • 超阈值零处理法cv.threshold(img, thresh, max_value, cv.THRESH_TOZERO_INV)

    • OTSU阈值法:cv.threshold(img, thresh, max_value, cv.THRESH_OSTU)或cv.threshold(img, thresh, max_value, cv.THRESH_OSTU_INV)

  • 返回值:

    • 第一个值(通常用下划线表示):计算出的阈值,若使用自适应阈值法,会根据算法自动计算出这个值。

    • 第二个值(binary):二值化后的图像矩阵。与输入图像尺寸相同。

        阈值法:通过设置一个阈值,将灰度图中的每一个像素值与该阈值进行比较,小于等于阈值的像素就被设置为0(通常代表背景),大于阈值的像素就被设置为maxval(通常代表前景)

        反阈值法:与阈值法相反。反阈值法是当灰度图的像素值大于阈值时,该像素值将会变成0(黑),当灰度图的像素值小于等于阈值时,该像素值将会变成maxval。

        截断阈值法:将灰度图中的所有像素与阈值进行比较,像素值大于阈值的部分将会被修改为阈值,小于等于阈值的部分不变

        低阈值零处理:字面意思,就是像素值小于等于阈值的部分被置为0,大于阈值的部分不变

        超阈值零处理:将灰度图中的每个像素与阈值进行比较,像素值大于阈值的部分置为0(也就是黑色),像素值小于等于阈值的部分不变。

        OSTU阈值法:OSTU阈值法 并不是一个有效的阈值类型,THRESH_OTSU 本身并不是一个独立的阈值化方法,通常与 THRESH_BINARYTHRESH_BINARY_INV 结合使用 默认情况下它会与 `THRESH_BINARY` 结合使用。也就是说,当你仅指定了 `cv2.THRESH_OTSU`,实际上等同于同时指定了 `cv2.THRESH_BINARY + cv2.THRESH_OTSU`

        OSTU 阈值法是一种基于图像灰度直方图统计特性的阈值确定方法,目的是将图像分为前景和背景两部分,使得分割后的两类之间的差异最大,也就是让类间方差最大,从而找到一个最佳的阈值来实现二值化

        遍历所有可能的阈值,将设当前阈值为t,遍历t到最大像素值减1,分别计算每个t对应的类间方差,使得类间方差值最大的那个t值就是OSTU算法所确定的最佳阈值,将图像中灰度值小于等于这个阈值的像素设置为 0(黑色,代表背景),大于这个阈值的像素设置为 255(白色,代表前景),就完成了基于 OSTU 阈值法的二值化处理。

代码实现:

import cv2 as cvflower = cv.imread('../images/flower.png')
# 读取灰色图像
# flower1 = cv.imread('../images/flower.png',0)#h灰度化处理
flower1 = cv.cvtColor(flower,cv.COLOR_BGR2GRAY)
flower1 = cv.resize(flower1,(360,360))
cv.imshow('flower1',flower1)#二值化,阈值法
_,binary = cv.threshold(flower1,127,255,cv.THRESH_BINARY)
cv.imshow('binary',binary)# 反阈值法,为什么前面用下划线,因为此处返回的值是thresh,本身就是我们传的参数,所以没必要接收,就可以用下划线占位
_,binary_inv =  cv.threshold(flower1,127,255,cv.THRESH_BINARY_INV)
cv.imshow('binary_inv',binary_inv)#截断阈值法
_,binary_trunc= cv.threshold(flower1,180,255,cv.THRESH_TRUNC)
cv.imshow('binary_trunc',binary_trunc)#低阈值0处理
_,binary_zero =cv.threshold(flower1,127,255,cv.THRESH_TOZERO)
cv.imshow('binary_zero',binary_zero)#超阈值0处理
_,binary_zero_inv =cv.threshold(flower1,127,255,cv.THRESH_TOZERO_INV)
cv.imshow('binary_zero_inv',binary_zero_inv)#OTSU阈值法 默认结合了cv.THRESH_BINARY  THRESH_BINARY=THRESH_BINARY+THRESH_OTSU
thresh1,otsu=cv.threshold(flower1,200,255,cv.THRESH_OTSU)
cv.imshow('otsu',otsu)
print(thresh1)
# otsu阈值结合反阈值法
thresh2,otsu_inv = cv.threshold(flower1,200,255,cv.THRESH_BINARY_INV+cv.THRESH_OTSU)
cv.imshow('otsu_inv',otsu_inv)
print(thresh2)#自适应二值化,小区域计算
#取均值
auto_mean =cv.adaptiveThreshold(flower1,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,11,2)
cv.imshow('auto_mean',auto_mean)
#高斯加权法
auto_gauss =  cv.adaptiveThreshold(flower1,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,11,2)
cv.imshow('auto_gauss',auto_gauss)#显示效果
cv.waitKey(0)
cv.destroyAllWindows()

四、图像翻转和仿射变换

1、图像的镜像翻转:

在OpenCV中,图片的镜像旋转是以图像的中心为原点进行镜像翻转的

- cv2.flip(img,flipcode)**

- 参数

  - img: 要翻转的图像
- flipcode: 指定翻转类型的标志
- flipcode=0: 垂直翻转,图片像素点沿x轴翻转
- flipcode>0: 水平翻转,图片像素点沿y轴翻转
- flipcode<0: 水平垂直翻转,水平翻转和垂直翻转的结合

import cv2 as cv
face= cv.imread('../images/face.png')
cv.imshow('face',face)
#翻转镜像旋转,以图像的中心为原点cv.flip(img,flipcode)
#flipcode=0:垂直翻转 沿x轴上下翻转
flip_0 = cv.flip(face,0)
cv.imshow('flip_0',flip_0)#flipcode>0:沿y轴水平翻转(左右翻转)
flip_1 = cv.flip(face,1)
cv.imshow('flip_1',flip_1)#flipcode<0:沿xy轴同时翻转(垂直水平都翻转)
flip_2 = cv.flip(face,-1)
cv.imshow('flip_2',flip_2)cv.waitKey(0)
cv.destroyAllWindows()

2、仿射变换:

仿射变换(Affine Transformation)是一种线性变换,保持了点之间的相对距离不变。

仿射变换的基本性质:

        保持直线
保持平行
比例不变性
不保持角度和长度

常见的仿射变换类型:旋转,平移,缩放,剪切

对于仿射变换,最重要的一步是获得变换矩阵,通过变换矩阵是的目标点变换到预定位置

原理:

        对于 2D 图像,任意像素点的坐标可以表示为齐次坐标形式 (x, y, 1)(增加维度便于统一处理平移)。仿射变换矩阵 M 是一个 3×3 的矩阵实际使用中常简化为 2×3,通过补全最后一行 [0,0,1] 变为齐次矩阵)

        原像素点 (x, y) 经过矩阵 M 变换后,得到新像素点 (x', y'),计算公式为:

展开后

此处的思维是我们再思考的时候进行的正向思考,通过变换矩阵得到变换后的像素点对应的值。

        实际在图像变换中,,我们通常需要根据目标图像的像素点 (x', y') 反推它在原图像中的对应像素点 (x, y),这一过程称为 “逆变换

        当我们对图像进行旋转得到新图像后,新图像中某个像素 (x', y') 的颜色,实际上来自原图像中某个像素 (x, y) 的颜色。为了准确填充新图像的像素值,必须找到 (x', y') 对应的 (x, y)

        此时,就需要通过仿射矩阵 M 的逆矩阵 M^{-1} 来实现反推,通过逆矩阵来求解原像素点

变换过程:

已知目标像素 (x', y'),通过逆矩阵 M^{-1} 求解原像素 (x, y)

展开后:其中(a', b', c', d', e', f') 是逆矩阵的元素

在 OpenCV 的 warpAffine 等变换函数中,内部会自动通过逆矩阵计算:

  1. 遍历目标图像的每个像素 (x', y')
  2. 用逆矩阵 M^{-1} 计算其在原图像中的对应点 (x, y)
  3. 取原图像 (x, y) 的像素值,赋给目标图像的 (x', y')

仿射变换函数:

cv2.warpAffine(img,M,dsize)

img:输入图像。

M:2x3的变换矩阵,类型为np.float32。

-dsize:输出图像的尺寸,形式为(width,height)

在实际运用时,最主要的是得到变换矩阵

          图像旋转:

首先利用cv2.getRotationMatrix2D()函数得到旋转矩阵:

        cv2.getRotationMatrix2D(center,angle,scale)

  • center:旋转中心点的坐标,格式为`(x,y)`。
  • angle:旋转角度,单位为度,正值表示逆时针旋转负值表示顺时针旋转。
  • scale:缩放比例,若设为1,则不缩放。
  • 返回值:M,2x3的旋转矩阵。
import cv2 as cv
#读图
cat = cv.imread("../images/1.jpg")#获取旋转矩阵 cv2.getRotationMatrix20(center,angle,scale)
M = cv.getRotationMatrix2D((200,300),30,1)
print(M)cat = cv.warpAffine(cat,M,(640,580))
cv.imshow("cat",cat)cv.waitKey(0)
cv.destroyAllWindows()

        图像平移:

移操作可以将图像中的每个点沿着某个方向移动一定的距离

假设我们有一个点 P(x,y),希望将其沿x轴方向平移t_x个单位,沿y轴方向平移t_y个单位到新的位置P′(x′,y′),那么平移公式如下:

​                 x′=x+tx

​                 y′=y+ty

在矩阵形式下,该变换可以表示为:

import cv2 as cv
import numpy as np
#读图
cat = cv.imread("../images/1.jpg")#定义平移量
tx=80
ty=120#定义平移矩阵
M = np.float32([[1,0,tx],[0,1,ty]])#仿射变换的API
cat = cv.warpAffine(cat,M,(1000,1000))
cv.imshow("cat",cat)cv.waitKey(0)
cv.destroyAllWindows()

        图像缩放

假设要把图像的宽高分别缩放为0.5和0.8,那么对应的缩放因子sx=0.5,sy=0.8。

点$P(x,y)$对应到新的位置P'(x',y'),缩放公式为:

   x′=s_x*x

  ​ y′=s_y*y

  在矩阵形式下,该变换可以表示为

import cv2 as cv
import numpy as np
#读图
cat = cv.imread("../images/1.jpg")#定义缩放因子
sx=0.8
sy=0.5#定义缩放矩阵,最后一列是平移量
M = np.float32([[sx,0,0],[0,sy,0]])#仿射变换的API
cat = cv.warpAffine(cat,M,(1000,1000))
cv.imshow("cat",cat)cv.waitKey(0)
cv.destroyAllWindows()

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

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

相关文章

【JToken】JToken == null 判断无效的问题

if (innerNode null) {continue; }Debug.Log($"toNode type: {node["toNode"]?.GetType()}");发现这个JToken 无法正确的判断 是否为 null&#xff0c;再排除逻辑问题后&#xff0c;我基本能确定的是 这个对象 不返回的不是真正的C# NULL 输出类型后是 N…

C++基于libmodbus库实现modbus TCP/RTU通信

今天看到了一个参考项目中用到了modbus库&#xff0c;看着使用很是方便&#xff0c;于是记录一下。后面有时间了或者用到了再详细整理。 参考&#xff1a;基于libmodbus库实现modbus TCP/RTU通信-CSDN博客 一、介绍 1.1库文件包含 1.2最简单的使用 本人在QT6.5下&#xff0…

【原创】微信小程序添加TDesign组件

前言 TDesign 是腾讯公司推出的一款UI界面库,至于腾讯的实力嘛,也不用多说了。 官网:https://tdesign.tencent.com/ 源码:https://github.com/Tencent/tdesign 目前处于活跃状态,发文前5日,该库仍在更新中… 遇到的问题 虽然腾讯为微信小程序开发提供了一个讨论的论坛,…

Vue的路由模式的区别和原理

路由模式 Vue 的路由模式指的是 Vue Router 提供的 URL 处理方式&#xff0c;主要有两种&#xff1a;Hash 模式和History 模式。 Hash模式 在 Vue Router 中&#xff0c;默认使用的是 hash 模式&#xff0c;即 mode: hash。如果想要使用 history 模式&#xff0c;可以设置 mode…

通过TPLink路由器进行用户行为审计实战

用户行为审计是指对用户在网络平台上的行为进行监控和记录&#xff0c;以便对其行为进行分析和评估的过程。随着互联网的普及和发展&#xff0c;用户行为审计在网络安全和数据隐私保护方面起到了重要的作用。 用户行为审计可以帮助发现和预防网络安全威助。通过对用户的行为进行…

MYSQL 第一次作业

新建产品库mysql> CREATE DATABASE mydb6_product;使用产品库mysql> USE mydb6_product;创建employess表mysql> CREATE TABLE employees (-> id INT PRIMARY KEY,-> name VARCHAR(50) NOT NULL,-> age INT,-> gender VARCHAR(10) NOT NULL DEFAULT unknow…

暑期前端训练day7——有关vue-diff算法的思考

前言 今天分享一下我对vue的diff的探究&#xff0c;跟我一起深入底层&#xff0c;看一看vue是怎么进行diff的&#xff0c;它的复杂度如何&#xff0c;为什么性能这么高&#xff0c;diff的目标是尽可能的复用原来的真实dom&#xff0c;减少删除真实dom和创建真实的dom的开销&…

【Docker】Docker的初步认识以及Ubuntu下的Docker环境安装、配置

前言 在当今快速迭代的软件开发与部署领域&#xff0c;容器化技术已成为不可或缺的核心力量&#xff0c;而 Docker 作为容器化技术的杰出代表&#xff0c;正以其轻量、高效、可移植的特性深刻改变着开发与运维的模式。它有效解决了 “在我机器上能运行&#xff0c;在你那里却不…

【密码学】2. 古典密码

目录2. 古典密码2.1 经典加密技术基础2.2 代换技术2.2.1 算术密码2.2.2 代换密码&#xff08;Substitution Cipher&#xff09;2.3 置换技术2.4 乘积密码2.5 历史上的教训2. 古典密码 2.1 经典加密技术基础 分类 代换&#xff08;Substitution&#xff09;&#xff1a;明文内…

CSS3文本阴影特效全攻略

CSS3文本阴影效果实现 下面我将创建一个展示各种CSS3文本阴影效果的页面&#xff0c;包含多种样式示例和代码实现。 设计思路 创建具有视觉吸引力的标题区域提供多种文本阴影效果实例显示对应的CSS代码以供参考添加交互元素让用户自定义效果 实现代码 <!DOCTYPE html&g…

JavaScript 03 严格检查模式Strict字符串类型详解

2.4 严格检查模式Strict在 JavaScript 里&#xff0c;也是 有 “作用域” 这个说法的。 所以说&#xff0c;变量 也分 全局变量 和 局部变量。 当我们 直接 把 代码 写在 script 双标签里面的时候&#xff0c;我们 JS 会认为 这只是 一个 没有名字的 函数&#xff01;&#xff…

车载诊断ECU架构

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

使用vue-pdf-embed发现某些文件不显示内容

在使用vue-pdf-embed过程中, 突然发现有些pdf文件可以正常打开, 有些文件只显示了一些数字, 并且控制台报出如下警告: Warning: loadFont - translateFont failed: “UnknownErrorException: Ensure that the cMapUrl and cMapPacked API parameters are provided.”. Warning…

【设计模式C#】状态模式(用于解决解耦多种状态之间的交互)

一种行为设计模式。特点是用类的方式去管理状态。优点&#xff1a;对每个状态进行了封装&#xff0c;提高了代码的可维护性&#xff1b;减少了条件判断语句的使用&#xff0c;降低维护成本&#xff1b;易于扩展&#xff0c;每次新增状态都无需大规模修改其他类&#xff0c;符合…

WebSocket数据通过splice保持现有DOM结构仅更新文本内容‌【防闪烁】。

文章目录 前言 一、DOM更新优化机制 ‌1.虚拟DOM复用性 2.‌响应式系统触发 二、性能对比 三、WebSocket场景实践 ‌1.防闪烁原理 2.代码实现示例 四、特殊注意事项 总结 前言 开发过程中渲染websocket返回的数据时&#xff0c;经常会遇到更新数据闪烁的问题&#xff0c;咱们可…

深入解析Hadoop的Block多副本同步机制与Pipeline复制

Hadoop分布式文件系统概述作为Hadoop生态的核心存储组件&#xff0c;HDFS&#xff08;Hadoop Distributed File System&#xff09;的设计哲学源于Google File System论文&#xff0c;其架构专门针对大规模数据集处理场景进行了优化。在理解Block多副本同步机制之前&#xff0c…

洪水预报中的序列到序列模型及其可解释性扩展

洪水预报中的序列到序列模型及其可解释性扩展 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff0c;觉得好请收藏。点击跳转到网站。 1. 引言 洪水预报是水文科学和灾害管理中的重要课题&#xff…

UniApp 优化实践:使用常量统一管理本地存储 Key,提升可维护性

在 UniApp 项目开发中&#xff0c;随着功能的增加&#xff0c;本地存储&#xff08;如 uni.setStorageSync&#xff09;的使用频率也会增加。如果直接在代码中硬编码 key 值&#xff0c;不仅容易出错&#xff0c;也难以后期维护。本文将以“自定义导航栏适配状态栏高度”为例&a…

计算机网络:(八)网络层(中)IP层转发分组的过程与网际控制报文协议 ICMP

计算机网络&#xff1a;&#xff08;八&#xff09;网络层&#xff08;中&#xff09;IP层转发分组的过程与网际控制报文协议 ICMP前言一、IP层转发分组的过程第一步&#xff1a;接收数据包并解封装第二步&#xff1a;提取目标 IP 地址第三步&#xff1a;查询路由表第四步&…

Python爬虫实战:研究concurrent-futures库相关技术

1. 引言 1.1 研究背景与意义 网络爬虫作为互联网数据采集的重要工具,在信息检索、舆情分析、学术研究等领域具有广泛应用。随着互联网数据量的爆炸式增长,传统单线程爬虫的效率已难以满足需求,并发爬虫技术成为研究热点。 1.2 相关工作 现有爬虫框架如 Scrapy、Beautifu…