opencv 图像的旋转
图像的旋转
- 1 单点旋转
- 2. 图片旋转(cv2.getRotationMatrix2D)
- 3. 插值方法
- 3.1 最近邻插值(cv2.INTER_NEAREST)
- 3.2 双线性插值(cv2.INTER_LINEAR)
- 3.3 像素区域插值(cv2.INTER_AREA)
- 3.4 双三次插值(cv2.INTER_CUBIC)
- 3.5 Lanczos插值(cv2.INTER_LANCZOS4)
- 3.6 小结
- 4. 边缘填充方式(cv2.warpAffine的属性borderMode)
- 4.1 边界复制(BODER_REPLICATE)
- 4.2 边界反射(BORDER_REFLECT)
- 4.3 边界反射101(BORDER_REFLECT_101)
- 4.4 边界常数(BORDER_CONSTANT)
- 4.5 边界包裹(BORDER_WRAP)
图像旋转是指图像以某一点为旋转中心,将图像中的所有像素点都围绕该点旋转一定的角度,并且旋转后的像素点组成的图像与原图像相同。
1 单点旋转
首先我们以最简单的一个点的旋转为例子,且以最简单的情况举例,令旋转中心为坐标系中心O(0,0),假设有一点 P 0 ( x 0 , y 0 ) P_{0}(x_{0},y_{0}) P0(x0,y0), P 0 P_{0} P0离旋转中心O的距离为r, O P 0 OP_{0} OP0与坐标轴x轴的夹角为 α \alpha α, P 0 P_{0} P0绕O顺时针旋转 θ \theta θ角后对应的点为 P ( x , y ) P(x,y) P(x,y),如下图所示:

单点旋转的原理
2. 图片旋转(cv2.getRotationMatrix2D)
明白了单个点的旋转过程之后,其实图像旋转也很好理解,就是将图像里的每个像素点都带入仿射变换矩阵里,从而得到旋转后的新坐标。在OpenCV中,要得到仿射变换矩阵可以使用cv2.getRotationMatrix2D(),通过这个函数即可直接获取到上面的旋转矩阵,
格式如下:
cv2.RotationMatrix2D(Center,Angle,Scale)
该函数需要接收的参数为:
- Center:表示旋转的中心点,是一个二维的坐标点(x,y)
- Angle:表示旋转的角度
- Scale:表示缩放比例,可以通过该参数调整图像相对于原始图像的大小变化
因此,在本实验中只需要在组件中填好图片要旋转的角度与缩放的比例即可。

代码如下:
'''图片的旋转'''img=cv2.imread(r"../15day4.10/src/1.jpg")# 求出图片的高宽和颜色h,w,c=img.shape# 给出一个旋转角度angle=45# 给出缩放倍数sacle=1# 以图片的中心作为旋转中心的仿射变换矩阵m=cv2.getRotationMatrix2D((h/2,w/2),angle=angle,scale=sacle)img_rotate=cv2.warpAffine(img,m,(w,h))cv2.imshow("img",img)cv2.imshow("img_rotate",img_rotate)cv2.waitKey(0)

