OpenCV图像处理1—图像色彩空间与几何变换

本篇目标

介绍几种常见的OpenCV色彩空间转换方法的使用,以及利用图像色彩进行简单的目标追踪。简述图像的尺度变换、平移旋转、仿射变换、透视投影变换的在Opencv中的使用方法和部分原理。

图像色彩空间

几种常见的色彩空间转换

opencv有超过150的色彩空间转换方法:

['COLOR_BAYER_BG2BGR', 'COLOR_BAYER_BG2BGRA', 'COLOR_BAYER_BG2BGR_EA', 'COLOR_BAYER_BG2BGR_VNG', 'COLOR_BAYER_BG2GRAY', 'COLOR_BAYER_BG2RGB', 'COLOR_BAYER_BG2RGBA', 'COLOR_BAYER_BG2RGB_EA', 'COLOR_BAYER_BG2RGB_VNG', 'COLOR_BAYER_BGGR2BGR', 'COLOR_BAYER_BGGR2BGRA', 'COLOR_BAYER_BGGR2BGR_EA', 'COLOR_BAYER_BGGR2BGR_VNG', 'COLOR_BAYER_BGGR2GRAY', 'COLOR_BAYER_BGGR2RGB', 'COLOR_BAYER_BGGR2RGBA', 'COLOR_BAYER_BGGR2RGB_EA', 'COLOR_BAYER_BGGR2RGB_VNG', 'COLOR_BAYER_GB2BGR', 'COLOR_BAYER_GB2BGRA', 'COLOR_BAYER_GB2BGR_EA', 'COLOR_BAYER_GB2BGR_VNG', 'COLOR_BAYER_GB2GRAY', 'COLOR_BAYER_GB2RGB', 'COLOR_BAYER_GB2RGBA', 'COLOR_BAYER_GB2RGB_EA', 'COLOR_BAYER_GB2RGB_VNG', 'COLOR_BAYER_GBRG2BGR', 'COLOR_BAYER_GBRG2BGRA', 'COLOR_BAYER_GBRG2BGR_EA', 'COLOR_BAYER_GBRG2BGR_VNG', 'COLOR_BAYER_GBRG2GRAY', 'COLOR_BAYER_GBRG2RGB', 'COLOR_BAYER_GBRG2RGBA', 'COLOR_BAYER_GBRG2RGB_EA', 'COLOR_BAYER_GBRG2RGB_VNG', 'COLOR_BAYER_GR2BGR', 'COLOR_BAYER_GR2BGRA', 'COLOR_BAYER_GR2BGR_EA', 'COLOR_BAYER_GR2BGR_VNG', 'COLOR_BAYER_GR2GRAY', 'COLOR_BAYER_GR2RGB', 'COLOR_BAYER_GR2RGBA', 'COLOR_BAYER_GR2RGB_EA', 'COLOR_BAYER_GR2RGB_VNG', 'COLOR_BAYER_GRBG2BGR', 'COLOR_BAYER_GRBG2BGRA', 'COLOR_BAYER_GRBG2BGR_EA', 'COLOR_BAYER_GRBG2BGR_VNG', 'COLOR_BAYER_GRBG2GRAY', 'COLOR_BAYER_GRBG2RGB', 'COLOR_BAYER_GRBG2RGBA', 'COLOR_BAYER_GRBG2RGB_EA', 'COLOR_BAYER_GRBG2RGB_VNG', 'COLOR_BAYER_RG2BGR', 'COLOR_BAYER_RG2BGRA', 'COLOR_BAYER_RG2BGR_EA', 'COLOR_BAYER_RG2BGR_VNG', 'COLOR_BAYER_RG2GRAY', 'COLOR_BAYER_RG2RGB', 'COLOR_BAYER_RG2RGBA', 'COLOR_BAYER_RG2RGB_EA', 'COLOR_BAYER_RG2RGB_VNG', 'COLOR_BAYER_RGGB2BGR', 'COLOR_BAYER_RGGB2BGRA', 'COLOR_BAYER_RGGB2BGR_EA', 'COLOR_BAYER_RGGB2BGR_VNG', 'COLOR_BAYER_RGGB2GRAY', 'COLOR_BAYER_RGGB2RGB', 'COLOR_BAYER_RGGB2RGBA', 'COLOR_BAYER_RGGB2RGB_EA', 'COLOR_BAYER_RGGB2RGB_VNG', 'COLOR_BGR2BGR555', 'COLOR_BGR2BGR565', 'COLOR_BGR2BGRA', 'COLOR_BGR2GRAY', 'COLOR_BGR2HLS', 'COLOR_BGR2HLS_FULL', 'COLOR_BGR2HSV', 'COLOR_BGR2HSV_FULL', 'COLOR_BGR2LAB', 'COLOR_BGR2LUV', 'COLOR_BGR2Lab', 'COLOR_BGR2Luv', 'COLOR_BGR2RGB', 'COLOR_BGR2RGBA', 'COLOR_BGR2XYZ', 'COLOR_BGR2YCR_CB', 'COLOR_BGR2YCrCb', 'COLOR_BGR2YUV', 'COLOR_BGR2YUV_I420', 'COLOR_BGR2YUV_IYUV', 'COLOR_BGR2YUV_YV12', 'COLOR_BGR5552BGR', 'COLOR_BGR5552BGRA', 'COLOR_BGR5552GRAY', 'COLOR_BGR5552RGB', 'COLOR_BGR5552RGBA', 'COLOR_BGR5652BGR', 'COLOR_BGR5652BGRA', 'COLOR_BGR5652GRAY', 'COLOR_BGR5652RGB', 'COLOR_BGR5652RGBA', 'COLOR_BGRA2BGR', 'COLOR_BGRA2BGR555', 'COLOR_BGRA2BGR565', 'COLOR_BGRA2GRAY', 'COLOR_BGRA2RGB', 'COLOR_BGRA2RGBA', 'COLOR_BGRA2YUV_I420', 'COLOR_BGRA2YUV_IYUV', 'COLOR_BGRA2YUV_YV12', 'COLOR_BayerBG2BGR', 'COLOR_BayerBG2BGRA', 'COLOR_BayerBG2BGR_EA', 'COLOR_BayerBG2BGR_VNG', 'COLOR_BayerBG2GRAY', 'COLOR_BayerBG2RGB', 'COLOR_BayerBG2RGBA', 'COLOR_BayerBG2RGB_EA', 'COLOR_BayerBG2RGB_VNG', 'COLOR_BayerBGGR2BGR', 'COLOR_BayerBGGR2BGRA', 'COLOR_BayerBGGR2BGR_EA', 'COLOR_BayerBGGR2BGR_VNG', 'COLOR_BayerBGGR2GRAY', 'COLOR_BayerBGGR2RGB', 'COLOR_BayerBGGR2RGBA', 'COLOR_BayerBGGR2RGB_EA', 'COLOR_BayerBGGR2RGB_VNG', 'COLOR_BayerGB2BGR', 'COLOR_BayerGB2BGRA', 'COLOR_BayerGB2BGR_EA', 'COLOR_BayerGB2BGR_VNG', 'COLOR_BayerGB2GRAY', 'COLOR_BayerGB2RGB', 'COLOR_BayerGB2RGBA', 'COLOR_BayerGB2RGB_EA', 'COLOR_BayerGB2RGB_VNG', 'COLOR_BayerGBRG2BGR', 'COLOR_BayerGBRG2BGRA', 'COLOR_BayerGBRG2BGR_EA', 'COLOR_BayerGBRG2BGR_VNG', 'COLOR_BayerGBRG2GRAY', 'COLOR_BayerGBRG2RGB', 'COLOR_BayerGBRG2RGBA', 'COLOR_BayerGBRG2RGB_EA', 'COLOR_BayerGBRG2RGB_VNG', 'COLOR_BayerGR2BGR', 'COLOR_BayerGR2BGRA', 'COLOR_BayerGR2BGR_EA', 'COLOR_BayerGR2BGR_VNG', 'COLOR_BayerGR2GRAY', 'COLOR_BayerGR2RGB', 'COLOR_BayerGR2RGBA', 'COLOR_BayerGR2RGB_EA', 'COLOR_BayerGR2RGB_VNG', 'COLOR_BayerGRBG2BGR', 'COLOR_BayerGRBG2BGRA', 'COLOR_BayerGRBG2BGR_EA', 'COLOR_BayerGRBG2BGR_VNG', 'COLOR_BayerGRBG2GRAY', 'COLOR_BayerGRBG2RGB', 'COLOR_BayerGRBG2RGBA', 'COLOR_BayerGRBG2RGB_EA', 'COLOR_BayerGRBG2RGB_VNG', 'COLOR_BayerRG2BGR', 'COLOR_BayerRG2BGRA', 'COLOR_BayerRG2BGR_EA', 'COLOR_BayerRG2BGR_VNG', 'COLOR_BayerRG2GRAY', 'COLOR_BayerRG2RGB', 'COLOR_BayerRG2RGBA', 'COLOR_BayerRG2RGB_EA', 'COLOR_BayerRG2RGB_VNG', 'COLOR_BayerRGGB2BGR', 'COLOR_BayerRGGB2BGRA', 'COLOR_BayerRGGB2BGR_EA', 'COLOR_BayerRGGB2BGR_VNG', 'COLOR_BayerRGGB2GRAY', 'COLOR_BayerRGGB2RGB', 'COLOR_BayerRGGB2RGBA', 'COLOR_BayerRGGB2RGB_EA', 'COLOR_BayerRGGB2RGB_VNG', 'COLOR_COLORCVT_MAX', 'COLOR_GRAY2BGR', 'COLOR_GRAY2BGR555', 'COLOR_GRAY2BGR565', 'COLOR_GRAY2BGRA', 'COLOR_GRAY2RGB', 'COLOR_GRAY2RGBA', 'COLOR_HLS2BGR', 'COLOR_HLS2BGR_FULL', 'COLOR_HLS2RGB', 'COLOR_HLS2RGB_FULL', 'COLOR_HSV2BGR', 'COLOR_HSV2BGR_FULL', 'COLOR_HSV2RGB', 'COLOR_HSV2RGB_FULL', 'COLOR_LAB2BGR', 'COLOR_LAB2LBGR', 'COLOR_LAB2LRGB', 'COLOR_LAB2RGB', 'COLOR_LBGR2LAB', 'COLOR_LBGR2LUV', 'COLOR_LBGR2Lab', 'COLOR_LBGR2Luv', 'COLOR_LRGB2LAB', 'COLOR_LRGB2LUV', 'COLOR_LRGB2Lab', 'COLOR_LRGB2Luv', 'COLOR_LUV2BGR', 'COLOR_LUV2LBGR', 'COLOR_LUV2LRGB', 'COLOR_LUV2RGB', 'COLOR_Lab2BGR', 'COLOR_Lab2LBGR', 'COLOR_Lab2LRGB', 'COLOR_Lab2RGB', 'COLOR_Luv2BGR', 'COLOR_Luv2LBGR', 'COLOR_Luv2LRGB', 'COLOR_Luv2RGB', 'COLOR_M_RGBA2RGBA', 'COLOR_RGB2BGR', 'COLOR_RGB2BGR555', 'COLOR_RGB2BGR565', 'COLOR_RGB2BGRA', 'COLOR_RGB2GRAY', 'COLOR_RGB2HLS', 'COLOR_RGB2HLS_FULL', 'COLOR_RGB2HSV', 'COLOR_RGB2HSV_FULL', 'COLOR_RGB2LAB', 'COLOR_RGB2LUV', 'COLOR_RGB2Lab', 'COLOR_RGB2Luv', 'COLOR_RGB2RGBA', 'COLOR_RGB2XYZ', 'COLOR_RGB2YCR_CB', 'COLOR_RGB2YCrCb', 'COLOR_RGB2YUV', 'COLOR_RGB2YUV_I420', 'COLOR_RGB2YUV_IYUV', 'COLOR_RGB2YUV_YV12', 'COLOR_RGBA2BGR', 'COLOR_RGBA2BGR555', 'COLOR_RGBA2BGR565', 'COLOR_RGBA2BGRA', 'COLOR_RGBA2GRAY', 'COLOR_RGBA2M_RGBA', 'COLOR_RGBA2RGB', 'COLOR_RGBA2YUV_I420', 'COLOR_RGBA2YUV_IYUV', 'COLOR_RGBA2YUV_YV12', 'COLOR_RGBA2mRGBA', 'COLOR_XYZ2BGR', 'COLOR_XYZ2RGB', 'COLOR_YCR_CB2BGR', 'COLOR_YCR_CB2RGB', 'COLOR_YCrCb2BGR', 'COLOR_YCrCb2RGB', 'COLOR_YUV2BGR', 'COLOR_YUV2BGRA_I420', 'COLOR_YUV2BGRA_IYUV', 'COLOR_YUV2BGRA_NV12', 'COLOR_YUV2BGRA_NV21', 'COLOR_YUV2BGRA_UYNV', 'COLOR_YUV2BGRA_UYVY', 'COLOR_YUV2BGRA_Y422', 'COLOR_YUV2BGRA_YUNV', 'COLOR_YUV2BGRA_YUY2', 'COLOR_YUV2BGRA_YUYV', 'COLOR_YUV2BGRA_YV12', 'COLOR_YUV2BGRA_YVYU', 'COLOR_YUV2BGR_I420', 'COLOR_YUV2BGR_IYUV', 'COLOR_YUV2BGR_NV12', 'COLOR_YUV2BGR_NV21', 'COLOR_YUV2BGR_UYNV', 'COLOR_YUV2BGR_UYVY', 'COLOR_YUV2BGR_Y422', 'COLOR_YUV2BGR_YUNV', 'COLOR_YUV2BGR_YUY2', 'COLOR_YUV2BGR_YUYV', 'COLOR_YUV2BGR_YV12', 'COLOR_YUV2BGR_YVYU', 'COLOR_YUV2GRAY_420', 'COLOR_YUV2GRAY_I420', 'COLOR_YUV2GRAY_IYUV', 'COLOR_YUV2GRAY_NV12', 'COLOR_YUV2GRAY_NV21', 'COLOR_YUV2GRAY_UYNV', 'COLOR_YUV2GRAY_UYVY', 'COLOR_YUV2GRAY_Y422', 'COLOR_YUV2GRAY_YUNV', 'COLOR_YUV2GRAY_YUY2', 'COLOR_YUV2GRAY_YUYV', 'COLOR_YUV2GRAY_YV12', 'COLOR_YUV2GRAY_YVYU', 'COLOR_YUV2RGB', 'COLOR_YUV2RGBA_I420', 'COLOR_YUV2RGBA_IYUV', 'COLOR_YUV2RGBA_NV12', 'COLOR_YUV2RGBA_NV21', 'COLOR_YUV2RGBA_UYNV', 'COLOR_YUV2RGBA_UYVY', 'COLOR_YUV2RGBA_Y422', 'COLOR_YUV2RGBA_YUNV', 'COLOR_YUV2RGBA_YUY2', 'COLOR_YUV2RGBA_YUYV', 'COLOR_YUV2RGBA_YV12', 'COLOR_YUV2RGBA_YVYU', 'COLOR_YUV2RGB_I420', 'COLOR_YUV2RGB_IYUV', 'COLOR_YUV2RGB_NV12', 'COLOR_YUV2RGB_NV21', 'COLOR_YUV2RGB_UYNV', 'COLOR_YUV2RGB_UYVY', 'COLOR_YUV2RGB_Y422', 'COLOR_YUV2RGB_YUNV', 'COLOR_YUV2RGB_YUY2', 'COLOR_YUV2RGB_YUYV', 'COLOR_YUV2RGB_YV12', 'COLOR_YUV2RGB_YVYU', 'COLOR_YUV420P2BGR', 'COLOR_YUV420P2BGRA', 'COLOR_YUV420P2GRAY', 'COLOR_YUV420P2RGB', 'COLOR_YUV420P2RGBA', 'COLOR_YUV420SP2BGR', 'COLOR_YUV420SP2BGRA', 'COLOR_YUV420SP2GRAY', 'COLOR_YUV420SP2RGB', 'COLOR_YUV420SP2RGBA', 'COLOR_YUV420p2BGR', 'COLOR_YUV420p2BGRA', 'COLOR_YUV420p2GRAY', 'COLOR_YUV420p2RGB', 'COLOR_YUV420p2RGBA', 'COLOR_YUV420sp2BGR', 'COLOR_YUV420sp2BGRA', 'COLOR_YUV420sp2GRAY', 'COLOR_YUV420sp2RGB', 'COLOR_YUV420sp2RGBA', 'COLOR_mRGBA2RGBA']

