当前位置: 首页 > news >正文

图像认知与OpenCV——图像预处理2

目录

一、仿射变换

图像旋转

 图像平移

图像缩放

二、插值方法

最近邻插值

双线性插值

像素区域插值

双三次插值

lanczos插值

三、边缘填充

边界复制

边界反射

边界反射101 

边界常数

边界包裹

四、透明变换

五、图像掩膜

掩膜

水印 

六、噪点消除

 均值滤波

方框滤波

高斯滤波

中值滤波

双边滤波

总结


一、仿射变换

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

  • 二维空间中,图像点坐标为(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')
cv.imshow('cat',cat)
# 获取旋转矩阵 cv2.getRotationMatrix2D(旋转中心坐标,旋转角度,缩放比例)
M = cv.getRotationMatrix2D((cat.shape[1]/2, cat.shape[0]/2), -45, 1)
# 放射变换函数 cv2.warpAffine(src, M, dsize)   dsize 输出图片大小,可以为任意大小,会自动缩放
dst = cv.warpAffine(cat, M, (cat.shape[1], cat.shape[0]))
cv.imshow('dst',dst)# 显示图片
cv.waitKey(0)
cv.destroyAllWindows()

 图像平移

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

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

    x′=x+tx

    y′=y+ty

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

  • 这里的t_x和t_y分别代表在x轴和y轴上的平移量。

示例

import cv2 as cv
import numpy as np# 读取图片
cat = cv.imread('../images/1.jpg')# 定义平移量
tx,ty = 100,100
# 定义变换矩阵
M = np.float32([[1,0,tx],[0,1,ty]])
# 仿射变换
dst = cv.warpAffine(cat,M,(cat.shape[1],cat.shape[0]))# 显示图片
cv.imshow('cat',cat)
cv.imshow('dst',dst)
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,sy = 0.6,0.5
# 定义变换矩阵
M = np.float32([[sx,0,0],[0,sy,0]])
# 仿射变换
dst = cv.warpAffine(cat,M,(cat.shape[1],cat.shape[0]))# 显示图片
cv.imshow('cat',cat)
cv.imshow('dst',dst)
cv.waitKey(0)
cv.destroyAllWindows()

二、插值方法

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

最近邻插值

放大前用点表示像素值,扩展后用方格表示像素点

如放大一倍时,一个点周围四个格会的像素值都会变为该点的像素值

CV2.INTER_NEAREST

双线性插值

当需要对图像进行变换时,特别是尺寸变化时,原始图像的某些像素坐标可能不再是新图像中的整数位置,这时就需要使用插值算法来确定这些非整数坐标的像素值。

CV2.INTER_LINEAR

 

像素区域插值

像素区域插值主要分两种情况,缩小图像和放大图像的工作原理并不相同。

缩小图像时:它就会变成一个均值滤波器,对一个区域内的像素值取平均值

放大图像时:

  • 如果图像放大的比例是整数倍,那么其工作原理与最近邻插值类似;

  • 如果放大的比例不是整数倍,那么就会调用双线性插值进行放大。

cv2.INTER_AREA

双三次插值

与双线性插值法相同,该方法也是通过映射,在映射点的邻域内通过加权来得到放大图像中的像素值。不同的是,双三次插值法需要原图像中近邻的16个点来加权,也就是4x4的网格。

cv2.INTER_CUBIC

lanczos插值

Lanczos插值方法与双三次插值的思想是一样的,不同的就是其需要的原图像周围的像素点的范围变成了8*8,并且不再使用BiCubic函数来计算权重,而是换了一个公式计算权重。

cv2.INTER_LANCZOS4

示例

import cv2 as cv# 读取图片
cat = cv.imread('../images/1.jpg')# 旋转
# 获取旋转矩阵
M= cv.getRotationMatrix2D((cat.shape[1]//2, cat.shape[0]//2), 45, 0.5)
# 仿射变换
dst = cv.warpAffine(cat,M,(cat.shape[1],cat.shape[0])) # 默认
# 最近邻插值
dst1 = cv.warpAffine(cat,M,(cat.shape[1],cat.shape[0]),cv.INTER_NEAREST)
# 双线性插值   单线性插值 插两次:水平,垂直
dst2 = cv.warpAffine(cat,M,(cat.shape[1],cat.shape[0]),cv.INTER_LINEAR)
# 像素区域插值   缩小:均值滤波  放大:整数 最近邻 不是整数 双线性 4点 2*2
dst3 = cv.warpAffine(cat,M,(cat.shape[1],cat.shape[0]),cv.INTER_AREA)
# 双三次插值  16个  4*4
dst4 = cv.warpAffine(cat,M,(cat.shape[1],cat.shape[0]),cv.INTER_CUBIC)
# lanczos  64个 8*8
dst5 = cv.warpAffine(cat,M,(cat.shape[1],cat.shape[0]),cv.INTER_LANCZOS4)cv.imshow('dst', dst)
cv.imshow('dst1', dst1)
cv.imshow('dst2', dst2)
cv.imshow('dst3', dst3)
cv.imshow('dst4', dst4)
cv.imshow('dst5', dst5)# 显示
cv.waitKey(0)
cv.destroyAllWindows()

三、边缘填充

边界复制

边界复制会将边界处的像素值进行复制,然后作为边界填充的像素值

cv.warpAffine(img,M,(w,h),cv.INTER_LANCZOS4,borderMode=cv.BORDER_REPLICATE)

 

边界反射

cv.warpAffine(img,M,(w,h),cv.INTER_LANCZOS4,borderMode=cv.BORDER_REFLECT)

 

边界反射101 

与边界反射不同的是,不反射边缘的像素点

cv.warpAffine(img,M,(w,h),cv.INTER_LANCZOS4,borderMode=cv.BORDER_REFLECT_101)

 

边界常数

统一填充常数

 当选择边界常数时,还要指定常数值是多少,默认的填充常数值为0

cv.warpAffine(img,M,(w,h), cv.INTER_LANCZOS4, borderMode=cv.BORDER_CONSTANT, borderValue=(0,0,255))

边界包裹

cv.warpAffine(img,M,(w,h),cv.INTER_LANCZOS4,borderMode=cv.BORDER_WRAP)

四、透明变换

视觉上的图像越远图像越小,通过图像矫正可以把图像变为实际的图像,类似于斜视变俯视

首先要获取要纠正区域图形的四个角的坐标

获得变换矩阵

进行纠正

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

示例

import cv2 as cv
import numpy as np# 读取图片
card = cv.imread('../images/3.png')
cv.imshow('card', card)
# 获取透视变换矩阵
# 原图卡片四个点 : [178,100],[487,134],[124,267],[473,308]
pt1 = np.float32([[178,100],[487,134],[124,267],[473,308]])
pt2 = np.float32([[0,0],[card.shape[1],0],[0,card.shape[0]],[card.shape[1],card.shape[0]]])
M = cv.getPerspectiveTransform(pt1, pt2)
dst = cv.warpPerspective(card, M, (card.shape[1], card.shape[0]),cv.INTER_LINEAR,borderMode=cv.BORDER_REFLECT)cv.imshow('dst', dst)cv.waitKey(0)
cv.destroyAllWindows()

效果

 

 

五、图像掩膜

掩膜

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

mask=cv.inRange(img,color_low,color_high)

首先转换为HSV颜色空间

定义颜色范围

制作掩膜  :在颜色范围内的替换为255,其他为0

与运算(融合,提取颜色): cv.bitwise_and(img1,img2[,mask])

 

import cv2 as cv
import numpy as np
# 读取图片
demo =  cv.imread('../images/demo.png')
demo = cv.resize(demo, (640, 640))
# 转为HSV颜色空间
hsv = cv.cvtColor(demo,cv.COLOR_BGR2HSV)
# 定义颜色范围
low = np.array([0,43,46])
high = np.array([10,255,255])
# 创建掩膜 cv.inRange(img,low,high)    传hsv空间下的图像
# 在范围内的替换为255,其他为0
mask = cv.inRange(hsv,low,high)
# 颜色提取  cv.bitwise_and(img1,img2[,mask])   传的原图
dst = cv.bitwise_and(demo,demo,mask=mask)cv.imshow('mask',mask)
cv.imshow('demo',demo)
cv.imshow('dst',dst)
cv.waitKey(0)
cv.destroyAllWindows()

 效果

水印 

图片需要灰度化

import cv2 as cv
# 读取图片
bg = cv.imread('../images/bg.png')
logo = cv.imread('../images/logohq.png')
h,w = logo.shape[0:2]  # 获取logo的宽高
roi = bg[0:h,0:w]# 转灰度
gray = cv.cvtColor(logo,cv.COLOR_BGR2GRAY)# 二值化
# 黑logo 白底   与上背景  == 黑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 == 黑底的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)
cv.imshow("roi",roi)
cv.imshow("bg",bg)# 显示
cv.waitKey(0)
cv.destroyAllWindows()

六、噪点消除

噪声:指图像中的一些干扰因素,通常是由图像采集设备、传输信道等因素造成的,表现为图像中随机的亮度。

常见的噪声类型包括高斯噪声和椒盐噪声。高斯噪声是一种分布符合正态分布的噪声,会使图像变得模糊或有噪点。椒盐噪声则是一些黑白色的像素值分布在原图像中。

滤波器:也可以叫做卷积核,与自适应二值化中的核一样,本身是一个小的区域,有着特定的核值,并且工作原理也是在原图上进行滑动并计算中心像素点的像素值。  

 均值滤波

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

方框滤波

滤波的过程与均值滤波一模一样,都采用卷积核从图像左上角开始,逐个计算对应位置的像素值,并从左至右、从上至下滑动卷积核,直至到达图像右下角,唯一的区别就是核值可能会不同。

高斯滤波

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

中值滤波

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

双边滤波

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

双边滤波明显保留了更多边缘信息

示例

import cv2 as cv# 优先考虑高斯滤波,其次使用均值滤波
# 椒盐噪声和斑点噪声使用中值滤波# 读取图片
lvbo2 = cv.imread("../images/lvbo2.png")
cv.imshow("lvbo2", lvbo2)
lvbo3 = cv.imread("../images/lvbo3.png")
cv.imshow("lvbo3", lvbo3)
# 均值滤波
dst1 = cv.blur(lvbo2, (3,3))  # 参数为图片和核大小 : 3*3
cv.imshow("dst1", dst1)
# 方框滤波    normalize=True时,就是均值滤波
dst2 = cv.boxFilter(lvbo2, -1, (3,3),normalize=False)  # -1 表示输出图片通道数和输入图片一致
cv.imshow("dst2", dst2)
# 高斯滤波
dst3 = cv.GaussianBlur(lvbo2, (3,3), 1)
cv.imshow("dst3", dst3)
# 中值滤波  用于处理椒盐噪声和斑点噪声
dst4 = cv.medianBlur(lvbo3,5)
cv.imshow("dst4", dst4)
# 双边滤波
dst5 = cv.bilateralFilter(lvbo2,7,75,75)   # 7为空间窗口大小, 50为灰度窗口大小
cv.imshow("dst5", dst5)# 显示
cv.waitKey(0)
cv.destroyAllWindows()

总结

本文系统介绍了OpenCV中的图像变换与处理技术。主要内容包括:1)仿射变换(旋转、平移、缩放)的实现方法;2)五种图像插值算法(最近邻、双线性、区域、双三次、Lanczos)的原理与应用;3)五种边缘填充方式(复制、反射、反射101、常数、包裹)的特点;4)透视变换的矫正方法;5)图像掩膜技术的实现步骤;6)常见噪声消除方法(均值、方框、高斯、中值、双边滤波)的适用场景。通过Python代码示例详细演示了各项技术的具体实现过程,为图像处理提供了全面的技术参考。