但是这里会有一个问题:
- 由于三角函数的值是小数,那么其乘积也会是小数,虽然OpenCV中会对其进行取整操作,但是像素点旋转之后的取整结果也有可能重合,这样就会导致可能会在旋转的过程中丢失一部分原始的像素信息。
- 并且如果使用了scale参数进行图像的缩放的话,当图像放大时,比如一个10*10的图像放大成20*20,图像由100个像素点变成400个像素点,那么多余的300个像素点是怎么来的?而当图像缩小时,比如一个20*20的图像缩小为10*10的图像,需要丢掉300个像素点,那到底要怎么丢才能保证图像还能是一个正常的图像?
- 因此我们需要一种方法来帮我们计算旋转后的图像中每一个像素点所对应的像素值,从而保证图像的完整性,这种方法就叫做插值法。
3. 插值方法
在图像处理和计算机图形学中,插值(Interpolation)是一种通过已知数据点之间的推断或估计来获取新数据点的方法。它在图像处理中常用于处理图像的放大、缩小、旋转、变形等操作,以及处理图像中的像素值。
图像插值算法是为了解决图像缩放或者旋转等操作时,由于像素之间的间隔不一致而导致的信息丢失和图像质量下降的问题。当我们对图像进行缩放或旋转等操作时,需要在新的像素位置上计算出对应的像素值,而插值算法的作用就是根据已知的像素值来推测未知位置的像素值。本实验提供了五种常见的插值算法,下面一一介绍。
3.1 最近邻插值(cv2.INTER_NEAREST)
最近邻插值的原理
代码如下:
'''最近邻插值法'''img=cv2.imread(r"../15day4.10/src/1.jpg")# 求出图片的高宽和颜色h,w,c=img.shape# 给出一个旋转角度angle=45# 给出缩放倍数sacle=1.5#给出缩放后的图像的窗口大小frame=(2*w,2*h)# 以图片的中心作为旋转中心的仿射变换矩阵m=cv2.getRotationMatrix2D((h/2,w/2),0,sacle)img_rotate=cv2.warpAffine(img,m,frame,flags=cv2.INTER_NEAREST)cv2.imshow("img",img)cv2.imshow("img_rotate",img_rotate)cv2.waitKey(0)

3.2 双线性插值(cv2.INTER_LINEAR)
双线性插值的原理
代码如下:
'''双线性插值'''img=cv2.imread(r"../15day4.10/src/1.jpg")# 求出图片的高宽和颜色h,w,c=img.shape# 给出一个旋转角度angle=45# 给出缩放倍数sacle=1.5#给出缩放后的图像的窗口大小frame=(2*w,2*h)# 以图片的中心作为旋转中心的仿射变换矩阵m=cv2.getRotationMatrix2D((h/2,w/2),0,sacle)img_rotate=cv2.warpAffine(img,m,frame,flags=cv2.INTER_LINEAR)cv2.imshow("img",img)cv2.imshow("img_rotate",img_rotate)cv2.waitKey(0)

注意:
- 双线性插值和最近邻插值的区别就,当放大倍数为小数时,最近邻插值(cv2.INTER_NEAREST)是对结果下取整,而双线性插值(cv2.INTER_LINEAR)根据距离哪个像素点近就将取大的权值

3.3 像素区域插值(cv2.INTER_AREA)
像素区域插值主要分两种情况,缩小图像和放大图像的工作原理并不相同。
当使用像素区域插值方法进行缩小图像时,它就会变成一个均值滤波器(滤波器其实就是一个核,这里只做简单了解,后面实验中会介绍),其工作原理可以理解为对一个区域内(均值滤波器/核)的像素值取平均值。
当使用像素区域插值方法进行放大图像时,如果图像放大的比例是整数倍,那么其工作原理与最近邻插值类似;如果放大的比例不是整数倍,那么就会调用双线性插值进行放大。
其中目标像素点与原图像的像素点的对应公式如下所示:
s r c X = d s t X ∗ s r c W i d t h d s t W i d t h s r c X=d s t X*{\frac{s r c W i d t h}{d s t W i d t h}} srcX=dstX∗dstWidthsrcWidth
s r c Y = d s t Y ∗ s r c H e i g h t d s t H e i g h t s r c Y=d s t Y*{\frac{s r c H e i g h t}{d s t H e i g h t}} srcY=dstY∗dstHeightsrcHeight
代码如下:
'''像素区域插值'''img=cv2.imread(r"../15day4.10/src/1.jpg")# 求出图片的高宽和颜色h,w,c=img.shape# 给出一个旋转角度angle=45# 给出缩放倍数sacle=1.5#给出缩放后的图像的窗口大小frame=(2*w,2*h)# 以图片的中心作为旋转中心的仿射变换矩阵m=cv2.getRotationMatrix2D((h/2,w/2),0,sacle)img_rotate=cv2.warpAffine(img,m,frame,flags=cv2.INTER_AREA)cv2.imshow("img",img)cv2.imshow("img_rotate",img_rotate)cv2.waitKey(0)

