2.2 OpenCV随手简记(三)

图像的阈值处理定义 将图像转化为二值图像(黑白图, 也可以用于彩色图形,达到夸张的效

目的:是用来提取图像中的目标物体,将背景和噪声区分开(可以近似的认为除了目标全是噪声)

阈值处理方法:通常会设定一个阈值 T ,通过 T 将图像的像素划分为两类:大于 T 的像素群和小于 T 像素群。

  1.         先将图像转化为灰度图像,因为在灰度图像中,每个像素都只有一个灰度值用来表示当前像素的亮度。
  2.         接下来二值化处理:即将图像中的像素划分为两类颜色,一种是大于阈值 T 的,另一种是小于阈值 T 的。

应用:图像预处理(滤波)--->图像分割--->图像识别

应用示例:分离对应于我们想要分析的对象的图像的区域。该分离基于对象像素和背景像素之间的强度变化。

为了区分我们感兴趣的像素(其最终将被拒绝),我们对每个像素强度值相对于阈值进行比较(据要解决的问题确定)。

一旦我们正确分离了重要的像素,我们可以用一个确定的值来设置它们来识别它们(即我们可以为它们分配值(黑色),(白色)或适合您需要的任何值)

       

        在 OpenCV 中,为我们提供了阈值函数 threshold()来帮助我们实现二值图像的处理。

函数如下:

retval, dst = cv2.threshold(src, thresh, maxval, type, dst=None)
  • retval: 阈值
  • dst: 处理后的图像
  • src: 原图像
  • thresh: 阈值
  • maxval: 最大值
  • type: 处理类型

常用的 5 中处理类型如下:

  • cv2.THRESH_BINARY:  二值处理
  • cv2.THRESH_BINARY_INV: 反二值处理
  • cv2.THRESH_TRUNC:  截断阈值
  • cv2.THRESH_TOZERO: 阈值化为 0
  • cv2.THRESH_TOZERO_INV: 反阈值化为 0

一、二值化处理(非黑即白)

这种二值处理方式最开始需要选定一个阈值 Threshold,从 0 ~ 255 之间, 这里选择出于中间的那个数127 

接下来的处理规则就是这样的:

像素值<= 阈值 Threshold: 像素值 = 0,即设定为纯黑色

像素值>= 阈值 Threshold: 像素值 = 最大值

接下来开始写代码

import cv2 as cv
src = cv.imread("maliao.jpg") # BGR 图像转灰度
gray_img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)# 二值图像处理
Threshold = 127
r, b = cv.threshold(gray_img, Threshold, 255, cv.THRESH_BINARY)# 显示图像 cv.imshow("src", src) cv.imshow("result", b)# 等待显示 cv.waitKey(0) cv.destroyAllWindows()

二、 反二值处理

这种方式和上面的二值处理非常相似,只是把处理规则给反了一下:

  • 像素值<= 阈值 Threshold: 像素值 =最大值
  • 像素值>= 阈值 Threshold: 像素值 = 0,即设定为纯黑色
import cv2 as cvsrc = cv.imread("maliao.jpg")# BGR 图像转灰度
gray_img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)# 二值图像处理
r, b = cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY_INV)# 显示图像
cv.imshow("src", src) cv.imshow("result", b)# 等待显示 cv.waitKey(0) cv.destroyAllWindows()

从图像上可以看到,颜色和上面的二值图像正好相反,大部分的位置都变成了白色。

三、截断阈值化

这种方法还是需要先选定一个阈值 T ,图像中大于该阈值的像素点被设定为该阈值,小于该阈值的保持不变。

完整代码如下:

import cv2 as cv
src = cv.imread("maliao.jpg")# BGR 图像转灰度
gray_img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)# 二值图像处理
r, b = cv.threshold(gray_img, 127, 255, cv.THRESH_TRUNC)# 显示图像 cv.imshow("src", src) cv.imshow("result", b)# 等待显示 cv.waitKey(0) cv.destroyAllWindows()

