3.opencv——图像变换1(色彩空间变换,几何变换)

色彩空间变换

\qquad 色彩空间也称颜色模型、颜色空间、色彩模型等,它是图像在计算机内部的一种存储方式。常见的色彩空间包括 RGB、GRAY、XYZ、YCrCb、HSV 等。色彩空间在物体追踪、特征检测等(简单来说就是识别一个东西)扮演着很重要的角色。毕竟每个物体都有特定的颜色和特征,我们可以应用其物体与环境颜色上的差异,从图像中提取特定范围的颜色并加上一些逻辑性的判断,获取待检测物体的位置。每种色彩空间都有其擅长的问题解决领域,所以在解决具体色彩问题时往往需要进行色彩空间类型转换。
OpenCV 的 cv2.cvtColor()函数用于转换色彩空间类型,其基本格式如下。

dst = cv2.cvtcolor(src,code[,dstcn]])

其参数说明如下:

参数说明
dst表示转换后的图像
src表示转换前的原图像
code表示色彩空间类型转换码
dstCn表示目标图像的通道数

常见的色彩空间类型转换码如下:

参数说明
cv2.COLOR_BGR2RGB将BGR 色彩空间转换为 RGB 色彩空间
cv2.COLOR_BGR2GRAY将 BGR 色彩空间转换为 GRAY 色彩空间
cv2.COLOR_BGR2HSV将 BGR 色彩空间转换为 HSV 色彩空间
cv2.COLOR_BGR2YCrCb将 BGR 色彩空间转换为 YCrCb 色彩空间
cv2.COLOR_RGB2BGR将 RGB 色彩空间转换为 BGR 色彩空间
cv2.COLOR_RGB2GRAY将 RGB 色彩空间转换为 GRAY 色彩空间
c2.COLOR_RGB2YCrCb将 RGB 色彩空间转换为 YCrCb 色彩空间
cv2.COLOR_RGB2HSV将RGB 色彩空间转换为 HSV 色彩空间

RGB色彩空间

\qquad RGB 色彩空间使用R(Red,红)、G(Green,绿)和B(Blue,蓝)3种基本颜色表示图像像素。RGB 色彩空间中,图像的每个像素用一个三元组表示,三元组中的3个值依次表示红色、绿色和蓝色,依次对应 R、G和B通道。OpenCV默认采用 BGR 色彩空间,它按 B、G和R通道顺序表示图像。
在cv2.cvtColor()函数中使用cv2.COLOR_BGR2RGB转换码可将图像从BGR色彩空间转换RGB色彩空间。

import cv2


img = cv2.imread('bee.jpg')  	             # 读取图像
cv2.imshow('bee', img)  	                 # 显示图像
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)  # 转换色彩空间为RGB
cv2.imshow('RGB', img2)  	                 # 显示图像
cv2.waitKey(0)

在这里插入图片描述

GRAY色彩空间

\qquad GRAY 色彩空间通常指 8 位灰度图像,其颜色取值范围为[0,255],共 256个灰度级。从 RGB 色彩空间转换为 GRAY 色彩空间的计算公式如下。
G r a y = 0.299 R + 0.587 G + 0.114 B Gray =0.299R+0.587G+0.114B Gray=0.299R+0.587G+0.114B
其中,R、G和 B为 RGB 色彩空间中 R、G 和 B 通道的图像。在 cv2.cvtColor()函数中使用 cv2.COLOR_BGR2GRAY 转换码可将图像从BGR 色彩空间转换为 GRAY 色彩空间。

import cv2


img = cv2.imread('bee.jpg')  	               # 读取图像
cv2.imshow('bee', img)  	                   # 显示图像
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)   # 转换色彩空间为GRAY
cv2.imshow('GRAY', img2)  	                   # 显示图像
cv2.waitKey(0)

在这里插入图片描述

YCrCb色彩空间