像素区域插值(cv2.INTER_AREA)就是最近邻插值和双线性插值的结合
3.4 双三次插值(cv2.INTER_CUBIC)
与双线性插值法相同,该方法也是通过映射,在映射点的邻域内通过加权来得到放大图像中的像素值。不同的是,双三次插值法需要原图像中近邻的16个点来加权。
目标像素点与原图像的像素点的对应公式如下所示:
s r c X = d s t X ∗ s r c W i d t h d s t W i d t h s r c X=d s t X*{\frac{s r c W i d t h}{d s t W i d t h}} srcX=dstX∗dstWidthsrcWidth
s r c Y = d s t Y ∗ s r c H e i g h t d s t H e i g h t s r c Y=d s t Y*{\frac{s r c H e i g h t}{d s t H e i g h t}} srcY=dstY∗dstHeightsrcHeight
下面我们举例说明,假设原图像A大小为m*n,缩放后的目标图像B的大小为M*N。其中A的每一个像素点是已知的,B是未知的,我们想要求出目标图像B中每一个像素点(X,Y)的值,必须先找出像素(X,Y)在原图像A中对应的像素(x,y),再根据原图像A距离像素(x,y)最近的16个像素点作为计算目标图像B(X,Y)处像素值的参数,利用BiCubic基函数求出16个像素点的权重,图B像素(x,y)的值就等于16个像素点的加权叠加。
假如下图中的P点就是目标图像B在(X,Y)处根据上述公式计算出的对应于原图像A中的位置,P的坐标位置会出现小数部分,所以我们假设P点的坐标为(x+u,y+v),其中x、y表示整数部分,u、v表示小数部分,那么我们就可以得到其周围的最近的16个像素的位置,我们用a(i,j)(i,j=0,1,2,3)来表示,如下图所示。

然后给出BiCubic函数:

其中,a一般取-0.5或-0.75。
我们要做的就是将上面的16个点的坐标带入函数中,获取16像素所对应的权重 W ( x ) W(x) W(x)。然而BiCubic函数是一维的,所以我们需要将像素点的行与列分开计算,比如a00这个点,我们需要将x=0带入BiCubic函数中,计算a00点对于P点的x方向的权重,然后将y=0带入BiCubic函数中,计算a00点对于P点的y方向的权重,其他像素点也是这样的计算过程,最终我们就可以得到P所对应的目标图像B在(X,Y)处的像素值为:
B ( X , Y ) = ∑ i = 0 3 ∑ j = 0 3 a i j × W ( i ) × W ( j ) B(X,Y)=\sum_{i=0}^{3}\sum_{j=0}^{3}a_{i j}\times W_{(i)}\times W_{(j)} B(X,Y)=i=0∑3j=0∑3aij×W(i)×W(j)
依此办法我们就可以得到目标图像中所有的像素点的像素值。
代码如下:
'''双三次插值'''img=cv2.imread(r"../15day4.10/src/1.jpg")# 求出图片的高宽和颜色h,w,c=img.shape# 给出一个旋转角度angle=45# 给出缩放倍数sacle=1.5#给出缩放后的图像的窗口大小frame=(2*w,2*h)# 以图片的中心作为旋转中心的仿射变换矩阵m=cv2.getRotationMatrix2D((h/2,w/2),0,sacle)img_rotate=cv2.warpAffine(img,m,frame,flags=cv2.INTER_CUBIC)cv2.imshow("img",img)cv2.imshow("img_rotate",img_rotate)cv2.waitKey(0)

