竞赛选题 题目:基于机器视觉的图像矫正 (以车牌识别为例) - 图像畸变校正

文章目录

  • 0 简介
  • 1 思路简介
    • 1.1 车牌定位
    • 1.2 畸变校正
  • 2 代码实现
    • 2.1 车牌定位
      • 2.1.1 通过颜色特征选定可疑区域
      • 2.1.2 寻找车牌外围轮廓
      • 2.1.3 车牌区域定位
    • 2.2 畸变校正
      • 2.2.1 畸变后车牌顶点定位
      • 2.2.2 校正
  • 7 最后

0 简介

🔥 优质竞赛项目系列,今天要分享的是

基于机器视觉的图像矫正 (以车牌识别为例)

该项目较为新颖,适合作为竞赛课题方向,学长非常推荐!

🧿 更多资料, 项目分享:

https://gitee.com/dancheng-senior/postgraduate

1 思路简介

目前车牌识别系统在各小区门口随处可见,识别效果貌似都还可以。查阅资料后,发现整个过程又可以细化为车牌定位、畸变校正、车牌分割和内容识别四部分。本篇随笔主要介绍车牌定位及畸变校正两部分,在python环境下通过opencv实现。

1.1 车牌定位

目前主流的车牌定位方法从大的方面来说可以分为两类:一种是基于车牌的背景颜色特征;另一种基于车牌的轮廓形状特征。基于颜色特征的又可分为两类:一种在RGB空间识别,另一种在HSV空间识别。经测试后发现,单独使用任何一种方法,效果均不太理想。目前比较普遍的做法是几种定位方法同时使用,或用一种识别,另一种验证。本文主要通过颜色特征对车牌进行定位,以HSV空间的H分量为主,以RGB空间的R分量和B分量为辅,后续再用车牌的长宽比例排除干扰。

1.2 畸变校正

在车牌的图像采集过程中,相机镜头通常都不是垂直于车牌的,所以待识别图像中车牌或多或少都会有一定程度的畸变,这给后续的车牌内容识别带来了一定的困难。因此需要对车牌进行畸变校正,消除畸变带来的不利影响。

2 代码实现

2.1 车牌定位

2.1.1 通过颜色特征选定可疑区域

取了不同光照环境下车牌的图像,截取其背景颜色,利用opencv进行通道分离和颜色空间转换,经试验后,总结出车牌背景色的以下特征:

  • (1)在HSV空间下,H分量的值通常都在115附近徘徊,S分量和V分量因光照不同而差异较大(opencv中H分量的取值范围是0到179,而不是图像学中的0到360;S分量和V分量的取值范围是到255);

  • (2)在RGB空间下,R分量通常较小,一般在30以下,B分量通常较大,一般在80以上,G分量波动较大;

  • (3)在HSV空间下对图像进行补光和加饱和度处理,即将图像的S分量和V分量均置为255,再进行色彩空间转换,由HSV空间转换为RGB空间,发现R分量全部变为0,B分量全部变为255(此操作会引入较大的干扰,后续没有使用)。

根据以上特征可初步筛选出可疑的车牌区域。随后对灰度图进行操作,将可疑位置的像素值置为255,其他位置的像素值置为0,即根据特征对图像进行了二值化。二值化图像中,可疑区域用白色表示,其他区域均为黑色。随后可通过膨胀腐蚀等操作对图像进一步处理。

for i in range(img_h):for j in range(img_w):# 普通蓝色车牌,同时排除透明反光物质的干扰if ((img_HSV[:, :, 0][i, j]-115)**2 < 15**2) and (img_B[i, j] > 70) and (img_R[i, j] < 40):img_gray[i, j] = 255else:img_gray[i, j] = 0

在这里插入图片描述

2.1.2 寻找车牌外围轮廓

选定可疑区域并将图像二值化后,一般情况下,图像中就只有车牌位置的像素颜色为白,但在一些特殊情况下还会存在一些噪声。如上图所示,由于图像右上角存在蓝色支架,与车牌颜色特征相符,因此也被当做车牌识别了出来,由此引入了噪声。

经过观察可以发现,车牌区域与噪声之间存在较大的差异,且车牌区域特征比较明显:

  • (1)根据我国常规车牌的形状可知,车牌的形状为扁平矩形,长宽比约为3:1;

  • (2)车牌区域面积远大于噪声区域,一般为图像中最大的白色区域。

