2. OpenCV基础图像处理

1. 窗口创建

OpenCV(open source computer vision library)是一个基于BSD许可(开源)发行的跨平台计算机视觉库
  • OpenCV窗口创建函数:cv.namedWindow()
  • OpenCV窗口大小重设:cv.resizeWindow()
  • 实验代码
import cv2 as cv

# 创建窗口(窗口大小自动)
cv.namedWindow('new', cv.WINDOW_AUTOSIZE)
# cv.WINDOW_AUTOSIZE不支持重设窗口大小
cv.imshow('new', 0)
cv.waitKey(0)
cv.destroyAllWindows()
  • 实验结果

在这里插入图片描述

  • 实验代码
import cv2 as cv

# cv.WINDOW_NORMAL支持窗口大小重新设置
cv.namedWindow('new', cv.WINDOW_NORMAL)
cv.resizeWindow("new", 640, 480)
cv.imshow('new', 0)
cv.waitKey(0)
cv.destroyAllWindows()
  • 实验结果
    在这里插入图片描述

2. 图像读取

  • 图像读取:cv.imread(图片路径)
    OpenCV读取的图像格式是BGR(不是RGB)

图像显示:imshow(窗口命名, 读取的图片)
waitKey()函数:等待用户触发函数

waitKey(0) 函数无限长,等待用户按下任意键后继续执行(返回按键ASCII码)
waitKey(5000) 函数等待5000ms后自动关闭窗口(期间用户可按下任意键,返回按键ASCII码),返回-1
此函数容易导致Python无响应,需加上destroyAllWindows()函数
destroyAllWindows()删除窗口

  • 拓展:Python中计算ASCII码的函数ord(‘字符’)
  • 实验代码
# 图像读取
import cv2 as cv

img = cv.imread('../picture/08.jpg')
cv.imshow("img", img)
cv.waitKey(0)
cv.destroyAllWindows()
  • 实验结果
    在这里插入图片描述
cv.imread()的三种读取模式

cv.IMREAD_COLOR:读取彩色图像,任何图像的透明度都会被忽略(OpenCV默认模式)(1)
cv.IMREAD_GRAYSCALE:以灰度模式加载图像(亦可以直接给0)
cv.IMREAD_UNCHANGED:被读取的图像,包括 alpha 通道(-1)

  • 实验代码
# 图像读取
import cv2 as cv
import numpy as np

# 彩色图cv.IMREAD_COLOR等价于1
img_color = cv.imread('../picture/08.jpg', cv.IMREAD_COLOR)
# 灰度图cv.IMREAD_GRAYSCALE等价于0
# cv.cvtColor转化为三通道
img_gray = cv.cvtColor(cv.imread('../picture/08.jpg', 0), cv.COLOR_GRAY2RGB)
# 包含alpha通道的彩色图cv.IMREAD_UNCHANGED等价于-1
img_unchanged = cv.imread('../picture/08.jpg', cv.IMREAD_UNCHANGED)
# 拼接显示
imgs = np.hstack((img_color, img_gray, img_unchanged))
cv.imshow("img", imgs)
cv.waitKey(0)
cv.destroyAllWindows()
  • 实验结果
    在这里插入图片描述

3. OpenCV图像基本操作

3.1 颜色转换cv.cvtColor()
OpenCV中的颜色转换模型:RGB模型、HSV模型、Lab模型、YUV模型、GRAY模型等
  • RGB模型: OpenCV (BGR) --蓝色(Blue),绿色(Green),红色(Red)
  • HSV模型:HSV模型更加符合人类感知颜色的方式(颜色、深浅以及亮暗)–色度(Hue),饱和度(Saturation),亮度(Value)
  • Lab生理特征的颜色模型:L表示亮度(Luminosity),a和b是两个颜色通道,两者的取值区间都是由-128到+127,其中a通道数值由小到大对应的颜色是从绿色变成红色,b通道数值由小到大对应的颜色是由蓝色变成黄色,颜色空间为一个球体
  • YUV模型:电视信号系统所采用的颜色编码方式–亮度(Y),红色分量与亮度的信号差值(U),蓝色与亮度的差值(V)
  • GRAY灰度图像的模型:灰度图像只有单通道,灰度值根据图像位数不同由0到最大依次表示由黑到白(相同尺寸相同压缩格式所占容量小,易于采集,便于传输)
  • 实验代码