这种方式实际上是把图片比较亮的像素处理成为阈值,其他部分保持不变。

四、阈值化为 0

这种方式还是需要先选定一个阈值 T ,将小于 T 的像素点设置为 0 黑色,其他的保持不变。

完整代码如下:

import cv2 as cvsrc = cv.imread("maliao.jpg")# BGR 图像转灰度
gray_img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
# 二值图像处理
r, b = cv.threshold(gray_img, 127, 255, cv.THRESH_TOZERO)# 显示图像
cv.imshow("src", src) cv.imshow("result", b)# 等待显示
cv.waitKey(0) cv.destroyAllWindows()

这个方法是亮的部分不改,把比较暗的部分修改为 0 

这个和前面的反二值图像很像,同样是反阈值化为 0 ,将大于等于 T 的像素点变为 0 ,其余保持不变。

完整代码如下:

import cv2 as cvsrc = cv.imread("maliao.jpg")# BGR 图像转灰度
gray_img = cv.cvtColor(src, cv.COLOR_BGR2GRAY)# 二值图像处理
r, b = cv.threshold(gray_img, 127, 255, cv.THRESH_TOZERO_INV)# 显示图像
cv.imshow("src", src)cv.imshow("result", b)# 等待显示 
cv.waitKey(0)
cv.destroyAllWindows()

接下来还是给这几种阈值处理后的图像来个全家福,让大家能有一个直观的感受,代码如下: 

import cv2 as cv
import matplotlib.pyplot as plt
# 读取图像
img=cv.imread('maliao.jpg')
lenna_img = cv.cvtColor(img,cv.COLOR_BGR2RGB)
gray_img=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 阈值化处理
ret1, thresh1=cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY)
ret2, thresh2=cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY_INV)
ret3, thresh3=cv.threshold(gray_img, 127, 255, cv.THRESH_TRUNC)
ret4, thresh4=cv.threshold(gray_img, 127, 255, cv.THRESH_TOZERO)
ret5, thresh5=cv.threshold(gray_img, 127, 255, cv.THRESH_TOZERO_INV)
# 显示结果
titles = ['Gray Img','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [gray_img, thresh1, thresh2, thresh3, thresh4, thresh5]
# matplotlib 绘图:可以同时显示多个图像,而且图像显示在命令窗口上,而不是以窗口弹出的方式显
示
for i in range(6):
plt.subplot(2, 3, i+1), plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()

 

举例2:同时显示多种阈值化操作后的图像

import cv2 as cv
import matplotlib.pyplot as plt
# 读取图像
img=cv.imread('C:\\Users\\seewo\\Desktop\\OpenCV\\photo\\beauty11.jpeg')
#lenna_img = cv.cvtColor(img,cv.COLOR_BGR2RGB)
#gray_img=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
gray_img = img
# 阈值化处理
TH = 200
ret1, thresh1=cv.threshold(gray_img, TH, 255, cv.THRESH_BINARY)
ret2, thresh2=cv.threshold(gray_img, TH, 255, cv.THRESH_BINARY_INV)
ret3, thresh3=cv.threshold(gray_img, TH, 255, cv.THRESH_TRUNC)
ret4, thresh4=cv.threshold(gray_img, TH, 255, cv.THRESH_TOZERO)
ret5, thresh5=cv.threshold(gray_img, TH, 255, cv.THRESH_TOZERO_INV)
# 显示结果
titles = ['Gray Img','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV']
images = [gray_img, thresh1, thresh2, thresh3, thresh4, thresh5]
# 封装图片显示函数:解决关闭窗口后,程序阻塞问题
def showImage(img, title='image', t=3000, esc=False):
cv.imshow(title, img)
if esc:
while cv.waitKey(100) != 27:
if cv.getWindowProperty(title,cv.WND_PROP_VISIBLE)<=0:# 如果图像窗口被
关闭,则不用等待用户按键,直接跳出
break
else:
cv.waitKey(t)
cv.destroyWindow(title) # 跳出后,关闭图像
showImage(thresh1, title='THRESH_BINARY', t=0, esc=False) # 二值化
showImage(thresh2, title='THRESH_BINARY_INV', t=0, esc=False) # 反二值化
showImage(thresh3, title='THRESH_TRUNC', t=0, esc=False) # 截断:图像整体变
暗,降低亮度的同时,浅颜色变得更浅
showImage(thresh4, title='TOZERO', t=0, esc=False) # 阈值化为0(低于阈
值0处理):深颜色沉底变黑,浅颜色不受影响
showImage(thresh5, title='THRESH_TOZERO_INV', t=0, esc=False) # 反阈值化为0(大于
阈值0处理):浅颜色沉底变黑,深颜色不受影响

 五、自适应阈值: 

        当同一幅图像上的不同部分的具有不同亮度时。这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果

