python+OpenCV图像处理(四)图像的简单几何变换

图像的简单几何变换

先看一下关于图像几何变换的简介:

几何变换不改变图像的像素值,只是在图像平面上进行像素的重新安排。

适当的几何变换可以最大程度地消除由于成像角度、透视关系乃至镜头自身原因所造成的几何失真所产生的负面影响。有利于我们在后续的处理和识别工作中将注意力集中子图像内容本身,更确切地说是图像中的对象,而不是该对象的角度和位置等。几何变换常常作为图像处理应用的预处理步骤,是图像归一化的核心工作之一。

一个几何变换需要两部分运算:首先是空间变换所需的运算,如平移、缩放、旋转和正平行投影等,需要用它来表示输出图像与输入图像之间的(像素)映射关系;此外,还需要使用灰度差值算法,因为按照这种变换关系进行计算,输出图像的像素可能被映射到输入图像的非整数坐标上。

(一)图形的平移

对于图像的平移非常简单,在平移之前,我们需要先构造一个移动矩阵,所谓移动矩阵,就是让说明白在x轴方向上移动多少距离,在y轴上移动多少距离。

通过numpy来构造这个矩阵,并将其传给仿射函数cv2.warpAffine( )

仿射函数cv2.warpAffine( )接受三个参数,需要进行图像变换的原始图像矩阵,移动矩阵以及图像变换的大小(这里要说明一下,图像本身并不会放大或缩小,而是图像显示区域的大小)

img = cv2.imread('4.jpg')
# 构造移动矩阵H
# 在x轴方向移动多少距离,在y轴方向移动多少距离
H = np.float32([[1, 0, 50], [0, 1, 25]])
rows, cols = img.shape[:2]
print(img.shape)
print(rows, cols)
res = cv2.warpAffine(img, H, (cols, rows))  # 注意这里rows和cols需要反置,个人感觉这里是一个坑
cv2.imshow('origin_picture', img)
cv2.imshow('new_picture', res)
cv2.waitKey(0)

(二)图像的放大和缩小

图像的放大和缩小有一个专门的函数,就是cv2.resize( ),这其中就需要设置缩放的比例,一种办法是设置缩放因子,另一种办法是直接设置图像的大小,在缩放以后,图像必然会发生变化,这就涉及到图像的插值问题。

缩放有几种不同的插值(interpolation)方法,在缩小时推荐使用cv2.INTER_AREA,扩大时推荐使用cv2.INTER_CUBIC和cv2.INTER_LINEAR。

img = cv2.imread('4.jpg')
# 一是通过设置图像缩放比例,即缩放因子,来对图像进行放大或缩小
res1 = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_LINEAR)
height, width = img.shape[:2]
# 二是直接设置图像的大小,不需要缩放因子
res2 = cv2.resize(img, (int(0.8*width), int(0.8*height)), interpolation=cv2.INTER_AREA)
cv2.imshow('origin_picture', img)
cv2.imshow('res1', res1)
cv2.imshow('res2', res2)
cv2.waitKey(0)

关于插值算法有很多,我这里举一个例子。

最近邻插值算法:选择离它映射到的位置最近的输入像素的灰度值为插值结果。

通过图像长和宽的比例,将原有的图像映射到所需要的图像上。这里涉及到对图像矩阵元素的操作,对于其如何计算的可以看代码,也可以联系我,从数学的角度解释。

# need_height参数不得超过原来图像高的两倍,这是由临近插值算法本身的性质所决定的
# need_width参数则可以任意选取
def pic_interpolation(img, need_height, need_width):height, width, channels = img.shapeprint(height, width, channels)emptyImage = np.zeros((need_height, need_width, channels), np.uint8)sh = need_height/heightsw = need_width/widthfor i in range(need_height):for j in range(need_width):x = round(i/sh)y = math.floor(j/sw)emptyImage[i, j] = img[x, y]return emptyImageimg = cv2.imread("4.jpg")
zoom = pic_interpolation(img, 220, 180)
cv2.imshow("nearest neighbor", zoom)
cv2.imshow("image", img)
cv2.waitKey(0)

(三)图像的旋转

对于图像的旋转,我们需要构造旋转矩阵。一般的图像的旋转矩阵是在原点处进行变换的


为了能够在任意位置进行旋转变换,OpenCV采用了另一种方式


为了构造这个矩阵,OpenCV提供了一个函数:cv2.getRotationMarix2D( ),这个函数需要三个参数,旋转中心,旋转角度,旋转后图像的缩放比例:

img = cv2.imread('4.jpg')
rows, cols = img.shape[:2]
# 第一个参数是旋转中心,第二个参数是旋转角度,第三个参数是缩放比例
M1 = cv2.getRotationMatrix2D((cols/2, rows/2), 45, 0.5)
M2 = cv2.getRotationMatrix2D((cols/2, rows/2), 45, 2)
M3 = cv2.getRotationMatrix2D((cols/2, rows/2), 45, 1)
res1 = cv2.warpAffine(img, M1, (cols, rows))
res2 = cv2.warpAffine(img, M2, (cols, rows))
res3 = cv2.warpAffine(img, M3, (cols, rows))
cv2.imshow('res1', res1)
cv2.imshow('res2', res2)
cv2.imshow('res3', res3)
cv2.waitKey(0)
cv2.destroyAllWindows()

