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))

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

查看所有标签

猜你喜欢:

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

运营之光 2.0

运营之光 2.0

黄有璨 / 电子工业出版社 / 2017-4 / 99

在互联网行业内,“运营”这个职能发展到一定阶段后,往往更需要有成熟的知识体系和工作方法来给予行业从业者以指引。 《运营之光:我的互联网运营方法论与自白 2.0》尤其难得之处在于:它既对“什么是运营”这样的概念认知类问题进行了解读,又带有大量实际的工作技巧、工作思维和工作方法,还包含了很多对于运营的思考、宏观分析和建议,可谓内容完整而全面,同时书中加入了作者亲历的大量真实案例,让全书读起来深入......一起来看看 《运营之光 2.0》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

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

UNIX 时间戳转换

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具