opencv学习记录之几何变换

------------恢复内容开始------------

几何变换是指将一幅图像映射到另外一幅图像内的操作

一、缩放

函数具体形式为

dst = cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])

dst代表输出的目标图像,类型与src相同,大小为dsize 或可以通过src.size() ,fx,fy计算得到

src代表需要缩放的原始图像

dsize代表输出图像大小

fx表示水平方向的缩放比例

fy表示垂直方向的缩放比例

interpolation代表插值方式

当缩小图像时,使用区域插值方式(INTER_AREA)能够得到最好的效果

当放大图像时,使用三次样条插值(INTER_CUBIC)方式和双线性插值(INTER_LINEAR)方式能够取的较好的结果,

1 import cv2
2 img = cv2.imread("/home/miao/dog.jpg")
3 rows,cols = img.shape[:2]
4 size = (int( cols*0.9) , int(rows * 0.5))
5 rst = cv2.resize( img , size)
6 print("img.shape=" , img.shape)
7 print("rst.shape=" , rst.shape)
img.shape= (200, 300, 3)
rst.shape= (100, 270, 3)

列数变为原来0.9倍,行数变为原来0.5倍

1 import cv2
2 img = cv2.imread("/home/miao/dog.jpg")
3 rst = cv2.resize(img , None , fx = 2 , fy = 0.5)
4 print("img.shape= " , img.shape)
5 print("rst.shape= " , rst.shape)
img.shape=  (200, 300, 3)
rst.shape=  (100, 600, 3)

fx是水平方向的缩放,将列数变为原来的2倍

fy是垂直方向的缩放,将行数变为原来的0.5倍

二、翻转

该函数可以实现垂直方向、水平方向和两个方向同时翻转

函数形式为

dst = cv2.flip( src , flipCode)

flipCode代表旋转类型,参数意义如下

参数值 说明 意义
0 只能是0 绕着x轴翻转
正数 1、2、3等任意正数 绕着y轴翻转
负数 -1、-2、-3等任意负数 围绕x轴,y轴同时翻转
 1 import cv2
 2 img = cv2.imread("/home/miao/dog.jpg")
 3 x = cv2.flip(img , 0)
 4 y = cv2.flip(img , 1)
 5 xy = cv2.flip(img , -1)
 6 cv2.imshow("img" , img)
 7 cv2.imshow("x" , x)
 8 cv2.imshow("y" , y)
 9 cv2.imshow("xy" , xy)
10 cv2.waitKey()
11 cv2.destroyAllWindows()

原图

x

y

xy

三、仿射

通过一系列的几何变换来实现平移、旋转等多种操作。该变换保持图像的平直性和平行性,

平直性是指在经过变换后直线仍然是直线

平行性是指在完成仿射变换后,平行线仍然是平行线

函数形式为

dst = cv2.warpAffine( src , M , dsize [, flags [, borderMode [, borderValue]]])

dst代表仿射后的输出图像

src代表要仿射的原始图像

M代表一个2x3的变换矩阵

dsize代表要输出图像的尺寸

flags代表插值方法,默认为INTER_LINEAR

borderMode代表边类型,默认为DORDER_CONSTANT

borderValue代表边界值,默认为0

通过转换矩阵M将原始图像src转换为目标图像dst

dst(x,y) = src(M11*x + M12 *y + M13 ,M21 * x + M22 * y + M23)

平移

 1 import cv2
 2 import numpy as np
 3 img = cv2.imread("/home/miao/dog.jpg")
 4 height , width = img.shape[:2]
 5 x = 50
 6 y = 100
 7 M = np.float32([[1,0,x] , [0 , 1, y]])
 8 move = cv2.warpAffine(img , M ,(width , height))
 9 cv2.imshow("original" , img )
10 cv2.imshow("move" , move)
11 cv2.waitKey()
12 cv2.destroyAllWindows()

由上的公式可得

dst( x , y) = src(1*x + 0 * y + 50 , 0 * x + 1 * y +100)

即可得到图像的平移

旋转需要调用函数来生成转换矩阵M

函数形式如下