# 查看颜色转换方式
import cv2 as cv

print("OpenCV版本", cv.__version__)
flags = [i for i in dir(cv) if i.startswith('COLOR_')]
print("颜色转换方式总数:", len(flags), "\n", flags)
  • 实验结果
    在这里插入图片描述
3.2 1/3灰度级图像(灰度图像)
  • 实验代码
import cv2 as cv
import numpy as np

# 灰度图像(各个像素值的1/3)
ratio = 1.0 / 3.0
img = cv.imread('../picture/08.jpg')
# 数据类型转换
int32_img = img.astype(np.int32)
# 将各个通道的数据除以1/3叠加后转换成uint8即可得到灰度图像
img_gray = (ratio * (int32_img[..., 0] + int32_img[..., 1] + int32_img[..., 2])).astype(np.uint8)

cv.imshow('gray', img_gray)
cv.waitKey(0)
cv.destroyAllWindows()
  • 实验结果
    在这里插入图片描述

4. 像素操作

OpenCV(open source computer vision library)彩色图像(h * w * c的矩阵)--h为图像高(相当于矩阵的行),w为图像宽(相当于矩阵列),c为通道数
  • 实验代码
import cv2 as cv
import numpy as np

img = cv.imread("../picture/08.jpg")
h, w, c = img.shape
# 图像基本属性
print("图像高:", h, "\n图像宽:", w, "\n通道数(RGB三通道):", c)
print("图像大小(像素总数:h*w*c)=", img.size)
print("像素数据类型:", img.dtype)

# 访问单像素单个通道值
print("访问第99(从0开始)行,99列R通道值:", img.item(100, 100, 2))

# 修改值
img.itemset((100, 100, 2), 100)
print("第99行,99列R通道值(修改后):", img.item(100, 100, 2))
  • 实验结果
    在这里插入图片描述
4.0 图像通道拆分

当使用OpenCV的 imshow(某通道) 函数,默认三通道相同,即查看R通道时为imshow(R,G,B) 实际为 imshow(R,R,R)–> 三个通道值相同时,显示为灰度图
合并出红色通道的图:merge(R, 零矩阵, 零矩阵)

  • 实验代码
import cv2 as cv
import numpy as np

img = cv.imread("../picture/08.jpg")

# 通道拆分合并
B, G, R = cv.split(img)

# 创建与img相同大小的零矩阵
zeros = np.zeros(img.shape[:2], dtype="uint8")

# 图像拼接显示
imgs = np.hstack((cv.merge([B, zeros, zeros]), 
                 cv.merge([zeros, G, zeros]), 
                 cv.merge([zeros, zeros, R])))
cv.imshow("imgs", imgs)
cv.waitKey(0)
cv.destroyAllWindows()
  • 实验结果

在这里插入图片描述

5. 图像几何变换

5.1 resize缩放
缩放即调整图片的大小,属于广义上的仿射变换,包括平移(transform)、旋转(rotate)等

cv.resize() 函数(指定缩放后的图像大小)
cv2.resize(InputArray src, OutputArray dst, Size, fx, fy, interpolation)

参数含义
InputArray src输入原图
OutputArray dst输出图像(一般不传参或者设成 None)
Size输出图像尺寸
fx, fyx 和 y 方向上的缩放比例
interpolation插值方式表示代码(int 数值,一般用 OpenCV 内置的参数代号以提高可读性)
  • 实验代码
import cv2 as cv