(四)图像的仿射

仿射变换是指在向量空间中进行一次线性变换(乘以一个矩阵)并加上一个平移(加上一个向量),变换为另一个向量空间的过程。

Affine Transform描述了一种二维仿射变换的功能,它是一种二维坐标之间的线性变换,保持二维图形的“平直性”(即变换后直线还是直线,圆弧还是圆弧)和“平行性”(其实是保持二维图形间的相对位置关系不变,平行线还是平行线,而直线上的点位置顺序不变,另特别注意向量间夹角可能会发生变化)。仿射变换可以通过一系列的原子变换的复合来实现包括:平移(Translation)、缩放(Scale)、翻转(Flip)、旋转(Rotation)和错切(Shear)。

仿射变化也是需要一个M矩阵就可以,但是由于仿射变换比较复杂,很难找到这个矩阵,opencv提供了根据变换前后三个点的对应关系来自动求解M, 这个函数是cv2.getAffineTransoform(pts1, pts2)

事实上,仿射变换代表的是两幅图之间的关系,我们通常使用2x3矩阵来表示仿射变换如下:


img = cv2.imread('4.jpg')
rows, cols = img.shape[:2]
pts1 = np.float32([[50, 50], [200, 50], [50, 200]])
pts2 = np.float32([[10, 100], [200, 50], [100, 250]])
# 类似于构造矩阵
M = cv2.getAffineTransform(pts1, pts2)
res = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('原图', img)
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

(五)图像的透射

仿射变换(affine transform)与透视变换(perspective transform)在图像还原、图像局部变化处理方面有重要意义。通常,在2D平面中,仿射变换的应用较多,而在3D平面中,透视变换又有了自己的一席之地。两种变换原理相似,结果也类似,可针对不同的场合使用适当的变换。

基于3×3矩阵进行的变换,叫透视变换或者单应性映射

仿射变换可以形象的表示成以下形式。一个平面内的任意平行四边形ABCD可以被仿射变换映射为另一个平行四边形A’B’C’D’。通俗的解释就是,可以将仿射变换想象成一幅图像画到一个胶版上,在胶版的角上推或拉,使其变形而得到不同类型的平行四边形。相比较仿射变换,透射变换更具有灵活性,一个透射变换可以将矩形转变成梯形。

img = cv2.imread('4.jpg')
rows, cols = img.shape[:2]
pts1 = np.float32([[56, 65], [238, 52], [28, 237], [239, 240]])
pts2 = np.float32([[0, 0], [200, 0], [0, 200], [200, 200]])
M = cv2.getPerspectiveTransform(pts1, pts2)
res = cv2.warpPerspective(img, M, (cols, rows))
cv2.imshow('yuantu', img)
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/490848.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

谷歌AI自动重建果蝇大脑,离绘制人脑更进一步

来源:googleblog、biorxiv、venturebeat导语:将果蝇的大脑分割成成千上万个40纳米的超薄切片?不怕,谷歌新AI技术能够重建果蝇完整大脑。智东西8月6日消息,据外媒报道,谷歌刚刚公布了一项最新研究结果“用洪…

python+OpenCV图像处理(五)图像的阈值分割

图像的阈值处理一幅图像包括目标物体、背景还有噪声,要想从多值的数字图像中直接提取出目标物体,常用的方法就是设定一个阈值T,用T将图像的数据分成两部分:大于T的像素群和小于T的像素群。这是研究灰度变换的最特殊的方法&#xf…

git Please move or remove them before you can merge. 错误解决方案

git pull 时 往往会遇到各种各样的问题 ,下面是常遇到的一种状况 Updating 7c9e086..936acacerror: The following untracked working tree files would be overwritten by merge:Common/HFHttpRequest/HFHttpRequestParameters.hCommon/HFHttpRequest/HFHttpRequestParameters…

为什么有些softmax公式需要减去输入中的最大值

我们都知道softmax公式如下: 但有些softmax公式是先将每个x_i减去x中的最大值再代入以上公式 原因是为了防止上溢和下溢 举个例子,x[100000,100001,100002],如果直接代入上式数值会非常大,当对每个x的值减去x中的最大值后得到[-2,-1,0]&…

决策树算法框架

决策树算法框架 (一)决策树主函数各种决策树的主函数都大同小异,本质上是一个递归函数。该函数的主要功能是按照某种规则生长决策树的各个分支节点,并根据终止条件结束算法。一般来讲,主函数需要完成如下几个功能。 &a…

基于哈夫曼编码完成的文件压缩及解压