这里介绍几种常用的,BGR->RGB,BGR->Gray,BGR->HSV。需要注意的是,使用Opencv读取的图像默认通道顺序是BGR,而是matplotlib默认的通道顺序是RGB,因此在使用opencv读取图像,matplotlib打印图像时需要进行色彩空间转换。

bgr_image = cv2.imread("images/pumpkin.jpg")

rgb_image = cv2.cvtColor(bgr_image,cv2.COLOR_BGR2RGB)
bgr_image = cv2.cvtColor(rgb_image,cv2.COLOR_BGR2RGB)
gray_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2GRAY)

plt.figure(figsize=(30,10))
plt.subplot(131),plt.imshow(bgr_image),plt.title("BGR")
plt.subplot(132),plt.imshow(rgb_image),plt.title("RGB")
plt.subplot(133),plt.imshow(gray_image),plt.title("GRAY") # 灰度图显示绿色是因为plt.imshow()种cmap默认的参数是Viridis,改为Gray后为灰色

在这里插入图片描述
在这里插入图片描述
HSV 表达彩色图像的方式由三个部分组成:Hue(色调、色相)、Saturation(饱和度、色彩纯净度)、Value(明度)。在 HSV 颜色空间下,比 BGR 更容易跟踪某种颜色的物体,常用于分割指定颜色的物体。转换为HSV色彩空间:

bgr_image = cv2.imread("images/pumpkin.jpg")
hsv_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2HSV)
plt.figure(figsize=(20,10))
plt.subplot(131),plt.imshow(bgr_image),plt.title("BGR")
plt.subplot(132),plt.imshow(hsv_image),plt.title("HSV")

在这里插入图片描述

Simple Object Tracking

采集摄像头获取每一帧的画面,进行色彩空间转换BGR->HSV,根据阈值过滤,提取。
这不是通用的目标检测或追踪方法,只是说可以通过目标的颜色可以进行简易追踪任务。

#objectTracking.py
import cv2
import numpy as np
cap = cv2.VideoCapture(0)
while(1):
    # Take each frame
    _, frame = cap.read()
    # Convert BGR to HSV
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    # define range of blue color in HSV
    lower_blue = np.array([110,100,50])
    upper_blue = np.array([130,255,255])
    # Threshold the HSV image to get only blue colors
    mask = cv2.inRange(hsv, lower_blue, upper_blue)
    # Bitwise-AND mask and original image
    res = cv2.bitwise_and(frame,frame, mask= mask)
    cv2.imshow('frame',frame)
    cv2.imshow('mask',mask)
    cv2.imshow('res',res)
    k = cv2.waitKey(50) & 0xFF ## waitKey: duration of per frame is 50 ms
    if k == 27:
        break