img = cv.imread('../picture/03.jpg')
print("原图大小:", img.shape)
cv.imshow("img", img)

"""
fx, fy为缩放比例(0.5倍(缩小为原图的一半),2倍放大)
"""

dst = cv.resize(img,None,fx=0.5, fy=0.5, interpolation = cv.INTER_CUBIC)
print("长宽缩小为原图1/2(仅取整数):", dst.shape)
# 显示图像
cv.imshow("dst" , dst)
cv.waitKey(0)
cv.destroyAllWindows()
  • 实验结果
原图大小: (675, 1200, 3)
长宽缩小为原图1/2(仅取整数): (338, 600, 3)

在这里插入图片描述

5.2 warpAffine仿射变换
仿射变换(Affine Transformation)
在向量空间中进行一次线性变换(乘以一个矩阵)和一次平移(加上一个向量),变换到另一个向量空间的过程(线性变换和平移变换的叠加)
性质不变性:
(1)凸性
(2)共线性:若几个点变换前在一条线上,则仿射变换后仍然在一条线上
(3)平行性:若两条线变换前平行,则变换后仍然平行
(4)共线比例不变性:变换前一条线上两条线段的比例,在变换后比例不变
  • cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]])
参数含义
src输入原图
M变换矩阵 (2*3的矩阵)
dsize输出图像大小
flags插入值方法(int 类型)
borderMode边界像素模式(int)
borderValue边界填充值
flages方式:
默认flags=cv2.INTER_LINEAR(线性插值)
cv2.INTER_NEAREST(最近邻插值)
cv2.INTER_AREA (区域插值)
cv2.INTER_CUBIC(三次样条插值)
cv2.INTER_LANCZOS4(Lanczos插值)

获取仿射变换矩阵

  • cv2.getAffineTransform(pts1,pts2) 函数
参数含义
pts1选取的原图像的三个点坐标
pts2变换后相应三个点的坐标
  • 实验代码
import cv2 as cv
import numpy as np

img = cv.imread('../picture/14.jpg')
height, width = img.shape[:2]

# 在原图像和目标图像上各选择三个点
src = np.float32([[0, 0], [0, height], [width, 0]])
dst = np.float32([[0, 0], [100, height - 100], [width - 100, 100]])

# 得到变换矩阵
transform = cv.getAffineTransform(src, dst)
print("变换矩阵M:", transform.shape)

# 进行仿射变换
dst = cv.warpAffine(img, transform, (width, height))

# 显示
imgs = np.hstack([img, dst])
cv.imshow("imgs", imgs)
cv.waitKey(0)
cv.destroyAllWindows()
  • 实验结果
    在这里插入图片描述
5.2.1 仿射变换 平移(transform)
  • 实验代码
import cv2 as cv
import numpy as np

img = cv.imread('../picture/13.jpg')
# 获取图像的长宽
height, width = img.shape[:2]
# 平移指定像素(向右,向下各平移50像素)
tx, ty = 50, 50
# 创建平移矩阵
translation_matrix = np.array([[1, 0, tx], [0, 1, ty]], dtype=np.float32)
# 将平移应用于图像
translated_img = cv.warpAffine(src=img,
                                  M=translation_matrix,
                                  dsize=(width, height))

print("原图大小:", img.shape)
print("平移后的大小:", translated_img.shape)

imgs = np.hstack((img, translated_img))
cv.imshow('imgs', imgs)
cv.waitKey(0)
  • 实验结果
原图大小: (519, 533, 3)
平移后的大小: (519, 533, 3)

在这里插入图片描述

5.2.2 仿射变换 旋转(rotation)
以图像的中心为原点,旋转一定的角度(图像上的所有像素都将旋转一个相同的角度)

① 构建旋转矩阵进行任意角度旋转getRotationMatrix2D()

  • cv2.getRotationMatrix2D(center, angle, scale)