\qquad YCrCb 色彩空间用亮度 Y、红色 Cr 和蓝色 Cb 表示图像。从 RGB 色彩空间转换为 YCrCb 色彩空间的计算公式如下。
Y = 0.299 R + 0.587 G + 0.114 B C r = 0.713 ( R − Y ) + d e l t a C b = 0.564 ( B − Y ) + d e l t a Y=0.299R+ 0.587G+ 0.114B\\ Cr= 0.713(R- Y)+ delta\\ Cb= 0.564(B- Y)+ delta\\ Y=0.299R+0.587G+0.114BCr=0.713(RY)+deltaCb=0.564(BY)+delta
其中
d e l t a = { 128 8 位 图 像 32767 16 位 图 像 0.5 单 精 度 图 像 delta= \begin{cases} 128 & 8位图像\\ 32767 & 16位图像 \\ 0.5 & 单精度图像 \\ \end{cases} delta=128327670.5816
在cv2.cvtColor()函数中使用 cv2.COLOR_BGR2YCrCb 转换码可将图像从 BGR 色彩空间转换为 YCrCb 色彩空间。

import cv2


img = cv2.imread('bee.jpg')  	               # 读取图像
cv2.imshow('bee', img)  	                   # 显示图像
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)  # 转换色彩空间为YCrCb
cv2.imshow('YCrCb', img2)  	                   # 显示图像
cv2.waitKey(0)

在这里插入图片描述

HSV色彩空间