http://www.dtcms.com/a/295400.html

相关文章:

  • 记一次electron开发插件市场遇到的问题
  • Linux 简单介绍及基础命令
  • 云原生MySQL Operator开发实战(一):Operator基础与CRD设计
  • 基于Odoo的微信小程序全栈开发探索分析
  • 开源中国:以国产开源生态筑基,赋能智能研发全栈升级
  • 【王树森推荐系统】推荐系统涨指标的方法05:特殊用户人群
  • [数据结构]#7 哈希表
  • 国产化PDF处理控件Spire.PDF教程:Python 将 PDF 转换为 Markdown (含批量转换示例)
  • spring boot 整合 Spring Cloud、Kafka 和 MyBatis菜鸟教程
  • 日语学习-日语知识点小记-构建基础-JLPT-N3阶段(9):ようなN
  • C++ 中值传参和引用传参
  • rust-数据结构
  • 聚观早报 | 猿编程推动中美青少年AI实践;华为Pura 80数字版售价公布;iPhone 17 Air电池曝光
  • Redis数据类型与内部编码
  • 国产数据库拐点已至:电科金仓用“融合+AI”重新定义下一代数据底座
  • rustfs/rustfs基于 Rust 的高性能分布式存储系统
  • 进程通信----匿名管道
  • 进阶向:基于Python的本地文件内容搜索工具
  • 加入淘宝联盟内容库,以便在B站等平台被推广
  • 我的新项目又来咯!
  • iOS 抓包工具有哪些?按能力划分的实用推荐与使用心得
  • 开发运维DevOps(附电子书资料)
  • 办公自动化入门:如何高效将图片整合为PDF文档
  • 7月25日 矩阵起源亮相深圳DA数智大会,解读多模态大模型驱动的数据处理新方法
  • 如何保证GPFS文件系统的强一致性
  • PDF转Markdown - Python 实现方案与代码
  • Go进阶高并发(多线程)处理教程
  • 中小企业安全落地:低成本漏洞管理与攻击防御方案
  • 新手操作steam搬砖项目,应该如何快速起步
  • 图机器学习(19)——金融数据分析