cv2.adaptiveThreshold(src, maxValue, adaptive_method, threshold_type, block_size,C )

参数:

src

原图像,原图像应该是灰度图

maxValue

像素值高于(有时是小于)阈值时应该被赋予的新的像素值

adaptive_method

自适应阈值计算方法:CV_ADAPTIVE_THRESH_MEAN_C(均值) 或

CV_ADAPTIVE_THRESH_GAUSSIAN_C(高斯加权

threshold_type

阈值类型:CV_THRESH_BINARY CV_THRESH_BINARY_INV

block_size

正方形区域:用来计算阈值的象素邻域大小: 3x3, 5x5, 7x7

C 常数

CV_ADAPTIVE_THRESH_MEAN_C: 块中的均值(mean - C

CV_ADAPTIVE_THRESH_MEAN_C: 块中的加权和(gaussian) - C

 

在图像阈值化操作中,更关注的是从二值化图像中,分离目标区域和背景区域,但是仅仅通过设定固定阈值很难达到理想的分割效果。

在前面的部分我们使用是全局阈值,整幅图像采用同一个数作为阈值。当时这种方法并不适应与所有情况,尤其是当同一幅图像上的不同部分的具有不同亮度时。这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。

自适应阈值,则是根据像素的邻域块的像素值分布来确定该像素位置上的二值化阈值。这样做的好处:

  • 每个像素位置处的二值化阈值不是固定不变的,而是由其周围邻域像素的分布来决定的。
  • 亮度较高的图像区域的二值化阈值通常会较高,而亮度低的图像区域的二值化阈值则会相适应的变小。
  • 不同亮度、对比度、纹理的局部图像区域将会拥有相对应的局部二值化阈值。
  • 适合处理光照不均的图像。
  • Python+opencv代码:
  • import cv2
    image = cv2.imread("flower3.jpeg") # 读取4.27.png
    image_Gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 将4.27.png转换为灰度图像
    # 自适应阈值的计算方法为cv2.ADAPTIVE_THRESH_MEAN_C
    athdMEAM = cv2.adaptiveThreshold\
    (image_Gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 5, 3)
    # 自适应阈值的计算方法为cv2.ADAPTIVE_THRESH_GAUSSIAN_C
    athdGAUS = cv2.adaptiveThreshold\
    (image_Gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY, 5, 3)
    # 显示自适应阈值处理的结果
    cv2.imshow("MEAN_C", athdMEAM)
    cv2.imshow("GAUSSIAN_C", athdGAUS)
    cv2.waitKey() # 按下任何键盘按键后
    cv2.destroyAllWindows() # 销毁所有窗口

 

与上述5种阈值处理方法相比:

  • 自适应阈值处理:只能处理灰度图
  • 自适应阈值处理:保留了图像中更多的细节信息,更明显地保留了灰度图像主题的轮廓
    • 能更好地处理明暗分布不均的图像,获得更简单的图像效果。
  • import cv2 as cv
    import matplotlib.pyplot as plt
    # 读取图像
    img=cv.imread('beauty4.jpeg')
    gray_img=cv.cvtColor(img,cv.COLOR_BGR2GRAY)
    # 5种阈值化处理
    ret1, thresh1=cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY)
    ret2, thresh2=cv.threshold(gray_img, 127, 255, cv.THRESH_BINARY_INV)
    ret3, thresh3=cv.threshold(gray_img, 127, 255, cv.THRESH_TRUNC)
    ret4, thresh4=cv.threshold(gray_img, 127, 255, cv.THRESH_TOZERO)
    ret5, thresh5=cv.threshold(gray_img, 127, 255, cv.THRESH_TOZERO_INV)
    # 自适应阈值的计算方法为cv2.ADAPTIVE_THRESH_MEAN_C
    athdMEAM = cv.adaptiveThreshold(gray_img, 255, cv.ADAPTIVE_THRESH_MEAN_C,
    cv.THRESH_BINARY, 5, 3)
    # 自适应阈值的计算方法为cv2.ADAPTIVE_THRESH_GAUSSIAN_C
    athdGAUS = cv.adaptiveThreshold(gray_img, 255,
    cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY, 5, 3)
    # 显示结果
    titles = ['Gray Img','BINARY','BINARY_INV','TRUNC','TOZERO',\
    'TOZERO_INV','Adaptive_Mean','Adaptive_Gaussian']
    images = [gray_img, thresh1, thresh2, thresh3,\
    thresh4, thresh5,athdMEAM,athdGAUS]
    # matplotlib 绘图:可以同时显示多个图像,而且图像显示在命令窗口上,而不是以窗口弹出的方式显
    示
    for i in range(8):plt.subplot(2, 4, i+1), plt.imshow(images[i],'gray')plt.title(titles[i])plt.xticks([]),plt.yticks([])
    plt.show()

 自适应阈值处理:保留了图像中更多的细节信息,更明显地保留了灰度图像主题的轮廓

Otsu阈值处理

Ostu是一种阈值选择的算法,在面对色彩分布不均匀的图像时,阈值的选择就会变得很复杂。这时我们就不需要凭借经验去认为设定,而是根据Otsu算法来计算出最合适的阈值。

Ostu的思想很简单,属于暴力寻优的一种,分别计算选用不同灰度级作为阈值时的前景、背景、整体方差。当方差最大时,此时的阈值最好,即遍历所有可能的阈值,从中找到最合适的阈值。

Otsu’s   Binarization是一种基于直方图的二值化方法,它需要和threshold函数配合使用。

对于图像二值化的简单阈值法,我们需要自己提供一个阈值,而大津法(OTSU可以根据图像特性,选择最佳的阈值,故它也被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响。从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景图像的类间方差最大

它是按图像的灰度特性,将图像分成背景和前景两部分。因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。

应用: 是求图像全局阈值的最佳方法,应用不言而喻,适用于大部分需要求图像全局阈值的场合。

优点: 计算简单快速,不受图像亮度和对比度的影响

缺点: 对图像噪声敏感;只能针对单一目标分割;当目标和背景大小比例悬殊、类间方差函数可能呈现双峰或者多峰,这个时候效果不好。

Otsu过程:

  1. 计算图像直方图;
  2. 设定一阈值,把直方图强度大于阈值的像素分成一组,把小于阈值的像素分成另外一组;
  3. 分别计算两组内的偏移数,并把偏移数相加;
  4. 0~255依照顺序多为阈值,重复1-3的步骤,直到得到最小偏移数,其所对应的值即为结果阈值。

代码展示

选择一张偏暗的图片来测试程序。

import cv2 as cv
import matplotlib.pyplot as plt
image = cv.imread("beauty5.jpeg", cv.IMREAD_GRAYSCALE)
ret1, dst1 = cv.threshold(image, 127, 255, cv.THRESH_BINARY) # 二值化阈值处理
ret2, dst2 = cv.threshold(image, 0 , 255, cv.THRESH_OTSU) # Otsu方法
dst3 = cv.adaptiveThreshold(image, 255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY, 5, 3) # 自适应阈值
#cv.imshow("image", image)
#cv.imshow("threshold", dst1)
#cv.imshow("otsu", dst2)
#cv.imshow("GAUSSIAN_C", dst3)
titles = ['gray_orgin','Binary','Otsu','Adaptive_Gaussian']
images = [image,dst1,dst2,dst3]
for i in range(4):
plt.subplot(2,2,i+1), plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
cv.waitKey()
cv.destroyAllWindows()

 

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

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

相关文章

GSEA的算法只考虑排序吗

其实这个问题很好回答&#xff0c;只需要运行如下代码&#xff0c;如下的基因列表是顺序是完全相同&#xff0c;并且我们只是做了最基础的变换 library(clusterProfiler) library(org.Hs.eg.db)data(geneList, package"DOSE")ego1 <- gseGO(geneList geneLi…

【iOS】UI学习(二)

UI学习&#xff08;二&#xff09; 进度条和滑动条步进器与分栏控件警告对话框和提示等待器UITextFieldUITextField控件UITextFieldDelegate协议 UIScrollView布局子视图手动布局子视图自动布局子视图 进度条和滑动条 下面通过一个程序来讲解该内容&#xff1a; #import <…

Django 里的增删改查

下面是步骤 先更新 urls.py 来添加新的url from django.contrib import admin from django.urls import path from app01 import viewsurlpatterns [path(demo/, views.demo), ]在 models.py 里创建表 from django.db import models# Create your models here. class UserI…

力扣 226. 翻转二叉树

给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ struct TreeNode* invertTree(struct Tr…

[leetcode hot150]第五十七题,插入区间

题目&#xff1a; 给你一个 无重叠的 &#xff0c;按照区间起始端点排序的区间列表 intervals&#xff0c;其中 intervals[i] [starti, endi] 表示第 i 个区间的开始和结束&#xff0c;并且 intervals 按照 starti 升序排列。同样给定一个区间 newInterval [start, end] 表示…

62. UE5 RPG 近战攻击获取敌人并造成伤害

在上一篇&#xff0c;我们实现了通过AI行为树控制战士敌人靠近攻击目标触发近战攻击技能&#xff0c;并在蒙太奇动画中触发事件激活攻击的那一刻的伤害判断&#xff0c;在攻击时&#xff0c;我们绘制了一个测试球体&#xff0c;用于伤害范围。 在之前实现的火球术中&#xff0c…

HBuilderX打包uni-app项目成安卓app

目录 1、下载Android 离线SDK 2、Android Studio导入工程 3、生成签名 3.1、进入到jdk bin目录下&#xff0c;输入cmd执行命令keytool -genkey -alias wxsalias -keyalg RSA -keysize 2048 -validity 36500 -keystore wxs.keystore 生成签名 3.2、查看签名密钥keytool -lis…

Simulink从0搭建模型08-P9 While If SwitchCase模块的使用的使用

Simulink从0搭建模型08-P9 While & If & SwitchCase模块的使用的使用 今日学习内容1. While1.1. While Iterator Subsystem模块1.2. 样例11.3. 样例2 2. If2.1. if模块If Action Subsystem模块&#xff08;action) 3. Switch3.1. Switch Case模块3.2. If Action Subsys…

Java实战:文本文件复制

任务目标 本实战任务的目标是创建一个Java程序&#xff0c;用于复制指定的文本文件到另一个位置&#xff0c;并在控制台中显示复制结果。 任务步骤 创建源文件&#xff1a;在指定的路径D:\love.txt创建源文件。创建文件复制类&#xff1a;在net.huawei.student.test包中创建…

成功解决“ModuleNotFoundError: No Module Named Pycocotools”错误的全面指南

成功解决“ModuleNotFoundError: No Module Named Pycocotools”错误的全面指南 在Python的数据科学、计算机视觉和机器学习项目中&#xff0c;经常需要用到各种工具和库来加速开发过程。其中&#xff0c;pycocotools 是一个专门用于处理 COCO 数据集的库&#xff0c;它提供了多…

代理IP如何提高网站的SEO排名

目录 一、代理IP的作用 二、使用代理IP提高SEO排名的几种常见方法 1. 采集数据 2. 提交网站 3. 模拟用户行为 4. 搜索引擎优化 三、合理使用代理IP的注意事项 四、代码示例 总结 代理IP是一种可以隐藏真实IP地址的技术&#xff0c;通过使用代理IP&#xff0c;可以实现…

最大的游戏交流社区Steam服务器意外宕机 玩家服务受影响

易采游戏网6月3日消息&#xff1a;众多Steam游戏玩家报告称&#xff0c;他们无法访问Steam平台上的个人资料、好友列表和社区市场等服务。同时&#xff0c;社区的讨论功能也无法正常使用。经过第三方网站SteamDB的确认&#xff0c;&#xff0c;这一现象是由于Steam社区服务器突…

新奇css模板

引言 (csscoco.com)https://csscoco.com/inspiration/#/./init

ardupilot开发 --- 机载计算机-软件方案 篇

马儿跑马儿不吃草 0. 概述APSyncBlueOSDroneKitFlytOSMaverickROSRpanion-server结论 0. 概述 The Companion Computer software refers to the programs and tools that run on the Companion Computer. They will take in MAVLink telemetry from the Flight Controller and…

Swift 中 @preconcurrency 修饰符使用浅谈

概述 Swift 6.0 与我们越来越近了&#xff0c;如何将旧范儿的并发代码装换为严格遵守 Swift 6.0 并发模型&#xff08; Strict Concurrency&#xff09;的新代码&#xff0c;这往往使得秃头码农们又要多抓掉几根头发了。 所以&#xff0c;为了最大限度的保持新旧两个并发世界暂…

模拟人为操作并获取数据

问题 假设需要获取一个微信公众号h5应用的某些数据&#xff0c;而这个应用存在如下一些反爬措施&#xff0c;从而决定了获取数据的方式。 每一个操作都有类似埋点行为&#xff0c;这样即可收集每个用户的操作轨迹。通过轨迹正常与否&#xff0c;很容易判断一个用户是否在恶意获…

【Spring Cloud Alibaba】开源组件Nacos及安装与配置

目录 什么是NacosNacos的关键特性服务发现和服务健康监测动态配置服务动态 DNS 服务服务及其元数据管理 Nacos的架构Nacos的用户Nacos的安装预备环境准备安装方式有两种&#xff1a;源码安装和下载编译好的安装包Nacos 支持三种部署模式&#xff0c;分别是单机、集群和多集群。…

性能飙升50%,react-virtualized-list如何优化大数据集滚动渲染

在处理大规模数据集渲染时&#xff0c;前端性能常常面临巨大的挑战。本文将探讨 react-virtualized-list 库如何通过虚拟化技术和 Intersection Observer API&#xff0c;实现前端渲染性能飙升 50% 的突破&#xff01;除此之外&#xff0c;我们一同探究下该库还支持哪些新的特性…

【Git篇 二】idea中使用git合并分支(拉取分支)

idea中使用git合并分支 前言idea使用git合并分支1) 将主分支&#xff08;master&#xff09;更新到自己的分支&#xff08;dev&#xff09;① checkout到自己分支② 目标分支&#xff08;dev&#xff09;更新到当前分支&#xff08;dev_KC240524&#xff09;③ 当前分支出现“绿…

【Python】 Python网络请求库大比拼:urllib、urllib2、urllib3与requests

基本原理 在Python中&#xff0c;进行网络请求是常见的任务之一&#xff0c;无论是下载网页内容、获取API数据还是进行文件上传。Python社区提供了多种库来帮助开发者完成这些任务。其中&#xff0c;urllib、urllib2、urllib3和requests是最为流行的几个。了解它们之间的区别对…