双三次插值(cv2.INTER_CUBIC)比双线性插值(cv2.INTER_LINEAR)对图片处理更精细,但是执行效率比较低
3.5 Lanczos插值(cv2.INTER_LANCZOS4)
Lanczos插值方法与双三次插值的思想是一样的,不同的就是其需要的原图像周围的像素点的范围变成了8*8,并且不再使用BiCubic函数来计算权重,而是换了一个公式计算权重。
首先还是目标像素点与原图像的像素点的对应公式如下所示:
s r c X = d s t X ∗ s r c W i d t h d s t W i d t h s r c X=d s t X*{\frac{s r c W i d t h}{d s t W i d t h}} srcX=dstX∗dstWidthsrcWidth
s r c Y = d s t Y ∗ s r c H e i g h t d s t H e i g h t s r c Y=d s t Y*{\frac{s r c H e i g h t}{d s t H e i g h t}} srcY=dstY∗dstHeightsrcHeight
下面我们举例说明,假设原图像A大小为m*n,缩放后的目标图像B的大小为M*N。其中A的每一个像素点是已知的,B是未知的,我们想要求出目标图像B中每一个像素点(X,Y)的值,必须先找出像素(X,Y)在原图像A中对应的像素(x,y),再根据原图像A距离像素(x,y)最近的64个像素点作为计算目标图像B(X,Y)处像素值的参数,利用权重函数求出64个像素点的权重,图B像素(x,y)的值就等于64个像素点的加权叠加。
假如下图中的P点就是目标图像B在(X,Y)处根据上述公式计算出的对应于原图像A中的位置,P的坐标位置会出现小数部分,所以我们假设P点的坐标为(x+u,y+v),其中x、y表示整数部分,u、v表示小数部分,那么我们就可以得到其周围的最近的64个像素的位置,我们用a(i,j)(i,j=0,1,2,3,4,5,6,7)来表示,如下图所示。

然后给出权重公式:

其中a通常取2或者3,当a=2时,该算法适用于图像缩小。a=3时,该算法适用于图像放大。
与双三次插值一样,这里也需要将像素点分行和列分别带入计算权重值,其他像素点也是这样的计算过程,最终我们就可以得到P所对应的目标图像B在(X,Y)处的像素值为:
S ( x , y ) = ∑ i = [ x ] − a + 1 [ x ] + a ∑ j = [ y ] − a + 1 [ y ] + a s i j L ( x − i ) L ( y − j ) S(x,y)=\sum_{i=[x]-a+1}^{[x]+a}\sum_{j=[y]-a+1}^{[y]+a}s_{i j}L(x-i)L(y-j) S(x,y)=i=[x]−a+1∑[x]+aj=[y]−a+1∑[y]+asijL(x−i)L(y−j)
其中 [ x ] [x] [x]、 [ y ] [y] [y]表示对坐标值向下取整,通过该方法就可以计算出新的图像中所有的像素点的像素值。
代码如下:
'''lanczos'''img=cv2.imread(r"../15day4.10/src/1.jpg")# 求出图片的高宽和颜色h,w,c=img.shape# 给出一个旋转角度angle=45# 给出缩放倍数sacle=1.5#给出缩放后的图像的窗口大小frame=(2*w,2*h)# 以图片的中心作为旋转中心的仿射变换矩阵m=cv2.getRotationMatrix2D((h/2,w/2),0,sacle)img_rotate=cv2.warpAffine(img,m,frame,flags=cv2.INTER_LANCZOS4)cv2.imshow("img",img)cv2.imshow("img_rotate",img_rotate)cv2.waitKey(0)

3.6 小结
最近邻插值的计算速度最快,但是可能会导致图像出现锯齿状边缘和失真,效果较差。双线性插值的计算速度慢一点,但效果有了大幅度的提高,适用于大多数场景。双三次插值、Lanczos插值的计算速度都很慢,但是效果都很好。
在OpenCV中,关于插值方法默认选择的都是双线性插值,且一般情况下双线性插值已经能满足大部分需求。
4. 边缘填充方式(cv2.warpAffine的属性borderMode)