参数含义
center图片的旋转中心
angle旋转角度
scale缩放比例

scale 0.5表示缩小为原来的一半,也能表示旋转方向,正数表示逆时针,负数表示顺时针旋转

  • 实验代码
import cv2 as cv
import numpy as np

img = cv.imread('../picture/14.jpg')
rows, cols = img.shape[:2]
# 构建旋转矩阵(逆时针旋转45度,且缩小为原图的一半)
M = cv.getRotationMatrix2D((cols / 2.0, rows / 2.0), 45, -0.5)
img_rotate = cv.warpAffine(img, M, (cols, rows), borderValue=(0, 0, 0))

imgs = np.hstack((img, img_rotate))
cv.imshow('imgs', imgs)
cv.waitKey(0)
cv.destroyAllWindows()
  • 实验结果

旋转
② 利用图像矩阵进行转置特定旋转transpose

  • cv2.transpose( src[, dst] )
参数含义
src要转置矩阵的图像
dst与原图像大小和深度相同的输出图像
  • 即只进行图像矩阵的行列转换
  • 实验代码
import cv2 as cv
import numpy as np

img = cv.imread('../picture/14.jpg')

# 只对图像(矩阵)进行转置(行列变换),使用不灵活
img_transpose = cv.transpose(img)

print("原图尺寸:", img.shape)
print("进行转置:", img_transpose.shape)

cv.imshow('img_transpose', img_transpose)
cv.waitKey(0)
cv.destroyAllWindows()
  • 实验结果
    在这里插入图片描述

③ 图像翻转flip

  • cv2.flip(filename, flipcode)
参数含义
filename要操作的图像
flipcode翻转方式1水平翻转
0垂直翻转
-1水平垂直翻转
  • 实验代码
# 利用翻转函数旋转
import cv2 as cv
import numpy as np

img = cv.imread('../picture/14.jpg')
# 翻转
img_flip = cv.flip(img, 1)
imgs = np.hstack((img, img_flip))

cv.imshow('imgs', imgs)
cv.waitKey(0)
cv.destroyAllWindows()
  • 实验结果
    在这里插入图片描述
5.3 warpPerspective透视变换
仿射变换可以将矩形映射为任意平行四边形,透视变换可以将任意四边形映射成矩形
  • cv2.warpPerspective(src, M, dsize, [, flags[, borderMode[, borderValue]]])
参数含义
src输入原图
M变换矩阵 (3*3的矩阵)
dsize输出图像大小
flags插入值方法(int 类型)
borderMode边界像素模式(int)
borderValue边界填充值

获取透视矩阵

  • cv2.getPerspectiveTransform(src, dst) 函数
    src表示输入图像的四个顶点坐标
    dst表示输出图像的四个顶点坐标
  • 实验代码
import cv2 as cv
import numpy as np

img = cv.imread('../picture/14.jpg')
height, width = img.shape[:2]

# 得到变换矩阵
transform = cv.getAffineTransform(np.float32([[0, 0], [0, height], [width, 0]]), 
                                 np.float32([[0, 0], [100, height - 100], [width - 100, 100]]))
# 进行仿射变换
img_affine = cv.warpAffine(img, transform, (width, height), borderValue=(255, 255, 255))

# 左上角,右上角,左下角,右下角
p1 = np.float32([[0, 0], 
                 [width - 100, 100], 
                 [100, height - 100],
                 [width, height]])

p2 = np.float32([[0, 0], 
                 [width, 0], 
                 [0, height],
                 [width, height]])

# 生成透视矩阵
M = cv.getPerspectiveTransform(p1, p2)
img_perspective = cv.warpPerspective(img_affine, M, (width, height))

cv.imshow('img', img)
cv.imshow('img_affine', img_affine)
cv.imshow('img_perspective', img_perspective)
cv.waitKey(0)
cv.destroyAllWindows()
  • 实验结果
    在这里插入图片描述
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一半不眠次日si记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值