\qquad HSV 色彩空间使用色调(Hue,也称色相)、饱和度(Saturation)和亮度(Value)表示图像。
色调 H表示颜色,用角度表示,取值范围为[0°,360°],从红色开始按逆时针方向计算。例如,红色为 0°、黄色为 60°、绿色为 120°、青色为 180°、蓝色为 240°、紫色为 300°等。饱和度 S 表示颜色接近光谱色的程度,或者表示光谱色中混入白光的比例。光谱色中白光的比例越低,饱和度越高,颜色越深、艳。光谱色中白光比例为 0 时,饱和度达到最高。饱和度的取值范围为[0,1]。亮度V表示颜色明亮的程度,是人眼可感受到的明暗程度,其取值范围为[0,1]。
从 RGB 色彩空间转换为 HSV 色彩空间的计算公式如下:
V = m a x ( R , G , B ) V = max(R,G,B) V=max(R,G,B)
S = { V − m i n ( R , G , B ) V V ≠ 0 0 V = 0 S= \begin{cases} \frac{V-min(R,G,B)}{V} & V\neq0\\ 0 & V=0 \\ \end{cases} S={VVmin(R,G,B)0V=0V=0
H = { 60 − ( G − B ) V − m i n ( R , G , B ) V = R 120 + 60 − ( B − R ) V − m i n ( R , G , B ) V = G 240 + 60 − ( R − G ) V − m i n ( R , G , B ) V = B H= \begin{cases} \frac{60-(G-B)}{V-min(R,G,B)} & V=R\\ 120+\frac{60-(B-R)}{V-min(R,G,B)} & V=G \\ 240+\frac{60-(R-G)}{V-min(R,G,B)} & V=B \\ \end{cases} H=Vmin(R,G,B)60(GB)120+Vmin(R,G,B)60(BR)240+Vmin(R,G,B)60(RG)V=RV=GV=B
计算结果中如果H<0,则令H= H+360.
在cv2.cvtColor()函数中使用 cv2.COLOR_BGR2HSV转换码可将图像从 BGR 色彩空间转换为 HSV 色彩空间。

import cv2


img = cv2.imread('bee.jpg')  	             # 读取图像
cv2.imshow('BGR', img)  	                 # 显示图像
img2 = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)  # 转换色彩空间为HSV
cv2.imshow('HSV', img2)  	                 # 显示图像
cv2.waitKey(0)

在这里插入图片描述

几何变换

缩放

OpenCV的cv2.resize()函数用于缩放图像,其基本格式如下。

dst=cv2.resize(src,dsize[,dst[,fx[,fy[,interpolation]]]])

其参数说明如下:

参数说明
dst表示转换后的图像
src表示用于缩放的原图像
dsize表示转换后的图像大小
fx表示水平方向的缩放比例
fy表示垂直方向的缩放比例
interpolation表示插值方式。在转换过程中,可能存在一些不能通过转换算法确定值的像素,插值方式决定了如何获得这些像素的值。可用的插值方式如下表
参数说明
cv2.INTER_NEAREST最近邻插值
cv2.INTER_LINEAR双线性插值,默认方式
cv2.INTER_CUBIC3 次样条插值
cv2.INTER_AREA区域插值
cv2.INTER_LANCZOS4Lanczos 插值
cv2.INTER_LINEAR_EXACT位精确双线性插值
cv2.INTER_MAX插值编码掩码
cv2.WARP_FILL_OUTLIERS标志,填充目标图像中的所有像素
cv2.WARP_INVERSE_MAP标志,逆变换

cv2.resize()函数在转换图像时,目标图像的类型和大小与转换之前 dst表示的图像无关。目标图像的类型与 src 表示的原图像一致,其大小可通过参数dsize、fx和 fy 来确定。当dsize 参数不为 None时,不管是否设置参数fx和fy,都由dsize 来确定目标图像的大小。dsize是一个二元组,其格式为“(width,height)”,width 表示目标图像的宽度,height表示目标图像的高度。当dsize 参数为 None时,参数fx和fy不能设置为 0。此时,目标图像的宽度为“round(原图像的宽度×fx)”,目标图像的高度为“round(原图像的高度×fy)”。

import cv2


img = cv2.imread('bee.jpg')  	                   # 读取图像
sc = [1, 0.2, 0.5, 1.5, 2]                         # 设置缩放比例
cv2.imshow('showimg', img)  	                   # 显示图像
while True:                   	    
    key = cv2.waitKey()
    if 48 <= key <= 52:                            # 按键【0】、【1】、【2】、【3】或【4】
        x = y = sc[key-48]                         # 获得缩放比例
        img2 = cv2.resize(img, None, fx=x, fy=y)   # 缩放图像
        cv2.imshow('showimg', img2)  	           # 显示图像

在这里插入图片描述

翻转

OpenCV 的 cv2.flip()函数用于翻转图像,其基本格式如下。

dst=cv2.flip(src,flipCode)

其参数说明如下:

参数说明
dst表示转换后的图像
src表示原图像
fipCode表示翻转类型。flip 为 0 时绕 X轴翻转(垂直翻转),fip 为大于 0 的整数时绕y轴翻转(水平翻转),flip 为小于 0 的整数时同时绕 ×轴和 y轴翻转(水平和垂直翻转)
import cv2


img = cv2.imread('bee.jpg')  	  # 读取图像
cv2.imshow('showimg', img)  	  # 显示图像
while True:                   	    
    key = cv2.waitKey()
    if key == 48:                 # 按【0】键时显示原图 
        img2 = img
    elif key == 49:               # 按【1】键时垂直翻转
        img2 = cv2.flip(img, 0)
    elif key == 50:               # 按【2】键时水平翻转
        img2 = cv2.flip(img, 1)
    elif key == 51:               # 按【3】键时水平、垂直翻转
        img2 = cv2.flip(img, -1)
    cv2.imshow('showimg', img2)

在这里插入图片描述

仿射

\qquad 仿射变换包含了平移、旋转、缩放等操作,其主要特点是:原图像中的所有平行线在转换后的图像中仍然平行。OpenCV 的 cv2.warpAfine()函数用于实现图像的仿射变换,其基本格式如下。

dst=cv2.warpAffine(src,M,dsize[,dst[,flags[,bonderMode[, borderValue]]]])

其参数说明如下:

参数说明
dst表示转换后的图像,图像类型和原图像一致,大小由 dsize 决定
src表示原图像
M是一个大小为 2×3的转换矩阵,使用不同的转换矩阵可实现平移、旋转等多种操作
dsize为转换后的图像大小
flags为插值方式,默认值为 cV2.INTER_LINEAR
borderMode为边类型,默认值为 cv2.BORDER_CONSTANT
borderValue为边界值,默认为 0

在 cv2.warpAffine()函数省略可选参数时,图像转换的矩阵运算公式如下:

d s t ( x , y ) = s r c ( M 11 x + M 12 y + M 13 , M 21 x + M 22 y + M 23 ) dst(x,y)=src(M_{11}x+M_{12y}+M_{13},M_{21}x+M_{22}y+M_{23}) dst(x,y)=src(M11x+M12y+M13,M21x+M22y+M23)

平移

\qquad 平移是指图像沿水平或者垂直方向移动一定的像素。假设 ( x 0 , y 0 ) (x_0, y_0) (x0,y0)为原图像上的一个点,图像水平平移量为 t x t_x tx,垂直平移为 t y t_y ty,则平移后点 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)坐标将变成 ( x 1 , y 1 ) (x_1,y_1) (x1,y1) ( x 0 , y 0 ) (x_0, y_0) (x0,y0) ( x 1 , y 1 ) (x_1,y_1) (x1,y1)的关系如下:
{ x 1 = x 0 + t x y 1 = y 0 + t y \left\{ \begin{aligned} x_1= x_0+t_x \\ y_1 = y_0+t_y\\ \end{aligned} \right. {x1=x0+txy1=y0+ty
其 中 d s t ( x 0 , y 0 ) = s r c ( x 0 + t x , y 0 + t y ) 其中dst(x_0,y_0) = src(x_0+t_x,y_0+t_y) dst(x0,y0)=src(x0+tx,y0+ty)

用矩阵表示如下:
[ x 1 y 1 1 ] = [ 1 0 t x 0 1 t y 0 0 1 ] [ x 0 y 0 1 ] \left[ \begin{matrix} x_1 \\ y_1 \\ 1\\ \end{matrix} \right] = \left[ \begin{matrix} 1 & 0& t_x \\ 0 & 1 & t_y \\ 0 & 0 & 1\\ \end{matrix} \right] \left[ \begin{matrix} x_0 \\ y_0\\ 1\\ \end{matrix} \right] x1y11=100010txty1x0y01

其逆运算如下:
[ x 0 y 0 1 ] = [ 1 0 − t x 0 1 − t y 0 0 1 ] [ x 1 y 1 1 ] \left[ \begin{matrix} x_0\\ y_0 \\ 1\\ \end{matrix} \right] = \left[ \begin{matrix} 1 & 0& -t_x \\ 0 &1& -t_y \\ 0 & 0 & 1\\ \end{matrix} \right] \left[ \begin{matrix} x_1 \\ y_1\\ 1\\ \end{matrix} \right] x0y01=100010txty1x1y11
转换矩阵 M = [ 1 0 t x 0 1 t y ] M=\left[ \begin{matrix} 1 & 0& t_x \\ 0 & 1 & t_y \\ \end{matrix} \right] M=[1001txty]
这样,平移后的图像上的每一点都可以在原图像中找到对应的点。例如,对于新图中的(0.0)像素,对应原图中的像素 ( − t x , − t y ) (-t_x,-t_y) (tx,ty)。如果 t x t_x tx t y t_y ty大于 0,则 ( t x , t y ) (t_x,t_y) (tx,ty)不在原图中。对于不在原图中的点,可以将它的像素值设置为 0 或则 255(对于灰度图就是黑色或白色)。若有点不在新图中,说明原图中有点被移出显示区域。如果不想丢失被移出的部分图像,可以将新生成的图像宽度扩大 ∣ t x ∣ |t_x| tx,高度扩大 ∣ t y ∣ |t_y| ty

import cv2
import numpy as np


img = cv2.imread('bee.jpg')  	            # 读取图像
cv2.imshow('img', img)  	                # 显示图像
height = img.shape[0]                       # 获得图像高度
width = img.shape[1]                        # 获得图像宽度
dsize = (width, height)
m = np.float32([[1, 0, 100], [0, 1, 50]])   # 创建转换矩阵
img2 = cv2.warpAffine(img, m, dsize)        # 平移图像
cv2.imshow('imgx+100y+50', img2)  	        # 显示图像
cv2.waitKey(0)

在这里插入图片描述

缩放

假设图像的宽度缩放比例为h,高度缩放比例为v, 根据图像转换的矩阵运算公式可得出执行缩放的转换矩阵 M = [ h 0 0 0 v 0 ] M=\left[ \begin{matrix} h & 0&0 \\ 0 & v & 0 \\ \end{matrix} \right] M=[h00v00]

import cv2
import numpy as np


img = cv2.imread('bee.jpg')  	            # 读取图像
cv2.imshow('img', img)  	                # 显示图像
height = img.shape[0]                       # 获得图像高度
width = img.shape[1]                        # 获得图像宽度
dsize = (width, height)
m = np.float32([[0.5, 0, 0], [0, 0.5, 0]])  # 创建转换矩阵
img2 = cv2.warpAffine(img, m, dsize)        # 执行缩放
cv2.imshow('img0.5x+0.5y', img2)  	        # 显示图像
cv2.waitKey(0)

在这里插入图片描述

旋转

OpenCV 的cv2.getRotationMatrix2D()函数可用于计算执行旋转操作的转换矩阵,其基本格式如下。

m = cv2.getRotationMatrix2D(center, angle, scale)

其参数说明如下:

参数说明
center表示原图像中作为旋转中心的坐标
angle表示旋转角度,正数表示按逆时针方向旋转,负数表示按顺时针方向旋转
scale表示目标图像与原图像的大小比例

假设原图像宽度为 width,高度为 height,将图像中心作为旋转中心顺时针旋转 60°,并将图像缩小 50%,则用于计算转换矩阵的语句如下,过程就不再推导了,和平移差不多,有兴趣的可以尝试下推导:

m = cv2.getRotationMatrix2D((width/2, height/2 ), -60, 0.5)
import cv2


img = cv2.imread('bee.jpg')  	                            # 读取图像
cv2.imshow('img', img)  	                                # 显示图像
height = img.shape[0]                                       # 获得图像高度
width = img.shape[1]                                        # 获得图像宽度
dsize = (width, height)
m = cv2.getRotationMatrix2D((width/2, height/2), -60, 0.5)  # 创建转换矩阵
img2 = cv2.warpAffine(img, m, dsize)                        # 执行旋转
cv2.imshow('imgRotation', img2)  	                        # 显示图像
cv2.waitKey(0)

在这里插入图片描述

三点映射变换

三点映射变换会将图像转换为任意的平行四边形,cv2.getAffineTransform()函数用于计算其转换矩阵,基本格式如下。

m= cv2.getAffineTransform(src, dst)

其参数说明如下:

参数说明
src为原图像中 3 个点的坐标
dst为原图像中 3 个点在目标图像中的对应坐标

cv2.getAffineTransform()函数将 src 和 dst 中的 3 个点作为平行四边形左上角、右上角和左下角的 3 个点,按原图和目标图像与 3 个点之间的坐标关系计算所有像素的转换矩阵。

import cv2
import numpy as np


img = cv2.imread('bee.jpg')  	  # 读取图像
cv2.imshow('img', img)  	      # 显示图像
height = img.shape[0]             # 获得图像高度
width = img.shape[1]              # 获得图像宽度
dsize = (width, height)
src = np.float32([[0, 0], [width-10, 0], [0, height-1]])          # 取原图像中三个点
dst = np.float32([[50, 50], [width-100, 80], [100, height-100]])  # 设置三点在目标图像中的坐标
m = cv2.getAffineTransform(src, dst)                              # 创建转换矩阵
img2 = cv2.warpAffine(img, m, dsize)                              # 执行转换
cv2.imshow('imgThreePoint', img2)  	                              # 显示图像
cv2.waitKey(0)

在这里插入图片描述

透视

透视变换会将图像转换为任意的四边形,其主要特点是:原始图像中的所有直线在转换后的图像中仍然是直线。OpenCV 的 cv2.warpPerspective()函数用于执行透视变换操作,其基本格式如下。

dst=cv2.warpPerspective(src,M,dsize[,flags[,borderMode[,borderValue]]])

其中,M 是大小为 3×3 的转换矩阵,其他参数含义与 cv2.warpAffine()函数中的一致。
OpenCV 的 cv2.getPerspectiveTransform()函数用于计算透视变换使用的转换矩阵,其基本格式如下。

M = cv2.getPerspectiveTransform(src,dst)

其参数说明如下:

参数说明
src为原图像中 4 个点的坐标
dst为原图像中 4 个点在转换后的目标图像中的对应坐标
import cv2
import numpy as np


img = cv2.imread('bee.jpg')  	  # 读取图像
cv2.imshow('img', img)  	      # 显示图像
height = img.shape[0]             # 获得图像高度
width = img.shape[1]              # 获得图像宽度
dsize = (width, height)
src = np.float32([[0, 0], [width-10, 0], [0, height-10], [width-1, height-1]])          # 取原图像中四个点
dst = np.float32([[50, 50], [width-50, 80], [50, height-100], [width-100, height-10]])  # 设置四点在目标图像中的坐标
m = cv2.getPerspectiveTransform(src, dst)     # 创建转换矩阵
img2 = cv2.warpPerspective(img, m, dsize)     # 执行转换
cv2.imshow('imgFourPoint', img2)  	          # 显示图像
cv2.waitKey(0)

在这里插入图片描述

实验素材

请添加图片描述

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值