内容简介: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 //插值方法 )
插值方法取值如下:
示例:
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()
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的变换矩阵来表示:
例如:
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()
2.3 旋转
图像旋转θ角度,可以通过矩阵
来表示。
可以将缩放、旋转集成到一个变换矩阵中,并设置旋转的中心点:
其中:
α=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()
原图:
旋转图:
这里值得注意的是,旋转得到的结果,超出原始图片大小的部分会被裁剪掉,即使输出尺寸填写的很大,也只会填充黑色。
旋转的过程可以理解为:
- 将坐标系变换至旋转中心点
- 旋转
- 将坐标系变换至原图左上角
- 超出原坐标系的部分裁减掉
要避免这种情况,只需要在第三步,变换坐标系的时候,将原点选在一个合适的位置,并调整输出图像大小即可。此处参考 https://blog.csdn.net/u010122972/article/details/78345447
将旋转后的坐标原点由原始图像左上角,移动到旋转后图像视框左上角即可,需要做的工作有旋转后图像大小计算、旋转矩阵修改等。
代码实现如下:
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()
旋转结果:
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()
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')
2.6 边缘模式/值
上面的示例中,可以发现几何变换后,图片边缘可能需要填充一些内容。 填充的方式是通过wrapAffine函数的borderMode、borderValue方式填充的,默认情况下borderMode为BORDER_CONSTANT,borderValue为(0,0,0)
borderMode取值如下:
例如
用绿色填充边缘:
dst = cv2.warpAffine(img, M, (1500,1500),borderValue=(0,255,0))
透明边缘:
dst = cv2.warpAffine(img, M, (1500,1500), borderMode=cv2.BORDER_TRANSPARENT,borderValue=(0,255,0))
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 深度学习和几何(演讲提要)
- 基于数据驱动的三维几何解码器
- AI“画皮”,色情原罪之后,商业机遇几何?
- 哭了!好美!交互式《几何原本》再现江湖
- 红帽变“蓝”,IBM 豪赌云服务胜算几何?
- Opencv图像处理系列(六)—— 图像梯度
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
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》 这本书的介绍吧!