可以看到,左图在逆时针旋转45度之后原图的四个顶点在右图中已经看不到了,同时,右图的四个顶点区域其实是什么都没有的,因此我们需要对空出来的区域进行一个填充。右图就是对空出来的区域进行了像素值为(0,0,0)的填充,也就是黑色像素值的填充。除此之外,后续的一些图像处理方式也会用到边缘填充,这里介绍五个常用的边缘填充方法。
4.1 边界复制(BODER_REPLICATE)
边界复制会将边界处的像素值进行复制,然后作为边界填充的像素值,如下图所示,可以看到四周的像素值都一样。

代码如下:
'''边界复制'''img=cv2.imread(r"../15day4.10/src/face.png")# 求出图片的高宽和颜色h,w,c=img.shape# 给出一个旋转角度angle=45# 给出缩放倍数sacle=1#给出缩放后的图像的窗口大小frame=(2*w,2*h)# 以图片的中心作为旋转中心的仿射变换矩阵m=cv2.getRotationMatrix2D((h/2,w/2),angle,sacle)img_rotate=cv2.warpAffine(img,m,frame,borderMode=cv2.BORDER_REPLICATE)cv2.imshow("img",img)cv2.imshow("img_rotate",img_rotate)cv2.waitKey(0)

4.2 边界反射(BORDER_REFLECT)
如下图所示,会根据原图的边缘进行反射。

代码如下:
'''边界反射'''img=cv2.imread(r"../15day4.10/src/face.png")# 求出图片的高宽和颜色h,w,c=img.shape# 给出一个旋转角度angle=45# 给出缩放倍数sacle=1#给出缩放后的图像的窗口大小frame=(2*w,2*h)# 以图片的中心作为旋转中心的仿射变换矩阵m=cv2.getRotationMatrix2D((h/2,w/2),angle,sacle)img_rotate=cv2.warpAffine(img,m,frame,borderMode=cv2.BORDER_REFLECT)cv2.imshow("img",img)cv2.imshow("img_rotate",img_rotate)cv2.waitKey(0)

边界反射是将原图沿着原图的边界镜像复制填充整个边框
4.3 边界反射101(BORDER_REFLECT_101)
与边界反射不同的是,不再反射边缘的像素点,如下图所示。

代码如下:
'''边界反射_101'''img=cv2.imread(r"../15day4.10/src/face.png")# 求出图片的高宽和颜色h,w,c=img.shape# 给出一个旋转角度angle=45# 给出缩放倍数sacle=1#给出缩放后的图像的窗口大小frame=(2*w,2*h)# 以图片的中心作为旋转中心的仿射变换矩阵m=cv2.getRotationMatrix2D((h/2,w/2),angle,sacle)img_rotate=cv2.warpAffine(img,m,frame,borderMode=cv2.BORDER_REFLECT_101)cv2.imshow("img",img)cv2.imshow("img_rotate",img_rotate)cv2.waitKey(0)

边界反射101是将原图以原图的边界为轴镜像复制填充整个边框
4.4 边界常数(BORDER_CONSTANT)
当选择边界常数时,还要指定常数值是多少,默认的填充常数值为0,如下图所示。
img2=cv2.warpAffine(img,M,(shape[1],shape[0]),flags=cv2.INTER_LINEAR,borderMode=cv2.BORDER_CONSTANT,borderValue=100)

代码如下:
'''边界常数'''img=cv2.imread(r"../15day4.10/src/face.png")# 求出图片的高宽和颜色h,w,c=img.shape# 给出一个旋转角度angle=45# 给出缩放倍数sacle=1#给出缩放后的图像的窗口大小frame=(2*w,2*h)# 以图片的中心作为旋转中心的仿射变换矩阵m=cv2.getRotationMatrix2D((h/2,w/2),angle,sacle)#边界常数(borderMode=cv2.BORDER_CONSTANT)的边界值(borderVlue)为0则是黑色,如果就是一个值的话是将bgr这三个值都赋值为这个值img_rotate=cv2.warpAffine(img,m,frame,borderMode=cv2.BORDER_CONSTANT,borderValue=(0,0,255))cv2.imshow("img",img)cv2.imshow("img_rotate",img_rotate)cv2.waitKey(0)