这几天在较为认真的研究基于哈夫曼编码的文件压缩及解压,费了点时间,在这分享一下: 这里用链式结构,非顺序表结构; 文件压缩: 1.获取文件信息(这里采用TXT格式文本); 2.压…

兰德公司报告分析 “分布式作战”对美空军兵力运用的影响

来源:兰德公司网站/图片来自互联网导读7月17日,兰德公司发布《竞争环境下的分布式作战:对美国空军兵力运用的影响》的报告,研究了美空军竞争环境下“分布式作战”的能力需求,分析了如何调整美空军当前的“兵力运用模式…

Keras中LSTM的return_sequences和return_state

keras.layers.LSTM()函数有两个重要的参数return_sequences和return_state return_sequences和return_state默认都为false,接下来分别讲解当return_sequences和return_state取不同值时LSTM函数的返回值 return_sequencesTrue会返回每个时间步的隐藏状态&#xff0…

MATLAB(四)在高等数学中的应用

MATLAB在高等数学中的应用 (一)求极限 matlab中求极限的命令为 limit(expr, x, a) limit(expr, a) limit(expr) limit(expr, x, a, left) limit(expr, x, a, right) 其中,limit(expr, x, a)表示求符号表达式expr关于符号变量x趋近于a时的…

华为手机到底用了多少美国芯?外媒拆解来了

来源:iFixit、IT之家从拆解结果来看,华为Mate 20 X (5G)手机除了使用了3颗美国的芯片产品(美光内存、SkyworksWCDMA/LTE低端前端模块、Qorvo中高频段模块)以及荷兰公司恩智浦的芯片产品,其余主要部件基本上都是由华为海…

c++判断字符是否为空格或数字

判断字符是否为空格的函数: isspace() 标准的空白字符包括: (0x20) space (SPC) 空格符 \t (0x09) horizontal tab (TAB) 水平制表符 \n (0x0a) newline (LF) 换行符 \v (0x0b) vertical tab (VT) 垂直制表符 \f (0x0c) …

[改善Java代码] 推荐使用序列化实现对象的拷贝

建议44: 推荐使用序列化实现对象的拷贝 上一个建议说了对象的浅拷贝问题,实现Cloneable接口就具备了拷贝能力,那我们来思考这样一个问题:如果一个项目中有大量的对象是通过拷贝生成的,那我们该如何处理?每个…

MATLAB(五)在线性代数中的应用

MATLAB在线性代数中的应用 (一)向量组的线性相关性 求列向量组A的一个最大线性无关组,可用命令rref(A)将A化成行最简形,其中单位向量对应的列向量即为最大线性无关组所含向量,其他列向量的坐标即为其对应向量用最大线…

C++一位的字符数字转数字

char c4; //1,2,3,.....9 int num0; num int(c - 0);’0’的ASC码是48,‘1’,‘2’......的ASC码分别为49,50...... 和0相减即为对应的数字

关于无穷大量的选择

在解题时候,通常有遇到设置为无穷大的情况。这时候通常用0x7fffffff来设置,他是计算机32位整数最大数,相当于INT_MAX.但是在很多时候这样设置并不会是最佳的,还可能导致bug,这是由于我们有的时候希望无穷大无穷大无穷大&#xff0…

全球市值最大公司的巨变:20年,已是沧海桑田

来源: 资本实验室三十年河东,三十年河西。而商业的世界,变化来得更为迅猛、激烈。就比如当我们比较1999到2019年间的全球市值最大公司,并回看二十年时,惊觉已是沧海桑田。如果以更短的五年为一个观察周期,则…

python+OpenCV图像处理(六)图像平滑与滤波

图像平滑与滤波 运用它,首先就要了解它,什么是平滑滤波? 平滑滤波是低频增强的空间域滤波技术。它的目的有两类:一类是模糊;另一类是消除噪音。空间域的平滑滤波一般采用简单平均法进行,就是求邻近像元点的…

pytorch每次迭代训练前都重新对数据集进行采样形成平衡数据集

对于不平衡数据集的训练通常有两种方法: 一种是先用数据平衡的方法形成平衡数据集之后用于每一轮的训练,此时每轮训练的数据集是不变的,这一方法在pytorch的实现比较简单,即先构建好平衡数据集train_set,然后构建trai…

Delphi中动态调用DLL的方法

Delphi中动态调用dll的方法如下&#xff1a; function CallFunc(dllname, funcname: string; const param: array of const): DWORD; varhLib: THandle;pFunc: Pointer;intSize: Integer; beginResult : 0;hLib : LoadLibrary(PChar(dllname));if hLib <> 0 then beginpF…

语音助手再次敲响隐私保护警钟

来源&#xff1a; 中国科学报智能手机内置的语音助手已成为人们生活中的亲密伙伴&#xff0c;大家习惯于让它完成报时、查询天气等日常任务甚至与它聊天解闷。然而&#xff0c;近期多家科技公司被曝光以智能语音助手录制用户谈话&#xff0c;再通过人工对语音做标注和反馈&…