Python----计算机视觉处理(Opencv:图像旋转:插值方法,边缘填充方法)
Python----计算机视觉处理(Opencv:二值化,阈值法,反阈值法,截断阈值法,OTSU阈值法)
一、边界填充
1.1、什么是边界填充
边界填充是一种在图像边缘添加额外像素的操作。这些额外的像素用于处理图像卷积、平滑 或其他涉及边界的操作,以避免边缘效应。例如,在进行卷积操作时,如果不进行边界填 充,图像边缘的像素将会缺少周围的像素信息,从而导致结果图像边缘模糊或失真。
1.2、边界填充方法
原图
BORDER_CONSTANT 常数填充
使用常数填充,通常是黑色(值为0)。
BORDER_REPLICATE 复制边界像素
这种方式会将图像的边界像素复制到图像的边界外部,产生类似边缘延伸的效果。
BORDER_REFLECT 反射边界像素
这种方式将图像的边界像素反射到外部,反射时不包括原边界像素。也就是说,边界的像素 会反转(镜像反射)到外部,但原本的边界像素不再重复。
BORDER_REFLECT_101反射边界像素
这种方式类似于 BORDER_REFLECT ,但是它反射的范围会排除原图像的第一个和最后一个像素。
BORDER_WRAP
环绕填充方式会将图像的边界像素“环绕”到另一侧。即,图像的左边会被右边的像素填充, 图像的上边会被下边的像素填充,像是在图像的四个边缘之间“连接”起来。
import cv2
# 读取图像
# cv2.imread() 函数用于从指定路径加载一张图片到内存中。
# './images/nezha.png' 是图片的文件路径。
img1 = cv2.imread('./images/nezha.png')
# 定义边界的厚度
# t, b, l, r 分别代表图像的 上 (top)、下 (bottom)、左 (left)、右 (right) 四个方向要添加的边界像素数量。
# 这里四个方向都设置为 50 像素。
t, b, l, r = (50, 50, 50, 50)
# 使用 cv2.copyMakeBorder 函数添加边界
# img1: 原始图像。
# t, b, l, r: 定义的边界厚度。
# cv2.BORDER_WRAP: 边界填充模式。
# BORDER_WRAP 模式通过重复图像本身来填充边界。它会将图像的另一侧像素“包裹”到边界上,
# 就像图像内容是周期性重复的一样。
img2 = cv2.copyMakeBorder(img1, t, b, l, r, cv2.BORDER_WRAP)
# 显示添加边界后的图像
# cv2.imshow() 函数用于在窗口中显示图像。
# 'images2' 是显示窗口的名称。
cv2.imshow('images2', img2)
# 等待按键
# cv2.waitKey(0) 表示程序将无限期等待用户的按键输入。
# 只有当用户按下任意键时,程序才会继续执行后续代码(例如关闭窗口)。
cv2.waitKey(0)
# 销毁所有OpenCV创建的窗口
# cv2.destroyAllWindows() 函数用于关闭所有由OpenCV创建的窗口。
cv2.destroyAllWindows()
1.3、copyMakeBorder函数
cv2.copymakeBorder0 是 OpenCV 中用来给图像添加边界的函数,常用于对图像进行扩展处理支持不同的边界填充方式。你可以用它来在图像周围添加空白(常用于卷积操作时)或特定的像素填充。
cv2.copyMakeBorder(src, top, bottom, left, right, borderType, value=None)
参数名 | 说明 |
---|---|
src | 输入图像,可以是灰度图像或彩色图像(numpy 数组格式)。 |
top | 上边界的宽度(像素数)。 |
bottom | 下边界的宽度(像素数)。 |
left | 左边的宽度(像素数)。 |
right | 右边的宽度(像素数)。 |
borderType | 填充类型,决定了边界如何填充。常用选项包括: |
- cv2.BORDER_CONSTANT :常数填充。 |
|
- cv2.BORDER_REPLICATE :复制边界像素填充。 |
|
- cv2.BORDER_REFLECT :反射边界像素(反射模式,不包括原边界像素)。 |
|
- cv2.BORDER_REFLECT_101 :类似 BORDER_REFLECT ,但对称反射会忽略第一个和最后一个像素。 |
|
- cv2.BORDER_WRAP :环绕填充。 |
|
value | 当 borderType=cv2.BORDER_CONSTANT 时,指定填充的颜色。默认为 0(黑色)。如果是彩色图像,可以设置为三元组(如 [0, 0, 255] 表示红色填充)。 |
二、图像融合
图像融合是将多张图像合成一张图像的过程,以便获取更丰富的信息或更高的图像质量。在 不同的应用中,图像融合的目的可能不同,如增强图像细节、减小噪声、提高图像分辨率 等。
常见的图像融合方法:
像素级融合:直接对两个或多个图像的像素值进行加权平均。
多分辨率融合:例如,使用小波变换(Wavelet Transform)将图像在不同分辨率下进行融合,能保留更多的图像细节。
特征级融合:提取图像的特征(如边缘、纹理等)后进行融合,而非直接处理像素。
import cv2
# 读取第一张图像
# cv2.imread() 函数用于从指定路径加载一张图片到内存中。
# 'apple.png' 是第一张图片的路径。
img1 = cv2.imread('./images/apple.png')
# 读取第二张图像
# 'parrot.png' 是第二张图片的路径。
img2 = cv2.imread('./images/parrot.png')
# 打印第一张图像的尺寸(高度、宽度、通道数)
# img.shape 返回一个元组,例如 (height, width, channels)。
print(img1.shape)
# 打印第二张图像的尺寸
print(img2.shape)
# 调整第一张图像的大小
# cv2.resize() 函数用于改变图像的尺寸。
# (261, 272) 是目标宽度和高度的元组 (width, height)。
# 图像融合要求参与融合的图像尺寸必须相同,因此这里将两张图都调整为相同大小。
img1 = cv2.resize(img1, (261, 272))
# 调整第二张图像的大小
img2 = cv2.resize(img2, (261, 272))
# 执行图像加权融合
# cv2.addWeighted() 函数用于实现两张图像的线性混合(也称为图像融合或透明度混合)。
# 公式为:dst = α * src1 + β * src2 + γ
# img1: 第一张输入图像。
# 0.5: 第一张图像的权重(α)。
# img2: 第二张输入图像。
# 0.5: 第二张图像的权重(β)。
# 0: 伽马值(γ),一个加到结果上的标量。这里设置为0,表示不额外增加亮度。
# 由于两张图像的权重都是0.5,这意味着它们将以50%的透明度相互叠加,形成一个半透明的效果。
img3 = cv2.addWeighted(img1, 0.5, img2, 0.5, 0)
# 显示第一张原始图像(调整大小后)
# 'images1' 是窗口的名称。
cv2.imshow('images1', img1)
# 显示第二张原始图像(调整大小后)
# 'images2' 是窗口的名称。
cv2.imshow('images2', img2)
# 显示融合后的图像
# 'images3' 是窗口的名称。
cv2.imshow('images3', img3)
# 等待按键
# cv2.waitKey(0) 表示程序将无限期等待用户的按键输入。
# 只有当用户按下任意键时,程序才会继续执行后续代码(例如关闭窗口)。
cv2.waitKey(0)
# 销毁所有OpenCV创建的窗口
# cv2.destroyAllWindows() 函数用于关闭所有由OpenCV创建的窗口。
cv2.destroyAllWindows()
addWeighted函数
addweighted 是 OpenCV 中用于图像加权融合的一个函数,广泛用于像素级图像融合。它通过对两张图像进行加权求和,产生一张新的图像。这对于实现图像的融合、过渡效果、或者图像增强等任务非常有用。
cv2.addWeighted(src1, alpha, src2, beta, gamma)
参数名 | 说明 |
---|---|
src1 | 第一张输入图像。 |
alpha | 第一张图像的权重,控制第一张图像对最终融合图像的贡献度。 |
src2 | 第二张输入图像。 |
beta | 第二张图像的权重,控制第二张图像对最终融合图像的贡献度。 |
gamma | 可选的偏移量,通常用于图像亮度的调整(例如对融合图像进行亮度增加或减少)。默认值为 0。 |
三、图像阈值
在OpenCV中,图像阈值操作是一个常见的图像处理技术,可以将图像的像素值根据设定的 阈值进行分类,通常是将图像分为前景和背景。
ret, dst = cv2.threshold(src, thresh, maxval, type)
参数名 | 说明 |
---|---|
ret |
True 或 False ,表示是否成功读取图片。 |
dst |
输出的二值化图像。 |
src |
输入图像(仅支持单通道,通常为灰度图)。 |
thresh |
阈值(0-255 之间的值,如 127)。 |
maxval |
当像素值超过(或低于)阈值时赋予的值(具体行为由 type 决定)。 |
type |
二值化操作类型,共 5 种(见下方详细对比)。 |
阈值类型(type ) |
大于阈值像素的处理 | 小于或等于阈值像素的处理 | 结果图像描述 |
---|---|---|---|
cv2.THRESH_BINARY |
设为 maxval (如 255) |
设为 0 | 亮区白色,暗区黑色 |
cv2.THRESH_BINARY_INV |
设为 0 | 设为 maxval (如 255) |
亮区黑色,暗区白色 |
cv2.THRESH_TRUNC |
截断为 thresh 值 |
保持原值 | 亮区被截断至阈值,暗区不变 |
cv2.THRESH_TOZERO |
保持原值 | 设为 0 | 亮区不变,暗区黑色 |
cv2.THRESH_TOZERO_INV |
设为 0 | 保持原值 | 亮区黑色,暗区不变 |
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取图片
img = cv2.imread("../images/ROI.png")
# 转换为灰度图
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh1 = cv2.threshold(gray_img,127,255,cv2.THRESH_BINARY )
ret,thresh2 = cv2.threshold(gray_img,127,255,cv2.THRESH_BINARY_INV )
ret,thresh3 = cv2.threshold(gray_img,127,255,cv2.THRESH_TRUNC )
ret,thresh4 = cv2.threshold(gray_img,127,255,cv2.THRESH_TOZERO )
ret,thresh5 = cv2.threshold(gray_img,127,255,cv2.THRESH_TOZERO_INV )
titles = ["Original Image","BINARY","BINARY_INV","TRUNC","TOZERO","TOZERO_INV"]
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
# 遍历在6张图片上 matplotilb
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()
cv2.waitKey(5000)
cv2.destroyAllWindows()
四、结构体Mat
4.1、Mat 的基本概念
Mat 是 OpenCV 中用于存储图像数据和矩阵数据的主要数据结构。它代表着一个 n 维的密 集数值型数组,被设计用来存储实数或复数元素,并且可以存储单通道或多通道的数据。 与传统的 IplImage 结构体相比,Mat 具有自动内存管理的优势,能有效避免内存泄漏,使 用起来更加方便和安全。
4.2、Mat 的组成部分
OpenCV 的 Mat 数据结构可以分为以下几个主要部分:
字段名 | 说明 |
---|---|
dims |
图像的维度(如 2D 图像的 dims=2 )。 |
rows |
图像的行数(高度)。 |
cols |
图像的列数(宽度)。 |
depth |
像素的位深(存储格式),例如 CV_8U (8位无符号整数)、CV_32F (32位浮点数)等。 |
channels |
图像的通道数(如 RGB/BGR 图像为 3,灰度图为 1)。 |
size |
矩阵的大小(格式为 (rows, cols) )。 |
type |
数据类型与通道的组合(如 CV_8UC3 表示 8位无符号整数 + 3通道)。 |
data |
实际存储的像素数据(通常是内存指针或数组)。 |
import cv2
img = cv2.imread("../images/ROI.png")
print("rows",img.shape[0]) #高度rows 578
print("cols",img.shape[1]) #宽度cols 398
print("channels",img.shape[2]) #通道数channels 3
print("cols",img.dtype) #数据类型cols uint8
五、深拷贝与浅拷贝
在 Python 中,深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是两种不同的对象复制 方式,主要区别在于是否复制了对象中的嵌套对象。
深拷贝 | 浅拷贝 |
img.copy() | 正常复制 |
import cv2
# 加载图片
img = cv2.imread("../images/ROI.png")
# 浅拷贝
img2 = img
# 深拷贝
img3 = img.copy()
# 修改img2
img[10:100,10:100] = [0, 0, 255]
cv2.imshow('img', img)
cv2.imshow('img2', img2)
cv2.imshow('img3', img3)
cv2.waitKey(0)
cv2.destroyAllWindows()