在这里插入图片描述

可以通过cv2.findContours()函数寻找二值化后图像中白色区域的轮廓。

注意:在opencv2和opencv4中,cv2.findContours()的返回值有两个,而在opencv3中,返回值有3个。视opencv版本不同,代码的写法也会存在一定的差异。

# 检测所有外轮廓,只留矩形的四个顶点
# opencv4.0, opencv2.x
contours, _ = cv2.findContours(img_bin, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
# opencv3.x
_, contours, _ = cv2.findContours(img_bin, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

这里,因为二值化图像中共有三块白色区域(车牌及两处噪声),因此返回值contours为长度为3的list。list内装有3个array,每个array内各存放着一块白色区域的轮廓信息。每个array的shape均为(n,
1, 2),即每个array存放着对应白色区域轮廓上n个点的坐标。

目前得到了3个array,即3组轮廓信息,但我们并不清楚其中哪个是车牌区域对应的那一组轮廓信息。此时可以根据车牌的上述特征筛选出车牌区域的轮廓。

#形状及大小筛选校验
det_x_max = 0
det_y_max = 0
num = 0
for i in range(len(contours)):x_min = np.min(contours[i][ :, :, 0])x_max = np.max(contours[i][ :, :, 0])y_min = np.min(contours[i][ :, :, 1])y_max = np.max(contours[i][ :, :, 1])det_x = x_max - x_mindet_y = y_max - y_minif (det_x / det_y > 1.8) and (det_x > det_x_max ) and (det_y > det_y_max ):det_y_max = det_ydet_x_max = det_xnum = i
# 获取最可疑区域轮廓点集
points = np.array(contours[num][:, 0])

最终得到的points的shape为(n, 2),即存放了n个点的坐标,这n个点均分布在车牌的边缘上

2.1.3 车牌区域定位

获取车牌轮廓上的点集后,可用cv2.minAreaRect()获取点集的最小外接矩形。返回值rect内包含该矩形的中心点坐标、高度宽度及倾斜角度等信息,使用cv2.boxPoints()可获取该矩形的四个顶点坐标。

# 获取最小外接矩阵,中心点坐标,宽高,旋转角度
rect = cv2.minAreaRect(points)
# 获取矩形四个顶点,浮点型
box = cv2.boxPoints(rect)
# 取整
box = np.int0(box)

但我们并不清楚这四个坐标点各对应着矩形的哪一个顶点,因此无法充分地利用这些坐标信息。

可以从坐标值的大小特征入手,将四个坐标与矩形的四个顶点匹配起来:在opencv的坐标体系下,纵坐标最小的是top_point,纵坐标最大的是bottom_point,
横坐标最小的是left_point,横坐标最大的是right_point。

# 获取四个顶点坐标
left_point_x = np.min(box[:, 0])
right_point_x = np.max(box[:, 0])
top_point_y = np.min(box[:, 1])
bottom_point_y = np.max(box[:, 1])left_point_y = box[:, 1][np.where(box[:, 0] == left_point_x)][0]
right_point_y = box[:, 1][np.where(box[:, 0] == right_point_x)][0]
top_point_x = box[:, 0][np.where(box[:, 1] == top_point_y)][0]
bottom_point_x = box[:, 0][np.where(box[:, 1] == bottom_point_y)][0]
# 上下左右四个点坐标
vertices = np.array([[top_point_x, top_point_y], [bottom_point_x, bottom_point_y], [left_point_x, left_point_y], [right_point_x, right_point_y]])

在这里插入图片描述
在这里插入图片描述

2.2 畸变校正

2.2.1 畸变后车牌顶点定位

要想实现车牌的畸变矫正,必须找到畸变前后对应点的位置关系。

可以看出,本是矩形的车牌畸变后变成了平行四边形,因此车牌轮廓和得出来的矩形轮廓并不契合。但有了矩形的四个顶点坐标后,可以通过简单的几何相似关系求出平行四边形车牌的四个顶点坐标。

在本例中,平行四边形四个顶点与矩形四个顶点之间有如下关系:矩形顶点Top_Point、Bottom_Point与平行四边形顶点new_top_point、new_bottom_point重合,矩形顶点Top_Point的横坐标与平行四边形顶点new_right_point的横坐标相同,矩形顶点Bottom_Point的横坐标与平行四边形顶点new_left_point的横坐标相同。

在这里插入图片描述

但事实上,由于拍摄的角度不同,可能出现两种不同的畸变情况。可以根据矩形倾斜角度的不同来判断具体是哪种畸变情况。

在这里插入图片描述

判断出具体的畸变情况后,选用对应的几何相似关系,即可轻易地求出平行四边形四个顶点坐标,即得到了畸变后车牌四个顶点的坐标。

要想实现车牌的校正,还需得到畸变前车牌四个顶点的坐标。因为我国车牌的标准尺寸为440X140,因此可规定畸变前车牌的四个顶点坐标分别为:(0,0),(440,0),(0,140),(440,140)。顺序上需与畸变后的四个顶点坐标相对应。

# 畸变情况1
if rect[2] > -45:new_right_point_x = vertices[0, 0]new_right_point_y = int(vertices[1, 1] - (vertices[0, 0]- vertices[1, 0]) / (vertices[3, 0] - vertices[1, 0]) * (vertices[1, 1] - vertices[3, 1]))new_left_point_x = vertices[1, 0]new_left_point_y = int(vertices[0, 1] + (vertices[0, 0] - vertices[1, 0]) / (vertices[0, 0] - vertices[2, 0]) * (vertices[2, 1] - vertices[0, 1]))# 校正后的四个顶点坐标point_set_1 = np.float32([[440, 0],[0, 0],[0, 140],[440, 140]])
# 畸变情况2
elif rect[2] < -45:new_right_point_x = vertices[1, 0]new_right_point_y = int(vertices[0, 1] + (vertices[1, 0] - vertices[0, 0]) / (vertices[3, 0] - vertices[0, 0]) * (vertices[3, 1] - vertices[0, 1]))new_left_point_x = vertices[0, 0]new_left_point_y = int(vertices[1, 1] - (vertices[1, 0] - vertices[0, 0]) / (vertices[1, 0] - vertices[2, 0]) * (vertices[1, 1] - vertices[2, 1]))# 校正后的四个顶点坐标point_set_1 = np.float32([[0, 0],[0, 140],[440, 140],[440, 0]])# 校正前平行四边形四个顶点坐标
new_box = np.array([(vertices[0, 0], vertices[0, 1]), (new_left_point_x, new_left_point_y), (vertices[1, 0], vertices[1, 1]), (new_right_point_x, new_right_point_y)])
point_set_0 = np.float32(new_box)

2.2.2 校正

该畸变是由于摄像头与车牌不垂直而引起的投影造成的,因此可用cv2.warpPerspective()来进行校正。

# 变换矩阵
mat = cv2.getPerspectiveTransform(point_set_0, point_set_1)
# 投影变换
lic = cv2.warpPerspective(img, mat, (440, 140))

在这里插入图片描述

import cv2import numpy as np# 预处理def imgProcess(path):img = cv2.imread(path)# 统一规定大小img = cv2.resize(img, (640,480))# 高斯模糊img_Gas = cv2.GaussianBlur(img,(5,5),0)# RGB通道分离img_B = cv2.split(img_Gas)[0]img_G = cv2.split(img_Gas)[1]img_R = cv2.split(img_Gas)[2]# 读取灰度图和HSV空间图img_gray = cv2.cvtColor(img_Gas, cv2.COLOR_BGR2GRAY)img_HSV = cv2.cvtColor(img_Gas, cv2.COLOR_BGR2HSV)return img, img_Gas, img_B, img_G, img_R, img_gray, img_HSV# 初步识别def preIdentification(img_gray, img_HSV, img_B, img_R):for i in range(480):for j in range(640):# 普通蓝色车牌,同时排除透明反光物质的干扰if ((img_HSV[:, :, 0][i, j]-115)**2 < 15**2) and (img_B[i, j] > 70) and (img_R[i, j] < 40):img_gray[i, j] = 255else:img_gray[i, j] = 0# 定义核kernel_small = np.ones((3, 3))kernel_big = np.ones((7, 7))img_gray = cv2.GaussianBlur(img_gray, (5, 5), 0) # 高斯平滑img_di = cv2.dilate(img_gray, kernel_small, iterations=5) # 腐蚀5次img_close = cv2.morphologyEx(img_di, cv2.MORPH_CLOSE, kernel_big) # 闭操作img_close = cv2.GaussianBlur(img_close, (5, 5), 0) # 高斯平滑_, img_bin = cv2.threshold(img_close, 100, 255, cv2.THRESH_BINARY) # 二值化return img_bin# 定位def fixPosition(img, img_bin):# 检测所有外轮廓,只留矩形的四个顶点contours, _ = cv2.findContours(img_bin, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)#形状及大小筛选校验det_x_max = 0det_y_max = 0num = 0for i in range(len(contours)):x_min = np.min(contours[i][ :, :, 0])x_max = np.max(contours[i][ :, :, 0])y_min = np.min(contours[i][ :, :, 1])y_max = np.max(contours[i][ :, :, 1])det_x = x_max - x_mindet_y = y_max - y_minif (det_x / det_y > 1.8) and (det_x > det_x_max ) and (det_y > det_y_max ):det_y_max = det_ydet_x_max = det_xnum = i# 获取最可疑区域轮廓点集points = np.array(contours[num][:, 0])return points#img_lic_canny = cv2.Canny(img_lic_bin, 100, 200)def findVertices(points):# 获取最小外接矩阵,中心点坐标,宽高,旋转角度rect = cv2.minAreaRect(points)# 获取矩形四个顶点,浮点型box = cv2.boxPoints(rect)# 取整box = np.int0(box)# 获取四个顶点坐标left_point_x = np.min(box[:, 0])right_point_x = np.max(box[:, 0])top_point_y = np.min(box[:, 1])bottom_point_y = np.max(box[:, 1])left_point_y = box[:, 1][np.where(box[:, 0] == left_point_x)][0]right_point_y = box[:, 1][np.where(box[:, 0] == right_point_x)][0]top_point_x = box[:, 0][np.where(box[:, 1] == top_point_y)][0]bottom_point_x = box[:, 0][np.where(box[:, 1] == bottom_point_y)][0]# 上下左右四个点坐标vertices = np.array([[top_point_x, top_point_y], [bottom_point_x, bottom_point_y], [left_point_x, left_point_y], [right_point_x, right_point_y]])return vertices, rectdef tiltCorrection(vertices, rect):# 畸变情况1if rect[2] > -45:new_right_point_x = vertices[0, 0]new_right_point_y = int(vertices[1, 1] - (vertices[0, 0]- vertices[1, 0]) / (vertices[3, 0] - vertices[1, 0]) * (vertices[1, 1] - vertices[3, 1]))new_left_point_x = vertices[1, 0]new_left_point_y = int(vertices[0, 1] + (vertices[0, 0] - vertices[1, 0]) / (vertices[0, 0] - vertices[2, 0]) * (vertices[2, 1] - vertices[0, 1]))# 校正后的四个顶点坐标point_set_1 = np.float32([[440, 0],[0, 0],[0, 140],[440, 140]])# 畸变情况2elif rect[2] < -45:new_right_point_x = vertices[1, 0]new_right_point_y = int(vertices[0, 1] + (vertices[1, 0] - vertices[0, 0]) / (vertices[3, 0] - vertices[0, 0]) * (vertices[3, 1] - vertices[0, 1]))new_left_point_x = vertices[0, 0]new_left_point_y = int(vertices[1, 1] - (vertices[1, 0] - vertices[0, 0]) / (vertices[1, 0] - vertices[2, 0]) * (vertices[1, 1] - vertices[2, 1]))# 校正后的四个顶点坐标point_set_1 = np.float32([[0, 0],[0, 140],[440, 140],[440, 0]])# 校正前平行四边形四个顶点坐标new_box = np.array([(vertices[0, 0], vertices[0, 1]), (new_left_point_x, new_left_point_y), (vertices[1, 0], vertices[1, 1]), (new_right_point_x, new_right_point_y)])point_set_0 = np.float32(new_box)return point_set_0, point_set_1, new_boxdef transform(img, point_set_0, point_set_1):# 变换矩阵mat = cv2.getPerspectiveTransform(point_set_0, point_set_1)# 投影变换lic = cv2.warpPerspective(img, mat, (440, 140))return licdef main():path = 'F:\\Python\\license_plate\\test\\9.jpg'# 图像预处理img, img_Gas, img_B, img_G, img_R, img_gray, img_HSV = imgProcess(path)# 初步识别img_bin  = preIdentification(img_gray, img_HSV, img_B, img_R)points = fixPosition(img, img_bin)vertices, rect = findVertices(points)point_set_0, point_set_1, new_box = tiltCorrection(vertices, rect)img_draw = cv2.drawContours(img.copy(), [new_box], -1, (0,0,255), 3)lic = transform(img, point_set_0, point_set_1)# 原图上框出车牌cv2.namedWindow("Image")cv2.imshow("Image", img_draw)# 二值化图像cv2.namedWindow("Image_Bin")cv2.imshow("Image_Bin", img_bin)# 显示校正后的车牌cv2.namedWindow("Lic")cv2.imshow("Lic", lic)# 暂停、关闭窗口cv2.waitKey(0)cv2.destroyAllWindows()if __name__ == '__main__':main()

在这里插入图片描述

7 最后

🧿 更多资料, 项目分享:

https://gitee.com/dancheng-senior/postgraduate

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

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

相关文章

yolov8-pose姿势估计,站立识别

系列文章目录 基于yolov8-pose的姿势估计模式,实现站姿,坐姿,伏案睡姿识别,姿态动作识别接口逻辑作参考。本文以学习交流,分享,欢迎留言讨论优化。 yoloPose-姿势动作识别 系列文章目录前言一、环境安装二、使用yolov8-pose1.导入模型,预测图像三.姿势动作识别之站立总…

人工智能_机器学习053_支持向量机SVM目标函数推导_SVM条件_公式推导过程---人工智能工作笔记0093

然后我们再来看一下支持向量机SVM的公式推导情况 来看一下支持向量机是如何把现实问题转换成数学问题的. 首先我们来看这里的方程比如说,中间的黑线我们叫做l2 那么上边界线我们叫l1 下边界线叫做l3 如果我们假设l2的方程是上面这个方程WT.x+b = 0 那么这里 我们只要确定w和…

<Linux> 文件理解与操作

目录 前言&#xff1a; 一、关于文件的预备知识 二、C语言文件操作 1. fope 2. fclose 3. 文件写入 3.1 fprintf 3.2 snprintf 三、系统文件操作 1. open 2. close 3. write 4. read 四、C文件接口与系统文件IO的关系 五、文件描述符 1. 理解文件描述符 2. 文…

一则 MongoDB 副本集迁移实操案例

文中详细阐述了通过全量 增量 Oplog 的迁移方式&#xff0c;完成一套副本集 MongoDB 迁移的全过程。 作者&#xff1a;张然&#xff0c;DBA 数据库技术爱好者~ 爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源。 本文约 900…

python炒股自动化(1),量化交易接口区别

要实现股票量化程序化自动化&#xff0c;就需要券商提供的API接口&#xff0c;重点是个人账户小散户可以申请开通&#xff0c;上手要简单&#xff0c;接口要足够全面&#xff0c;功能完善&#xff0c;首先&#xff0c;第一步就是要找对渠道和方法&#xff0c;这里我们不讨论量化…

linux 内核等待队列

等待队列在Linux内核中用来阻塞或唤醒一个进程&#xff0c;也可以用来同步对系统资源的访问&#xff0c;还可以实现延迟功能 在软件开发中任务经常由于某种条件没有得到满足而不得不进入睡眠状态&#xff0c;然后等待条件得到满足的时候再继续运行&#xff0c;进入运行状态。这…

网络安全--基于Kali的网络扫描基础技术

文章目录 1. 标准ICMP扫描1.1使用Ping命令1.1.1格式1.1.2实战 1.2使用Nmap工具1.2.1格式1.2.2实战1.2.2.1主机在线1.2.2.2主机不在线 1.3使用Fping命令1.3.1格式1.3.2实战 2. 时间戳查询扫描2.1格式2.2实战 3. 地址掩码查询扫描3.1格式3.2实战 2. TCP扫描2.1TCP工作机制2.2TCP …

位运算总结

文章目录 &#x1f348;1. 基础位运算&#x1f34c;2. 给一个数n&#xff0c;确定它的二进制表示中的第x位是0还是1&#x1f34f;3. 将一个数n的二进制表示的第x位修改成1&#x1f353;4. 将一个数的n的二进制表示的第x位修改成0&#x1f954;5. 位图的思想&#x1fad2;6. 提前…

医保移动支付程序开发

作为公司最苦命的开发&#xff0c;年初接到任务开发医保移动支付程序&#xff08;微信小程序和支付宝小程序&#xff09;&#xff0c;为医疗机构提供线上医保结算。好家伙&#xff0c;我一看解压后资料大于一个G&#xff0c;内心无比的惊慌。 一、技术流程图 图太大了显示不全需…

0-1背包的初始化问题

题目链接 这道题的状态转移方程比较易于确定。dp[i][j]表示能放前i个物品的情况下&#xff0c;容量为j时能放物品的数量&#xff08;这道题歌曲数量对应物品数量&#xff0c;容量对应时间&#xff09;。 技巧&#xff08;收获&#xff09; 二维dp数组可以视情况优化为一维dp数组…

Linux——vim编辑文件时——.swp文件解决方案

test.cpp样例 当我们vim test.cpp进入编辑文件。 却忘记了保存退出 再次进入就会出现一下画面 当你摁下Enter键位 出现以下几个选项 O——是只读不写 E——是正常打开文件但不会载入磁盘内容 R——覆盖——是加载存储磁盘的文件(当我们忘记保存时&#xff0c;系统会自动帮我…

事件代理?

1.什么是事件代理&#xff1f; 事件代理也叫事件委托&#xff0c;只指定一个事件处理程序&#xff0c;就可以管理某一类型得事件。 可以简单理解为&#xff0c;事件代理就是将本应该绑定子元素事件绑定给父元素代理。它的优点就是&#xff1a;减少事件得执行&#xff0c;减少浏…

CentOS 7 部署 MariaDB 的 2 种方法

有两种安装 MariaDB 服务器的方法。您可以安装 CentOS 7 存储库中可用的默认版本&#xff0c;也可以通过手动添加 MariaDB 存储库来安装最新版本。 如果安装过MariaDB或MySQL&#xff0c;使用以下命令彻底删除它们: yum remove mariadb* yum remove mysql* 方法一: 使用 Yum…

Make Pixels Dance: High-Dynamic Video Generation论文解析

高动态视频生成的新进展 Make Pixels Dance: High-Dynamic Video Generation高动态视频生成的新进展前言视频生成模式摘要论文十问实验数据集定量评估指标消融研究 训练和推理技巧训练技术推理技术 更多的应用 Make Pixels Dance: High-Dynamic Video Generation 高动态视频生…

VBA技术资料MF87:创建固定顺序名称的一组文件夹

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。我的教程一共九套&#xff0c;分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的入门&#xff0c;到…

gRPC Java、Go、PHP使用例子

文章目录 1、Protocol Buffers定义接口1.1、编写接口服务1.2、Protobuf基础数据类型 2、服务器端实现2.1、生成gRPC服务类2.2、Java服务器端实现 3、java、go、php客户端实现3.1、Java客户端实现3.2、Go客户端实现3.3、PHP客户端实现 4、运行效果 本文例子是在Window平台测试&a…

Unity UGUI图片锯齿严重怎么解决

在开发的时候&#xff0c;发现图片锯齿严重&#xff0c;打包到移动端或者在编辑器都这样&#xff0c;如下图 原因&#xff1a; 查了一些资料&#xff0c;找到了原因如下&#xff1a;关于为什么会发生这种情况&#xff1a;看起来你的源资源比你在屏幕上显示的大小大得多。所以当…

深入浅出 Vue 中的插槽 slot

深入浅出 Vue 中的插槽 slot start 最近被问到好几次 Vue 中的插槽相关知识&#xff0c;掌握的还是有些不全面。抱着重新学习的心态&#xff0c;写这篇博客。首先对基础知识做一个回顾&#xff0c;然后再对源码实现做一个学习。作者&#xff1a;番茄编写时间&#xff1a;2023…

STM32_10(I2C)

I2C通信 I2C&#xff08;Inter IC Bus&#xff09;是由Philips公司开发的一种通用数据总线两根通信线&#xff1a;SCL&#xff08;Serial Clock&#xff09;、SDA&#xff08;Serial Data&#xff09;同步&#xff0c;半双工带数据应答支持总线挂载多设备&#xff08;一主多从…

QAC支持的静态度量属性

上面介绍了Coverity支持的12个度量属性&#xff0c;下面我们看看QAC这款工具支持的度量属性。下面分成3类&#xff0c;函数度量、文件度量和类度量。 函数度量指标不多&#xff0c;一共有8个。 文件度量度量指标一共10个&#xff0c;如下表。 类度量指标一个8个&#xff0c;如…