cv2.getRotationMatrix2D(center , angel , scale)

center为旋转中心点

angel为旋转角度,整数表示逆时针旋转,负数表示顺时针旋转

scale为变换尺度(缩放大小)

1 import cv2
2 img = cv2.imread("/home/miao/dog.jpg")
3 height , width = img.shape[:2]
4 M = cv2.getRotationMatrix2D((width/2 , height/2) , 45 , 0.6 )
5 rotate = cv2.warpAffine(img , M , (width , height))
6 cv2.imshow("original" , img)
7 cv2.imshow("rotation" , rotate)
8 cv2.waitKey()
9 cv2.destroyAllWindows()

函数是以图中心为原点,逆时针旋转45度,并将目标图像缩小为原始图像的0.6倍

更复杂的仿射变换

通过函数

cv2.getAffineTransform( src , dst)

src为输入图像的三个点坐标

dst为输出图像的三个点坐标

三个点坐标为对应平行四边形的左上角,右上角和左下角三个点

 1 import cv2
 2 import numpy as np
 3 img = cv2.imread("/home/miao/dog.jpg")
 4 rows , cols, ch = img.shape
 5 p1 = np.float32([[0,0],[cols-1,0] , [0,rows-1]])
 6 p2 = np.float32([[0,rows*0.33],[cols*0.85, rows*0.25],[cols*0.15,rows*0.71]])
 7 M = cv2.getAffineTransform(p1 , p2)
 8 dst = cv2.warpAffine(img , M ,(cols , rows))
 9 cv2.imshow("original" , img)
10 cv2.imshow("result" , dst)
11 cv2.waitKey()
12 cv2.destroyAllWindows()

四、重映射

将一幅图像内的像素点放置到另外一幅图像内的指定位置即为重映射

函数形式为

dst = cv2.remap( src , map1 , map2 ,interpolation [, borderMode [ , borderValue]])

dst 代表目标图像,它和src具有相同的大小和类型

src代表原始图像

map1

1.表示(x,y)点的一个映射

2.表示CV _16SC2 , CV_32FC1 ,CV_32FC2类型(x,y)点的x值

map2

1.当map1表示(x,y)时,该值为空

2.当map1表示(x,y)点的x值时,该值是CV_16UC1,CV_32FC1类型(x,y)点的y值

interpolation代表插值方式,这里不支持INTER_AREA

borderMode代表边界模式,

borderValue代表边界值,该值默认为0

以下为将原始图像内第0行第3列上的像素值映射到所有像素点,即map1为3,map2为0

其映射关系即为map1和map2对应的像素位置对应图像的像素点的位置,即map1和map2的[0,0]对应图像的[0,0],然后将结果位置值存入该点,即map1存第几列,map2存第几行。对应以下代码即每个点映射的都是[0,3]的值

 1 import cv2
 2 import numpy as np
 3 img = np.random.randint( 0 ,256 , size = [4,5] , dtype = np.uint8)
 4 rows , cols = img.shape
 5 mapx = np.ones(img.shape , np.float32) * 3
 6 mapy = np.ones(img.shape , np.float32) * 0
 7 rst = cv2.remap( img , mapx ,mapy ,cv2.INTER_LINEAR)
 8 print("img = \n" , img)
 9 print("mapx = \n" , mapx)
10 print("mapy = \n" , mapy)
11 print("rst = \n" , rst)
img =
 [[150 228 176  51  98]
 [126 172 203 204  89]
 [ 84  31 202 132  61]
 [ 85  44  44 169 204]]
mapx =
 [[3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3.]
 [3. 3. 3. 3. 3.]]
mapy =
 [[0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0.]]
rst =
 [[51 51 51 51 51]
 [51 51 51 51 51]
 [51 51 51 51 51]
 [51 51 51 51 51]]

结果即为全是51

 1 import cv2
 2 import numpy as np
 3 #img = np.random.randint( 0 , 256 , size = [9,9] , dtype = np.uint8)
 4 img = cv2.imread("/home/miao/dog.jpg")
 5 rows , cols = img.shape[:2]
 6 mapx = np.zeros(img.shape[:2] , np.float32)
 7 mapy = np.zeros(img.shape[:2] , np.float32)
 8 for i in range(rows):
 9     for j in range(cols):