边界常数(borderMode=cv2.BORDER_CONSTANT)的边界值(borderVlue)为0则是黑色,如果就是一个值的话是将bgr这三个值都赋值为这个值
4.5 边界包裹(BORDER_WRAP)
如下图所示。

代码如下:
'''边界包裹'''img=cv2.imread(r"../15day4.10/src/face.png")# 求出图片的高宽和颜色h,w,c=img.shape# 给出一个旋转角度angle=45# 给出缩放倍数sacle=1#给出缩放后的图像的窗口大小frame=(2*w,2*h)# 以图片的中心作为旋转中心的仿射变换矩阵m=cv2.getRotationMatrix2D((h/2,w/2),angle,sacle)img_rotate=cv2.warpAffine(img,m,frame,borderMode=cv2.BORDER_WRAP)cv2.imshow("img",img)cv2.imshow("img_rotate",img_rotate)cv2.waitKey(0)

边界包裹(cv2.BORDER_WRAP)的含义就是将图片平铺填充窗口
相关文章:
opencv 图像的旋转
图像的旋转 1 单点旋转2. 图片旋转(cv2.getRotationMatrix2D)3. 插值方法3.1 最近邻插值(cv2.INTER_NEAREST)3.2 双线性插值(cv2.INTER_LINEAR)3.3 像素区域插值(cv2.INTER_AREA)3.4 双三次插值(cv2.INTER_CUBIC&#…...
【DNS】BIND 9的配置
该文档围绕BIND 9的配置与区域文件展开,介绍了BIND 9配置文件及区域文件的相关知识,以及权威名称服务器、解析器的相关内容,还阐述了负载均衡和区域文件的详细知识,具体如下: 基础配置文件: named.conf&am…...
Spring Boot常用注解详解:实例与核心概念
Spring Boot常用注解详解:实例与核心概念 前言 Spring Boot作为Java领域最受欢迎的快速开发框架,其核心特性之一是通过注解(Annotation)简化配置,提高开发效率。注解驱动开发模式让开发者告别繁琐的XML配置ÿ…...
【多线程】线程互斥 互斥量操作 守卫锁 重入与线程安全
文章目录 Ⅰ. 线程互斥概念Ⅱ. 互斥锁的概念Ⅲ. 互斥锁的接口一、互斥锁的定义二、初始化互斥锁三、销毁互斥锁四、互斥量的加锁和解锁① 加锁接口② 解锁接口五、改进买票系统💥注意事项Ⅳ. 互斥锁的实现原理一、问题引入二、复习知识三、实现原理Ⅴ. 封装锁对象 &&…...
[原创](现代Delphi 12指南):[macOS 64bit App开发]:如何使用NSString类型字符串?
[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 开发工具: Visual Studio、Delphi、XCode、…...
Python协程详解:从基础到实战
协程是Python中实现并发编程的重要方式之一,它比线程更轻量级,能够高效处理I/O密集型任务。本文将全面介绍协程的概念、原理、实现方式以及与线程、进程的对比,包含完整的效率对比代码和详细说明,帮助Python开发者深入理解并掌握协…...
学习笔记(C++篇)--- Day 4
目录 1.赋值运算符重载 1.1 运算符重载 1.2 赋值运算符重载 1.3 日期类实现 1.赋值运算符重载 1.1 运算符重载 ①当运算符被用于类类型的对象时,C语言允许我们通过通过运算符重载的形式指定新的含义。C规定类类型对象使用运算符时,必须转换成调用对…...
空闲列表:回收和再利用
空闲列表:回收和再利用 手动与自动内存管理 手动管理:程序员需要明确地分配和释放内存。自动管理:例如使用垃圾收集器(GC),它能够自动检测并回收未使用的对象,不需要程序员干预。 对于某些数据结构如B树,…...
504 nginx解决方案
当遇到 504 Gateway Time-out 错误时,通常是因为 Nginx 作为反向代理等待后端服务(如 PHP-FPM、Java 应用等)响应的时间超过了预设的超时阈值。以下是详细的解决方案,结合知识库中的信息整理而成: 一、核心原因分析 后…...
【消息队列RocketMQ】五、RocketMQ 实战应用与生态拓展
本篇文章主要将结合前面几篇文章的基础讲解,来演示RocketMQ的实际场景中的应用。 一、RocketMQ 实战应用场景 1.1 电商系统中的应用 在电商系统中,RocketMQ 承担着重要角色。以双十一大促活动为例,短时间内会产生海量的订单请求、库存…...
volatile怎么保证可见性和有序性?(个人理解)
volatile怎么保证可见性和有序性? volatile变量会在字段修饰符中显示ACC_VOLATILE。通过插入内存屏障指令,禁止指令重排序。不管前面与后面任何指令,都不能与内存屏障指令进行重排,保证前后的指令按顺序执行 。同时保证数据修改的…...
计算机组成与体系结构:直接内存映射(Direct Memory Mapping)
目录 CPU地址怎么找到真实的数据? 内存映射的基本单位和结构 1. Pages(页)——虚拟地址空间的基本单位 2. Frames(页框)——物理内存空间的基本单位 3. Blocks(块)——主存和缓存之间的数据…...
RAGFlow:构建高效检索增强生成流程的技术解析
引言 在当今信息爆炸的时代,如何从海量数据中快速准确地获取所需信息并生成高质量内容已成为人工智能领域的重要挑战。检索增强生成(Retrieval-Augmented Generation, RAG)技术应运而生,它将信息检索与大型语言模型(L…...
STM32提高篇: 蓝牙通讯
STM32提高篇: 蓝牙通讯 一.蓝牙通讯介绍1.蓝牙技术类型 二.蓝牙协议栈1.蓝牙芯片架构2.BLE低功耗蓝牙协议栈框架 三.ESP32-C3中的蓝牙功能1.广播2.扫描3.通讯 四.发送和接收 一.蓝牙通讯介绍 蓝牙,是一种利用低功率无线电,支持设备短距离通信的无线电技…...
SpringMVC处理请求映射路径和接收参数
目录 springmvc处理请求映射路径 案例:访问 OrderController类的pirntUser方法报错:java.lang.IllegalStateException:映射不明确 核心错误信息 springmvc接收参数 一 ,常见的字符串和数字类型的参数接收方式 1.1 请求路径的…...
高质量学术引言如何妙用ChatGPT?如何写提示词
目录 1、引言究竟是什么? 2、引言如何构建?? 在学术写作领域,巧妙利用人工智能来构建文章的引言和理论框架是一个尚待探索的领域。小编在这篇文章中探讨一种独特的方法,即利用 ChatGPT 作为工具来构建引言和理论框架…...
【程序员 NLP 入门】词嵌入 - 上下文中的窗口大小是什么意思? (★小白必会版★)
🌟 嗨,你好,我是 青松 ! 🌈 希望用我的经验,让“程序猿”的AI学习之路走的更容易些,若我的经验能为你前行的道路增添一丝轻松,我将倍感荣幸!共勉~ 【程序员 NLP 入门】词…...
从物理到预测:数据驱动的深度学习的结构化探索及AI推理
在当今科学探索的时代,理解的前沿不再仅仅存在于我们书写的方程式中,也存在于我们收集的数据和构建的模型中。在物理学和机器学习的交汇处,一个快速发展的领域正在兴起,它不仅观察宇宙,更是在学习宇宙。 AI推理 我们…...
各种各样的bug合集
一、连不上数据库db 1.可能是密码一大包东西不对; 2.可能是里面某个port和数据库不一样(针对于修改了数据库但是连不上的情况); 3.可能是git代码没拉对,再拉一下代码。❤ 二、没有这个包 可能是可以#注释掉。❤ …...
大模型AI的“双刃剑“:数据安全与可靠性挑战与破局之道
在数字经济蓬勃发展的浪潮中,数据要素已然成为驱动经济社会创新发展的核心引擎。从智能制造到智慧城市,从电子商务到金融科技,数据要素的深度融合与广泛应用,正以前所未有的力量重塑着产业格局与经济形态。 然而,随着…...
如何使用 CompletableFuture、Function 和 Optional 优雅地处理异步编程?
当异步遇上函数式编程,代码变得更优雅 在日常开发中,很多时候我们需要处理异步任务、函数转换和空值检查。传统的回调方式和空值判断常常让代码看起来繁琐而难以维护。幸运的是,Java 提供了 CompletableFuture、Function 和 Optional&#x…...
基于大模型的结肠癌全病程预测与诊疗方案研究
目录 一、引言 1.1 研究背景与意义 1.2 研究目的与创新点 二、结肠癌概述 2.1 流行病学特征 2.2 发病机制与危险因素 2.3 临床症状与诊断方法 三、大模型技术原理与应用现状 3.1 大模型的基本原理 3.2 在医疗领域的应用情况 3.3 在结肠癌预测中的潜力分析 四、术前…...
操作系统概述与安装
主流操作系统概述 信创平台概述 虚拟机软件介绍与安装 windows server 安装 centos7 安装 银河麒麟V10 安装 一:主流服务器操作系统 (1)Windows Server 发展历程: 1993年推出第一代 WindowsNT(企业级内核&am…...
算法设计与分析(基础)
问题列表 一、 算法的定义与特征,算法设计的基本步骤二、 算法分析的目的是什么?如何评价算法,如何度量算法的复杂性?三、 递归算法、分治法、贪婪法、动态规划法、回溯法的基本思想方法。四、 同一个问题,如TSP&#…...
多线程(线程安全)
一、线程安全的风险来源 1.1 后厨的「订单撞单」现象 场景:两服务员同时录入客人点单到同一个菜单本 问题: 订单可能被覆盖菜品数量统计错误 Java中的表现: public class OrderServlet extends HttpServlet {private int totalOrders 0…...
开发了一个b站视频音频提取器
B站资源提取器-说明书 一、功能说明 本程序可自动解密并提取B站客户端缓存的视频资源,支持以下功能: - 自动识别视频缓存目录 - 将加密的.m4s音频文件转换为标准MP3格式 - 将加密的.m4s视频文件转换为标准MP4格式(合并音视频流)…...
基于javaweb的SpringBoot校园服务平台系统设计与实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文…...
北京SMT贴片加工工艺优化要点
内容概要 在北京地区SMT贴片加工领域,工艺优化是实现高可靠电子组装的系统性工程。本文以精密化生产需求为导向,围绕制程关键节点展开技术剖析,从钢网印刷的锡膏成型控制到贴装环节的视觉定位精度,逐步构建全流程优化模型。通过分…...
PHYBench:首个大规模物理场景下的复杂推理能力评估基准
2025-04-23, 由北京大学物理学院和人工智能研究所等机构共同创建的 PHYBench 数据集,这是一个专门用于评估大型语言模型在物理场景下的复杂推理能力的高质量基准。该数据集包含 500 道精心策划的物理问题,覆盖力学、电磁学、热力学、光学、现代物理和高级…...
将输入帧上下文打包到下一个帧的预测模型中用于视频生成
Paper Title: Packing Input Frame Context in Next-Frame Prediction Models for Video Generation 论文发布于2025年4月17日 Abstract部分 在这篇论文中,FramePack是一种新提出的网络结构,旨在解决视频生成中的两个主要问题:遗忘和漂移。 具体来说,遗忘指的是在生成视…...