cap.release()
cv2.destroyAllWindows()

在这里插入图片描述

图像几何变换

Geometric Transformations of Images
主要简述尺度变换、平移、旋转、仿射变换、透视投影变换的在Opencv中的使用方法和原理。

尺度变换(scaling)

只调整图像的大小,进行放大或缩小在opencv中通过resize函数实现。interpolation参数控制插值方法,缩小图像时较好的插值方法是 cv2.INTER_AREA 和cv2.INTER_CUBIC (slow) ,放大图像时使用cv.INTER_LINEAR进行插值较好。

image = cv2.imread("images/windmill.jpg",0)
# Scaling
scal_img = cv2.resize(image, None, fx=0.5,fy=1,interpolation=cv2.INTER_CUBIC)
plt.subplot(121),plt.imshow(image),plt.title("raw")
plt.subplot(122),plt.imshow(scal_img),plt.title("scaling:width*0.5")

在这里插入图片描述

平移原理(Translation)

移动物体的位置。通过矩阵M实现将 ( x , y ) (x,y) (x,y)点移动到 ( x + t x , y + t y ) (x+t_x,y+t_y) (x+tx,y+ty)

M = [ 1 0 t x 0 1 t y ] ; M ∗ [ x y 1 ] = [ x + t x y + t y ] M = \begin{bmatrix} {1}&{0}&{t_{x}}\\ {0}&{1}&{t_{y}}\\ \end{bmatrix} ;M * \begin{bmatrix} {x}\\ {y}\\ {1}\\ \end{bmatrix} =\begin{bmatrix} {x+t_{x}}\\ {y+t_{y}}\\ \end{bmatrix} M=[1001txty]M xy1 =[x+txy+ty]

