Opencv图像处理系列(二)——几何变换

栏目: 编程工具 · 发布时间: 5年前

内容简介:Opencv提供了一系列对图像进行几何变换的API,如位移,旋转,缩放,仿射变换,透视变换等。opencv提供了warpAffine函数来对图像执行更多的几何变换操作

Opencv提供了一系列对图像进行几何变换的API,如位移,旋转,缩放,仿射变换,透视变换等。

2. API及示例

2.1 缩放

void cv::resize    (    
InputArray     src, //输入图
OutputArray     dst, //输出图
Size     dsize,       //输出图尺寸,不填则根据原图和xy方向的缩放因子计算
double     fx = 0,      //x方向缩放因子,不填则根据输入输出图尺寸计算
double     fy = 0,      //y方向缩放因子
int     interpolation = INTER_LINEAR //插值方法
)

插值方法取值如下:

Opencv图像处理系列(二)——几何变换

示例:

import cv2
import matplotlib.pyplot as plt

def testScale():
    img = cv2.imread("test.jpg")
    img = cv2.resize(img,None, fx=0.5, fy=0.1, interpolation = cv2.INTER_CUBIC)
    cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    plt.imshow(img)
    plt.show()

testScale()

Opencv图像处理系列(二)——几何变换

2.2 位移

opencv提供了warpAffine函数来对图像执行更多的几何变换操作

void cv::warpAffine    (    
InputArray     src,  //输入
OutputArray     dst,  //输出
InputArray     M,    //2x3的变换矩阵
Size     dsize,        //输出图尺寸  
int     flags = INTER_LINEAR, //插值方法
int     borderMode = BORDER_CONSTANT,//边缘模式
const Scalar &     borderValue = Scalar() //边框参数,不填为(0,0,0),即填充黑色
)

如果让一个图片在x,y方向上分别位移Tx,Ty,这个位移可以用一个2*3的变换矩阵来表示:

Opencv图像处理系列(二)——几何变换

例如:

img = cv2.imread('test.jpg', 0)
rows, cols = img.shape
M = np.float32([[1, 0, 250], [0, 1, 200]])
dst = cv2.warpAffine(img, M, (cols, rows))
dst = cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)
plt.imshow(dst)
plt.show()

Opencv图像处理系列(二)——几何变换

2.3 旋转

图像旋转θ角度,可以通过矩阵

Opencv图像处理系列(二)——几何变换

来表示。

可以将缩放、旋转集成到一个变换矩阵中,并设置旋转的中心点:

Opencv图像处理系列(二)——几何变换

其中:

α=scale⋅cosθ
β=scale⋅sinθ

当然,我们并不需要自己去计算这个复杂的矩阵,opencv提供了函数来计算这个矩阵:

Mat cv::getRotationMatrix2D    (    
Point2f     center, //旋转中心点
double     angle,          //旋转角度
double     scale           //缩放倍数
)

可以用这个函数来生成旋转矩阵试一下:

import cv2
import numpy as np
import matplotlib.pyplot as plt

def testRotate():
    img = cv2.imread('test.jpg')
    rows, cols, chanels = img.shape
    print("rows, cols, chanels :",rows, cols, chanels )
    M = cv2.getRotationMatrix2D((cols / 2,rows / 2), 90, 1)
    dst = cv2.warpAffine(img, M, (900,900))

    cv2.cvtColor(dst, cv2.COLOR_BGR2RGB, dst)
    plt.imshow(dst)
    plt.show()

testRotate()

原图:

Opencv图像处理系列(二)——几何变换

旋转图:

Opencv图像处理系列(二)——几何变换

这里值得注意的是,旋转得到的结果,超出原始图片大小的部分会被裁剪掉,即使输出尺寸填写的很大,也只会填充黑色。

旋转的过程可以理解为:

  1. 将坐标系变换至旋转中心点
  2. 旋转
  3. 将坐标系变换至原图左上角
  4. 超出原坐标系的部分裁减掉

要避免这种情况,只需要在第三步,变换坐标系的时候,将原点选在一个合适的位置,并调整输出图像大小即可。此处参考 https://blog.csdn.net/u010122972/article/details/78345447

Opencv图像处理系列(二)——几何变换