10         mapx.itemset((i,j) , j)
11         mapy.itemset((i,j) , i)
12 rst_copy = cv2.remap(img , mapx , mapy , cv2.INTER_LINEAR)
13
14 for i in range(rows):
15     for j in range(cols):
16         mapx.itemset((i,j) , j)
17         mapy.itemset((i,j) , rows - 1 -i)
18 rst_x = cv2.remap(img , mapx , mapy , cv2.INTER_LINEAR)
19
20 for i in range(rows):
21     for j in range(cols):
22         mapx.itemset((i,j) ,cols - 1-  j)
23         mapy.itemset((i,j) , i)
24 rst_y = cv2.remap(img , mapx , mapy , cv2.INTER_LINEAR)
25
26 for i in range(rows):
27     for j in range(cols):
28         mapx.itemset((i,j) ,cols - 1 - j)
29         mapy.itemset((i,j) ,rows - 1 - i)
30 rst_xy = cv2.remap(img , mapx , mapy , cv2.INTER_LINEAR)
31
32 for i in range(rows):
33     for j in range(cols):
34         mapx.itemset((i,j) ,i )
35         mapy.itemset((i,j) ,j )
36 rst_x_y = cv2.remap(img , mapx , mapy , cv2.INTER_LINEAR)
37
38 for i in range(rows):
39     for j in range(cols):
40         if 0.25*cols<j<0.75*cols and 0.25*rows<i<0.75*rows:
41             mapx.itemset((i,j) , 2*(j - 0.25*cols)  + 0.5)
42             mapy.itemset((i,j) , 2*(i - 0.25*rows)  + 0.5)
43
44         else :
45             mapx.itemset((i,j) , 0)
46             mapy.itemset((i,j) , 0)
47
48 rst = cv2.remap(img , mapx , mapy , cv2.INTER_LINEAR)
49 cv2.imshow("original" , img)
50 cv2.imshow("rst_x" , rst_x)
51 cv2.imshow("rst_y" , rst_y)
52 cv2.imshow("rst_xy" , rst_xy)
53 cv2.imshow("rst_x_y" , rst_x_y)
54 cv2.imshow("result" , rst)
55 cv2.waitKey()
56 cv2.destroyAllWindows()

原图

复制(第一个for循环)

绕x轴旋转(第二个for循环)

绕y轴旋转(第三个for循环)

绕x轴、y轴(第四个for循环)

x轴、y轴交换(第五个for循环)

图像缩放(第六个for循环)

图像缩放的for循环中

if 0.25*cols<j<0.75*cols and 0.25*rows<i<0.75*rows:
    mapx.itemset((i,j) , 2*(j - 0.25*cols)  + 0.5)
    mapy.itemset((i,j) , 2*(i - 0.25*rows)  + 0.5)else :     mapx.itemset((i,j) , 0)      mapy.itemset((i,j) , 0) 

将列值和行值取在0.25-0.75的范围内,其他范围取值为(0,0)的值

在该范围内j减去0.25cols是为了可以从0到cols-1,乘2是每2个点取一次

加0.5是取两个像素点之间的位置,该点是不存在像素值的,可以采用不同的方法实现插值

------------恢复内容结束------------

file:///home/miao/桌面/y.png

原文地址:https://www.cnblogs.com/miaorn/p/12186737.html

时间: 2024-11-13 08:55:20

opencv学习记录之几何变换的相关文章

【opencv学习记录】以迭代器方式访问图像像素,统计像素信息存入文件

opencv2.4.9,练习使用图像迭代器访问像素值+STL中的vector #include <opencv2\core\core.hpp> #include <opencv2\highgui\highgui.hpp> #include <opencv2\imgproc\imgproc.hpp> #include <iostream> #include <fstream> using namespace std; using namespace

opencv学习记录

