Opencv 图像编辑与增强技术

发布于:2025-07-27 ⋅ 阅读:(17) ⋅ 点赞:(0)

目录

一、插值方法

最近邻插值

双线性插值

像素区域插值

双三次插值

Lanczos插值

二、透视变换

三、图像掩膜

四、颜色替换

五、图像加水印

六、图像噪点去除

均值滤波

方框滤波

高斯滤波

中值滤波

双边滤波

小结

总结


在图像处理和计算机图形学中,插值(Interpolation)是一种通过已知数据点之间的推断或估计来获取新数据点的方法。它在图像处理中常用于处理图像的放大、缩小、旋转、变形等操作,以及处理图像中的像素值。

图像插值算法是为了解决图像缩放或者旋转等操作时,由于像素之间的间隔不一致而导致的信息丢失和图像质量下降的问题。当我们对图像进行缩放或旋转等操作时,需要在新的像素位置上计算出对应的像素值,而插值算法的作用就是根据已知的像素值来推测未知位置的像素值。

一、插值方法

首先获取旋转矩阵。旋转矩阵的核心作用是计算图像旋转后像素的原始坐标,为插值操作提供精确的位置映射依据。

# 获取旋转矩阵
M=cv.getRotationMatrix2D((w//2,h//2),45,0.5)

最近邻插值

最近邻插值通过取映射点最近的整数坐标像素值实现,计算速度快但可能导致边缘锯齿,适用于对速度要求高而精度要求低的场景;

new_img1=cv.warpAffine(img,M,(w,h),flags=cv.INTER_NEAREST)
# 最近邻插值 + 边界复制
dst=cv.warpAffine(cat,M,(w,h))
dst1=cv.warpAffine(cat,M,(w,h),cv.INTER_NEAREST,borderMode=cv.BORDER_REPLICATE)
cv.imshow("cat1",dst1)
# 计算公式  (计算出的像素值向下取整)
srcX=dst X*{\frac{src Width}{dst Width}}

srcY=dst Y*{\frac{src Height}{dst Height}}

- dstX:目标图像中某点的x坐标,
- dstY:目标图像中某点的y坐标,
- srcWidth:原图的宽度,
- dstWidth:目标图像的宽度;
- srcHeight:原图的高度,
- dstHeight:目标图像的高度。
- 而srcX和srcY:目标图像中的某点对应的原图中的点的x和y的坐标。

双线性插值

双线性插值基于映射点周围 4 个相邻像素,在水平和垂直方向分别次线性插值得到加权平均值,效果优于最近邻,边缘更平滑且计算量适中,是常用方法;

目标点与原图像中点的计算公式

示例图

运行代码与结果

# 双线性插值   水平,垂直插两次  +边界反射
dst2=cv.warpAffine(cat,M,(w,h),cv.INTER_LINEAR,borderMode=cv.BORDER_REFLECT)
cv.imshow("cat2",dst2)

像素区域插值

像素区域插值考虑原始图像像素对目标图像的贡献区域,通过计算区域覆盖面积权重进行插值,能较好保留细节、减少锯齿,适合图像缩小以避免信息丢失;

目标像素点与原图像的像素点的对应公式

运行代码与结果

# 像素区域插值  缩小:均值滤波  放大:整数  最近邻    +边界反射101
dst3=cv.warpAffine(cat,M,(w,h),cv.INTER_AREA,borderMode=cv.BORDER_REFLECT_101)
cv.imshow("cat3",dst3)

双三次插值

双三次插值利用映射点周围 16 个像素,通过三次多项式计算权重进行复杂加权平均,边缘更平滑且细节保留更好,但计算量较大适用于印刷、高清图像缩放等对画质要求高的场景

双三次插值法需要原图像中近邻的16个点来加权,也就是4x4的网格。

 目标像素点与原图像的像素点的对应公式

BiCubic函数:

a一般取-0.5或-0.75,用于控制插值函数的形状。

# 双三次插值   16个点  4x4    +边界常数
dst4=cv.warpAffine(cat,M,(w,h),cv.INTER_CUBIC,borderMode=cv.BORDER_CONSTANT,borderValue=255)
cv.imshow("cat4",dst4)

Lanczos插值

Lanczos 插值基于 Lanczos 窗函数,使用映射点周围更多像素(通常 3×3 或 5×5 区域),通过 sinc 函数计算权重,能提供更高质量的插值效果,细节保留出色,但计算复杂度也更高,适合对图像质量有极高要求的应用。

目标像素点与原图像的像素点的对应公式

权重公式

# Lanczos插值  64个点  8x8     +边界包裹
dst5=cv.warpAffine(cat,M,(w,h),cv.INTER_LANCZOS4,borderMode=cv.BORDER_WRAP)
cv.imshow("cat5",dst5)

二、透视变换

透视变换的作用其实就是改变一下图像里的目标物体的被观察的视角。

cv2.warpPerspective(src, M, dsize, flags, borderMode)

src:输入图像。

M:透视变换矩阵。这个矩阵可以通过getPerspectiveTransform函数计算得到。

dsize:输出图像的大小。它可以是一个Size对象,也可以是一个二元组。

flags:插值方法的标记。

borderMode:边界填充的模式。

# 原图中卡片的四个角点:左上、右上、左下、右下
[[178, 100], [487, 134], [124, 267], [473, 308]]

pt1=np.float32([[178, 100], [487, 134], [124, 267], [473, 308]])
pt2=np.float32([[0,0],[shape[1],0],[0,shape[0]],[shape[1],shape[0]]])
M=cv.getPerspectiveTransform(pt1,pt2)

# 透视变换
dst=cv.warpPerspective(card,M,(shape[1],shape[0]),cv.INTER_LINEAR,borderMode=cv.BORDER_REFLECT)
cv.imshow("card",card)
cv.imshow("dst",dst)

运行结果

三、图像掩膜

掩膜(Mask)是一种在图像处理中常见的操作,它用于选择性地遮挡图像的某些部分,以实现特定任务的目标。掩膜通常是一个二值化图像,并且与原图像的大小相同,其中目标区域被设置为1(或白色),而其他区域被设置为0(或黑色),并且目标区域可以根据HSV的颜色范围进行修改。

# 读图
demo=cv.imread("../images/demo.png")

首先转为HSV颜色空间,便于我们后续的操作

# 转为hsv颜色空间
hsv=cv.cvtColor(demo,cv.COLOR_BGR2HSV)
# 创建掩膜   传hsv颜色空间下的图像
mask=cv.inRange(hsv,low,high)

定义需要掩膜出的颜色部分

# 定义颜色范围(red)
low=np.array([0,43,46])
high=np.array([10,255,255])
# 颜色提取   cv2.bitwise_and(src1,src2[,mask])  传原图
dst=cv.bitwise_and(demo,demo,mask=mask)

根据HSV颜色空间不同的值,按照上方的代码展示即可掩膜出不同的颜色部分(前提是图片中有)

四、颜色替换

由于掩膜与原图的大小相同,并且像素位置一一对应,那么我们就可以得到掩膜中白色(也就是像素值为255)区域的坐标,并将其带入到原图像中,即可得到原图中的红色区域的坐标,然后就可以修改像素值了,这样就完成了颜色的替换。

# 颜色替换   bool索引
arr=mask==255
demo[arr]=(0,255,0)
cv.imshow("demo",demo)

BGR通道(blue,green,red),在对应通道将值设为最高255即可替换对应颜色

五、图像加水印

具体的操作思想是通过将原始图片转换成灰度图,并进行二值化处理去除背景部分,得到一个类似掩膜的图像。然后将这个二值化图像与另一张图片中要添加水印的区域进行“与”运算,使得目标物体的形状出现在要添加水印的区域。最后,将得到的目标物体图像与要添加水印的区域进行相加,就完成了添加水印的操作。这样可以实现将一个图像中的某个物体或图案叠加到另一个图像上,从而实现添加水印的效果。

# 读取图片
bg=cv.imread("../images/bg.png")
logo=cv.imread("../images/logohq.png")
# 取logo的高宽
h,w=logo.shape[:2]
# 选择roi感兴趣部分
roi=bg[:h,:w]
# 转灰度
gray=cv.cvtColor(logo,cv.COLOR_BGR2GRAY)
# 二值化
# 黑logo白底 与上背景 阈值法
_,mask1=cv.threshold(gray,200,255,cv.THRESH_BINARY)
bg1=cv.bitwise_and(roi,roi,mask=mask1)
cv.imshow("mask1",mask1)
cv.imshow("bg1",bg1)
# 白logo黑底  与上logo
_,mask2=cv.threshold(gray,200,255,cv.THRESH_BINARY_INV)
logo1=cv.bitwise_and(logo,logo,mask=mask2)
cv.imshow("mask2",mask2)
cv.imshow("logo1",logo1)

# 融合
# roi[:]=cv.add(bg1,logo1)
dst=cv.add(logo1,bg1)
roi[:]=dst
cv.imshow("roi",roi)
cv.imshow("bg",bg)

六、图像噪点去除

噪声:指图像中的一些干扰因素,通常是由图像采集设备、传输信道等因素造成的,表现为图像中随机的亮度,也可以理解为有那么一些点的像素值与周围的像素值格格不入。常见的噪声类型包括高斯噪声和椒盐噪声。高斯噪声是一种分布符合正态分布的噪声,会使图像变得模糊或有噪点。椒盐噪声则是一些黑白色的像素值分布在原图像中。

# 读取滤波图片
lvbo2=cv.imread("../images/lvbo2.png")
lvbo3=cv.imread("../images/lvbo3.png")

均值滤波

均值滤波是一种最简单的滤波处理,它取的是卷积核区域内元素的均值。

在滤波算法组件中,当参数filtering_method选为均值滤波,参数component_param为ksize,代表卷积核的大小,eg:ksize=3,则代表使用3×3的卷积核。

# 均值滤波  降噪
dst1=cv.blur(lvbo2,(3,3))
cv.imshow("blur",dst1)

方框滤波

  • ksize:代表卷积核的大小,eg:ksize=3,则代表使用3×3的卷积核。

  • ddepth:输出图像的深度,-1代表使用原图像的深度

    • 图像深度是指在数字图像处理和计算机视觉领域中,每个像素点所使用的位数(bit depth),也就是用来表示图像中每一个像素点的颜色信息所需的二进制位数。图像深度决定了图像能够表达的颜色数量或灰度级。

  • normalize:当normalize为True的时候,方框滤波就是均值滤波,上式中的a就等于1/9;normalize为False的时候,a=1,相当于求区域内的像素和(图片会很亮)

# 方框滤波
dst2=cv.boxFilter(lvbo2,-1,(3,3),normalize=False)
cv.imshow("box",dst2)

高斯滤波

高斯滤波是一种常用的图像处理技术,主要用于平滑图像、去除噪声。它通过使用高斯函数(正态分布)作为卷积核来对图像进行模糊处理。

在滤波算法组件中,当参数filtering_method选为高斯滤波,参数component_param为ksize,sigmaX。

# 高斯滤波
dst3=cv.GaussianBlur(lvbo2,(3,3),1)
cv.imshow("gauss",dst3)

中值滤波

中值又叫中位数,是所有数排序后取中间的值。中值滤波没有核值,而是在原图中从左上角开始,将卷积核区域内的像素值进行排序,并选取中值作为卷积核的中点的像素值。

中值滤波就是用区域内的中值来代替本像素值,所以那种孤立的斑点,如0或255很容易消除掉,适用于去除椒盐噪声和斑点噪声。中值是一种非线性操作,效率相比前面几种线性滤波要

在滤波算法组件中,当参数filtering_method选为中值滤波,参数component_param为ksize,代表卷积核的大小,eg:ksize=3,则代表使用3×3的卷积核。

# 中值滤波
dst4=cv.medianBlur(lvbo3,1)
cv.imshow("median",dst4)

双边滤波

模糊操作基本都会损失掉图像细节信息,尤其前面介绍的线性滤波器,图像的边缘信息很难保留下来。然而,边缘(edge)信息是图像中很重要的一个特征,所以这才有了双边滤波。

双边滤波的基本思路是同时考虑将要被滤波的像素点的空域信息(周围像素点的位置的权重)和值域信息(周围像素点的像素值的权重)。

双边滤波采用了两个高斯滤波的结合,一个负责计算空间邻近度的权值(也就是空域信息),也就是上面的高斯滤波器,另一个负责计算像素值相似度的权值(也就是值域信息),也是一个高斯滤波器。

  • ksize:卷积核的大小

  • d:过滤时周围每个像素领域的直径,这里已经设置了核大小。d=9===>9x9

  • sigmaColor:在color space(色彩空间)中过滤sigma。参数越大,那些颜色足够相近的的颜色的影响越大。较大的sigmaColor值意味着更大的颜色差异将被允许参与到加权平均中,从而使得颜色相近但不完全相同的像素也能够相互影响。

  • sigmaSpace:在coordinate space(坐标空间)中过滤sigma。这个参数是坐标空间中的标准差,决定了像素位置对滤波结果的影响程度。它定义了在图像的空间域中,一个像素可以影响周围像素的最大距离。换句话说,它控制着滤波器作用的范围大小。

关于2个sigma参数:

简单起见,可以令2个sigma的值相等;

如果他们很小(小于10),那么滤波器几乎没有什么效果

如果他们很大(大于150),那么滤波器的效果会很强,使图像显得非常卡通化

关于参数d:

过大的滤波器(d>5)执行效率低。

对于实时应用,建议取d=5;

对于需要过滤严重噪声的离线应用,可取d=9;

# 双边滤波
dst5=cv.bilateralFilter(lvbo2,9,75,75)
cv.imshow("bilateral",dst5)

小结

均值,方框,高斯三种滤波为线性滤波方式(速度相对快)

中值,双边为非线性滤波方式,主要依靠逻辑性(速度相对慢)

使用高斯滤波、中值滤波或双边滤波减少噪声。高斯滤波适用于高斯噪声,中值滤波对椒盐噪声效果显著,双边滤波在平滑的同时保留边缘细节。

总结

综上所述,此次的opencv核心操作—编辑与增强等操作大致操作便是这样,若还有疑问欢迎随时在评论区提出,我会积极帮助大家解决。最后感谢您的阅读!


网站公告

今日签到

点亮在社区的每一天
去签到