opencv中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_{12}y+M_{13},M_{21}x+M_{22}y+M_{23}) dst(x,y)=src(M11x+M12y+M13,M21x+M22y+M23)

# Translation is the shifting of an object's location using matrix M, shifting point from x,y to tx,ty
tx,ty = 100,50
M = np.float32([[1,0,tx],[0,1,ty]])
image = cv2.imread("images/windmill.jpg",0)
shift_img = cv2.warpAffine(image,M,(300,200))
plt.subplot(121),plt.imshow(image),plt.title("raw")
plt.subplot(122),plt.imshow(shift_img),plt.title("shift")

在这里插入图片描述

旋转原理(Rotation)

图像旋转是通过矩阵变换的形式实现的,原理解释如下。如下图,点围绕原点从(x,y)旋转到(x’y’),点到原点长度为 a a a,旋转角度 θ \theta θ,通过计算点旋转前后的坐标关系如下:
{ a ∗ c o s ( θ + φ ) = x ′ a ∗ s i n ( θ + φ ) = y ′ a ∗ c o s ( φ ) = x a ∗ s i n ( φ ) = y = > \begin{cases} a*cos(\theta+\varphi) = x'\\ a*sin(\theta+\varphi) = y'\\ a*cos(\varphi)=x\\ a*sin(\varphi)=y\\ \end{cases} => acos(θ+φ)=xasin(θ+φ)=yacos(φ)=xasin(φ)=y=> { x ′ = x ∗ c o s θ − y ∗ s i n θ y ′ = x ∗ s i n θ + y ∗ c o s θ \begin{cases} x' = x*cos\theta-y*sin\theta \\ y' = x*sin\theta+y*cos\theta \end{cases} {x=xcosθysinθy=xsinθ+ycosθ,即 [ x ′ y ′ ] = [ c o s θ − s i n θ s i n θ c o s θ ] [ x y ] \begin{bmatrix} {x'}\\ {y'}\\ \end{bmatrix} = \begin{bmatrix} {cos\theta}&{-sin\theta}\\ {sin\theta}&{cos\theta}\\ \end{bmatrix} \begin{bmatrix} {x}\\ {y}\\ \end{bmatrix} [xy]=[cosθsinθsinθcosθ][xy]

可得旋转矩阵为M= [ c o s θ − s i n θ s i n θ c o s θ ] \begin{bmatrix} {cos\theta}&{-sin\theta}\\ {sin\theta}&{cos\theta}\\ \end{bmatrix} [cosθsinθsinθcosθ],OpenCV中提供了一种功能更加全面的变换矩阵,支持自定义旋转中心和尺度变换,通过函数getRotationMatrix2D()获取旋转矩阵

[ α β ( 1 − α ) ∗ c e n t e r . x − β ∗ c e n t e r . y − β α β ∗ c e n t e r . x − ( 1 − α ) ∗ c e n t e r . y ] \begin{bmatrix} {\alpha}&{\beta}&{(1-\alpha)*center.x - \beta*center.y}\\ {-\beta}&{\alpha}&{\beta*center.x - (1-\alpha)*center.y}\\ \end{bmatrix} [αββα(1α)center.xβcenter.yβcenter.x(1α)center.y],where: { α = s c a l e ∗ c o s ( θ ) β = s c a l e ∗ s i n ( θ ) \begin{cases} \alpha = scale*cos(\theta)\\ \beta = scale*sin(\theta)\\ \end{cases} {α=scalecos(θ)β=scalesin(θ)

然后通过warpAffine()函数进行旋转。

在这里插入图片描述

image = cv2.imread("images/windmill.jpg",0)
assert image is not None, "file could not be read, check with os.path.exists()"
rows,cols = image.shape
# getRotationMatrix2D(center, angle, scale)
M = cv2.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),45,1)
rotation_img_in_center = cv2.warpAffine(image,M,(cols,rows))
rotation_img_in_topLeftCorner = cv2.warpAffine(image,
                                               cv2.getRotationMatrix2D((0,0),30,1) ,
                                               (cols,rows))
rotation_img_in_center_with_scale = cv2.warpAffine(image,
                                               cv2.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),45,0.5),
                                               (cols,rows))
plt.figure(figsize=(40,10))
plt.subplot(141),plt.imshow(image),plt.title("raw")
plt.subplot(142),plt.imshow(rotation_img_in_center),plt.title("rotation_img_in_center")
plt.subplot(143),plt.imshow(rotation_img_in_topLeftCorner),plt.title("rotation_img_in_topLeftCorner")
plt.subplot(144),plt.imshow(rotation_img_in_center_with_scale),plt.title("rotation_img_in_center_with_scale")
plt.show()

在这里插入图片描述

仿射变换(Affine Transformation)

仿射变换是任何保留共线性和距离比的变换,仿射变换不会保留角度和长度不变。仿射变换什么时候用?如何寻找仿射变换矩阵?
图像变换后的所有平行线在输出图像中仍然是平行的,为了找到变换矩阵,只需要从输入图像和输出图像中分别寻找三个点,使用cv2.getAffineTransform()方法通过三对点计算原图像到目标图像的变换矩阵M,cv2.warpAffine()方法进行图像仿射变换。仿射变换可以用来进行图像矫正,将下图中的Output图像矫正为Input中横平竖直的方格。

img = cv2.imread('images/Sudoku.png')
rows,cols,ch = img.shape
pts1 = np.float32([[0,0],[100,0],[0,100]])
pts2 = np.float32([[0,0],[100,50],[0,100]])
M = cv2.getAffineTransform(pts1,pts2)
dst = cv2.warpAffine(img,M,(cols,rows))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()

在这里插入图片描述

An affine transformation is any transformation that preserves collinearity (i.e., all points lying on a line initially still lie on a line after transformation) and ratios of distances (e.g., the midpoint of a line segment remains the midpoint after transformation). In this sense, affine indicates a special class of projective transformations that do not move any objects from the affine space R^3 to the plane at infinity or conversely. An affine transformation is also called an affinity.——《Wolfram MathWorld》

透视变换(Perspective Transformation)

透视变换其实是在对图像中的物体进行空间变换,从二维坐标向齐次坐标系转换,再进行投影,此外还需要使用到图像插值方法,相对来说透视变换要复杂一点,下面时使用方法。透视变换使用到四对点,通过cv2.getperspectiveTransform()找到变换矩阵。然后通过cv2.warpPerspective()对图像进行透视变换,如下:

img = cv2.imread('images/laptop.png')
rows,cols,ch = img.shape
pts1 = np.float32([[207,271],[846,162],[888,495],[334,739]])
pts2 = np.float32([[0,0],[600,0],[600,400],[0,400]])
M = cv2.getPerspectiveTransform(pts1,pts2)
dst = cv2.warpPerspective(img,M,(600,400))
plt.figure(figsize=(15,10))
plt.subplot(121),plt.imshow(img),plt.title('Input')
plt.subplot(122),plt.imshow(dst),plt.title('Output')
plt.show()

在这里插入图片描述

warpPerspective计算目标点坐标:
d s t ( x , y ) = s r c ( M 11 x + M 12 y + M 13 M 31 x + M 32 y + M 33 , M 21 x + M 22 y + M 23 M 31 x + M 32 y + M 33 ) dst(x,y)=src(\frac{M_{11}x+M_{12}y+M_{13}}{M_{31}x+M_{32}y+M_{33}},\frac{M_{21}x+M_{22}y+M_{23}}{M_{31}x+M_{32}y+M_{33}}) dst(x,y)=src(M31x+M32y+M33M11x+M12y+M13,M31x+M32y+M33M21x+M22y+M23)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

乔布斯砸牛顿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值