Opencv-python从入门到放弃 —— 图像变换(4)

自己是一个菜鸡,希望通过写博客的方式提升自己,最近正好接触到了opencv,想把学习路程以博客的形式记录下来,也算是学习opencv的一种动力吧,好吧,话不多说,干就完了!

一、基本原理

图像平移操作:
变换矩阵:M = [[1, 0, dx], [0, 1, dy]]
M = np.float32([[1, 0, 20], [0, 1, -30]]),必须是float类型的矩阵,opencv规定的。。
cv2.warpfine(img, M, (img.shape[1], img.shape[0])) 执行相应变换操作,图纸大小保持不变
其中[1, 0, dx]代表水平方向移动,dx > 0: 向右移动, dx < 0: 向左移动
图像旋转操作
图像旋转操作的旋转中心点一般选为原图像的中心点,当然opencv可以让你任取旋转点。。
变换矩阵:M = cv2.getRotationMatrix2D(pot, angle, scale) pot为旋转点,angle为旋转角度,其中正值代表逆时针旋转,负值则代表顺时针。scale为旋转过程中图像缩放的比例。
cv2.warpAffine(img, M, (w, h)) w, h为旋转后图纸的大小,一般与原图大小一致
图像缩放操作:
缩放操作一般应该保持原图像的宽高比,缩放后像素点所在位置的坐标不一定为整数值,此时应采用相应的插值方法,后面会简述opencv中常见的插值方法。
cv2.resize(img, (w_final, h_final), 插值方法)
具体的插值方法:(复杂度由低到高)
cv2.INTER_NEAREST:最近邻插值
cv2.INTER_LINEAR:双线性插值(默认)
cv2.INTER_AREA:运用像素区域关系进行重采样,效果很好,推荐这种。
cv2.INTER_CUBIC:4*4像素邻域的双三次插值
图像反转操作:
反转操作分为水平反转与竖直反转操作。
np.flip(img, 0),即垂直翻转(沿着第零个维度)
np.flip(img, 1),即水平翻转(沿着第一个维度)
np.flip(img, -1),水平,垂直翻转,先从哪个维度开始都可以。

二、Demo

import cv2
import numpy as np

def translate(image, dx, dy):
    """平移操作,dx>0右移,dy>0下移"""
    M = np.float32([[1, 0, dx], [0, 1, dy]])  # x轴平移dx(水平), y轴平移dy(竖直)
    shifted = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
    return shifted

def resize(image, width=None, height=None, inter=cv2.INTER_AREA):
    """缩放操作,保持原图片的宽高比,默认差值方式为cv2.INTER_AREA"""
    dim = None                  # 最终维度
    h, w = image.shape[:2]      # 原始图片高、宽

    if width is not None and height is not None:  # 保持高、宽相同的缩放比例,否则抛出异常
        raise Exception('To keep the same resize ratio, you only need to point out one dimension.')
    elif width is None and height is None:  # 如果都没写,就直接返回原图
        return image
    elif width is None:           # height不为空
        ratio = height / h        # 算出高度比例,并且应用于宽度,即保持原图的宽高比
        dim = (int(w * ratio), height)
    else:                         # width不为空
        ratio = width / w
        dim = (width, int(ratio * h))

    resized = cv2.resize(image, dim, interpolation=inter)
    return resized

def rotate(image, angle, center=None, scale=1.0):
    """图像旋转操作,默认旋转点为图像中心,旋转过程中图像尺寸保持不变"""
    h, w = image.shape[:2]
    if center is None:
        center = (w // 2, h // 2)
    M = cv2.getRotationMatrix2D(center, angle, scale)
    rotated = cv2.warpAffine(image, M, (w, h))

def flip(image, axis):
    """图像翻转操作,axis=0为垂直翻转,axis=1为水平翻转"""
    fliped = cv2.flip(image, axis)
    return fliped

# test
image = cv2.imread('./beach.png')
shifted1 = translate(image, 10, 20)         # right-bottom
cv2.imwrite('shifted1.jpg', shifted1)
shifted2 = translate(image, -10, -20)       # left-up
cv2.imwrite('shifted2.jpg', shifted2)
resized1 = resize(image, width=350)         # width=350
cv2.imwrite('resized1.jpg', resized1)
resized2 = resize(image, width=40)          # width=40
cv2.imwrite('resized2.jpg', resized2)
rotated1 = rotate(image, 45)                # 逆时针旋转45度
cv2.imwrite('rotated1.jpg', rotated1)
rotated2 = rotate(image, -30)               # 顺时针旋转30度
cv2.imwrite('rotated2.jpg', rotated2)
flip1 = flip(image, 0)                  # 垂直翻转
cv2.imwrite('flip1.jpg', flip1)             
flip2 = flip(image, -1)                 #垂直&水平翻转
cv2.imwrite('flip2.jpg', flip2)

运行结果
shifted1.jpg
shifted2.jpg
resized1.jpg
resized2.jpg
rotated1.jpg
rotated2.jpg
flip1.jpg
flip2.jpg

三、总结

  1. 平移矩阵类型一定是np.float32类型
  2. 最好的插值方法为cv2.INTER_AREA,这个效果最好。
  3. 这三种方法是很常见的图像处理方法,准备将这三个方法放到imutils.py工具包中,方便下次调用。

猜你喜欢

转载自blog.csdn.net/Annihilation7/article/details/82505635