1 #include<iostream> 2 #include <opencv2/core/core.hpp> 3 #include <opencv2/highgui/highgui.hpp> 4 using namespace cv; 1 Mat img4 = imread("LinuxLogo.jpg"); 2 // 创建画"窗口 3 namedWindow("4"); 4 // 在窗口中显示游戏原画 5 imsho

opencv学习记录之图像运算

图像的运算可以是十进制的值运算也可以是二进制的位逻辑运算 一.图像加法运算 1 import cv2 2 import numpy as np 3 img1 = np.random.randint(0,256, size = [3,3] , dtype = np.uint8) 4 img2 = np.random.randint(0,256, size = [3,3] , dtype = np.uint8) 5 img3 = cv2.add(img1,img2) 6 print("img1 =\

opencv学习记录之阈值处理

阈值处理是指将图像内高于一定值或者低于一定值的像素点进行处理 函数形式为: retval ,dst = cv2.thresshold( src , thresh , maxval , type ) retval代表返回的阈值 dst代表阈值分割结果图像,与原始图像有相同的大小和类型 src代表要进行分割的图像,可以是多通道的 thresh代表要设定的阈值 maxval代表当type为THRESH_BINARY或者THRESH_BINARY_INV类型时,需要设定的最大值 type代表阈值分割的类

opencv学习记录之形态学操作

腐蚀和膨胀是形态学运算的基础,将腐蚀和膨胀进行组合运算,通过不同的组合可以实现不同的效果,需要自行开发则可以实现开运算,闭运算,形态学梯度运算,礼帽运算 黑帽运算,击中击不中运算等不同形式的运算 函数形式 dst = cv2.morphologyEx( src , op , kernel [ , anchor [ , interations [, borderType [ , borderValue]]]]) dst 形态学操作之后的图像,与原图像类型大小相同 src需要操作的图像,与之腐蚀和膨

opencv学习记录之模板匹配

模板匹配是指在图像A中寻找与图像B最相似的部分,一般A称为输入图像,B称为模板图像 模板匹配函数 result = cv2.matchTemplate(image , temp1 , method , [,mask]) result 函数每次计算模板和输入图像的重叠区域相似度之后将结果存入映射图像result中, result图像中每个点都代表一次相似度的比较,类型是单通道32位浮点型 若输入图像的尺寸位W×H,模板图像为w×h,则返回值为(W-w+1)×(H-h+1) 模板在原始图像上遍历,左

opencv学习笔记(四)投影

opencv学习笔记(四)投影 任选了一张图片用于测试,图片如下所示: 1 #include <cv.h> 2 #include <highgui.h> 3 using namespace std; 4 using namespace cv; 5 int main() 6 { 7 IplImage * src = cvLoadImage("cat.png", 0); //强制转化读取图像为灰度图 8 cvShowImage("灰度图像", s

OpenCV学习笔记(01)我的第一个OpenCV程序(环境配置)

昨天刚刚考完编译原理,私心想着可以做一些与考试无关的东西了.一直想做和图像处理相关的东西,趁这段时间有空学习一下OpenCV,搭建环境真是一件麻烦的事情,搞了近三个小时终于OK了.先来张图: 大致描述一下步骤吧: 一.安装前准备 1.VS2012(网上看到很多用的VS2010,但是基本不影响) 2.OpenCV 安装包(我下载的是最新的2.4.9) 二.安装OpenCV 1.解压OPenCV 说是安装,其实就是解压,OpenCV的Windows安装程序就是一个自解压程序: 这里我解压到C:\Pr

OpenCV学习笔记[5]FLANN特征匹配

OpenCV学习笔记:FLANN特征匹配 本次给出FLANN特征匹配的Java实现. [简介] 特征匹配记录下目标图像与待匹配图像的特征点(KeyPoint),并根据特征点集合构造特征量(descriptor),对这个特征量进行比较.筛选,最终得到一个匹配点的映射集合.我们也可以根据这个集合的大小来衡量两幅图片的匹配程度. 特征匹配与模板匹配不同,由于是计算特征点集合的相关度,转置操作对匹配影响不大,但它容易受到失真.缩放的影响. [特征匹配] FeatureMatching.java: imp