内容简介: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图像处理系列(六)—— 图像梯度
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。