将旋转后的坐标原点由原始图像左上角,移动到旋转后图像视框左上角即可,需要做的工作有旋转后图像大小计算、旋转矩阵修改等。

代码实现如下:

img = cv2.imread('test.jpg')
degree = 30
heightOrigin, widthOrigin = img.shape[:2]
heightFinal = int(widthOrigin * math.fabs(math.sin(math.radians(degree))) +
                  heightOrigin * math.fabs(math.cos(math.radians(degree))))
widthFinal = int(heightOrigin * math.fabs(math.sin(math.radians(degree))) +
                 widthOrigin * math.fabs(math.cos(math.radians(degree))))
matRotation = cv2.getRotationMatrix2D((widthOrigin / 2, heightOrigin / 2), degree, 1)
matRotation[0, 2] += (widthFinal - widthOrigin) / 2
matRotation[1, 2] += (heightFinal - heightOrigin) / 2
dst = cv2.warpAffine(img, matRotation, (widthFinal, heightFinal), borderValue=(255, 255, 255))
cv2.cvtColor(dst, cv2.COLOR_BGR2RGB, dst)
plt.imshow(dst)
plt.show()

旋转结果:

Opencv图像处理系列(二)——几何变换

2.4 仿射变换

和2.3小节相似,仿射变换也是由opecv提供的函数生成一个2*3矩阵,然后由wrapAffine函数应用到图像。

仿射变换通过3个点的变换前后位置,来定义变换矩阵:

Mat cv::getAffineTransform    (    
const Point2f     src[], //变换前的点(个)
const Point2f     dst[]  //变换后的点(3个)
)

示例代码:

img = cv2.imread('test.jpg')
    rows, cols, chanels = img.shape
    pts1 = np.float32([[50, 50], [200, 50], [50, 200]])
    pts2 = np.float32([[10, 100], [200, 50], [100, 250]])
    M = cv2.getAffineTransform(pts1, pts2)
    dst = cv2.warpAffine(img, M, (cols,rows))

    cv2.cvtColor(dst, cv2.COLOR_BGR2RGB, dst)
    plt.imshow(dst)
    plt.show()

Opencv图像处理系列(二)——几何变换

2.5 透视变换

透视变换与仿射变换类似,仿射变换是透视变换的一种特殊情况。对应的矩阵计算函数和变换函数不同,示例如下:

img = cv2.imread('test.jpg')
rows, cols, ch = img.shape
pts1 = np.float32([[56, 65], [368, 52], [28, 387], [389, 390]])
pts2 = np.float32([[10, 90], [200, 150], [50, 200], [200, 250]])
M = cv2.getPerspectiveTransform(pts1, pts2)
dst = cv2.warpPerspective(img, M, (300, 300),borderValue=(0,255,0))
cv2.cvtColor(img, cv2.COLOR_BGR2RGB, img)
cv2.cvtColor(dst, cv2.COLOR_BGR2RGB, dst)
plt.subplot(121), plt.imshow(img), plt.title('Input')
plt.subplot(122), plt.imshow(dst), plt.title('Output')

Opencv图像处理系列(二)——几何变换

2.6 边缘模式/值

上面的示例中,可以发现几何变换后,图片边缘可能需要填充一些内容。 填充的方式是通过wrapAffine函数的borderMode、borderValue方式填充的,默认情况下borderMode为BORDER_CONSTANT,borderValue为(0,0,0)

borderMode取值如下:

Opencv图像处理系列(二)——几何变换

例如

用绿色填充边缘:

dst = cv2.warpAffine(img, M, (1500,1500),borderValue=(0,255,0))

Opencv图像处理系列(二)——几何变换

透明边缘:

dst = cv2.warpAffine(img, M, (1500,1500), borderMode=cv2.BORDER_TRANSPARENT,borderValue=(0,255,0))

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Paradigms of Artificial Intelligence Programming

Paradigms of Artificial Intelligence Programming

Peter Norvig / Morgan Kaufmann / 1991-10-01 / USD 77.95

Paradigms of AI Programming is the first text to teach advanced Common Lisp techniques in the context of building major AI systems. By reconstructing authentic, complex AI programs using state-of-the-......一起来看看 《Paradigms of Artificial Intelligence Programming》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具