OpenCV图像处理之七种常用图像几何变换
作者:JeffchenITM 发布时间:2022-01-27 03:11:51
0 程序环境与所学函数
本章程序运行需要导入下面三个库,并定义了一个显示图像的函数
所学函数
##放大、缩小
cv.resize(img,dsize,[interpolation])
##平移变换
M = np.array([[...]], dtype=np.float32)
cv.warpAffine(img, M, dsize)
##镜像变换
cv.flip(img, 1) # 垂直镜像
cv.flip(img, 0) # 水平镜像
cv.flit(img, -1) # 水平垂直同时进行
##旋转变换
M = cv.getRotationMatrix2D(center, angle, scale)
img_rotate = cv.rotate(img, cv.ROTATE_90_CLOCKWISE)
##透视变换
M = cv.getPerspectiveTransform(src, dst)
img = cv.warpPerspective(img, M, dsize)
1 裁剪、放大、缩小
读入图像
img = cv.imread('pic/rabbit500x333.jpg')
show(img)
显示
裁剪:数组选择方法(冒号)
#裁剪
rabbit = img[150:450:] #限定行数,列数和三通道
show(rabbit)
显示
放大和缩小:resize()函数
插值方法
程序实现
#放大缩小
#cv.resize(img,dsize,[interpolation]) dsize表示大小,[interpolation]是插值方法,可选,有默认值
img2 = cv.resize(img,(500,400)) #放大为宽500高400
#使用定义插值方法
#一般来说放大地话选择LINEAR方法,缩小选择AREA方法
img3 = cv.resize(img,(500,400),interpolation=cv.INTER_NEAREST)
show(np.hstack([img2,img3]))
显示
2 平移变换
原理、平移矩阵推导
读入图像
img = cv.imread('pic/rabbit500x333.jpg')
show(img)
显示
程序实现
# M = np.array([[...]],dtype=np.float32)
# cv.warAffine(img,M,dsize) cv里面图像仿射变换函数,M是上面矩阵,dsize是输出图像大小
M=np.array([
[1,0,100],
[0,1,50]
],dtype=np.float32) #水平向右平移100个像素点,竖直向下平移50个像素点,原理见理论部分
img2 = cv.warpAffine(img,M,(333,500))
show(img2)
显示
3 错切变换
原理、错切矩阵推导
读入图像
img = cv.imread('pic/rabbit500x333.jpg')
show(img)
显示
水平错切
M = np.array([
[1,0.2,0],
[0,1,0]
],dtype=np.float32)
img3 = cv.warpAffine(img,M,(533,500))
show(img3)
显示
垂直错切
M = np.array([
[1,0,0],
[0.3,1,0]
],dtype=np.float32)
img3 = cv.warpAffine(img,M,(333,700))
show(img3)
显示
4 镜像变换
原理、镜像矩阵推导
读入图像
img = cv.imread('pic/rabbit500x333.jpg')
show(img)
显示
水平镜像
Mx = np.array([
[-1,0,333],
[0,1,0]
],dtype = np.float32)
img2 = cv.warpAffine(img,Mx,(333,500)) #仿射变换函数
show(img2)
显示
垂直镜像
My = np.array([
[1,0,0],
[0,-1,500]
],dtype=np.float32)
img3 = cv.warpAffine(img,My,(333,500))
show(img3)
显示
opencv内置函数实现镜像变换
#垂直镜像 cv.flip(img,1)
#水平镜像 cv.flip(img,0)
#水平垂直同时进行 cv.flip(img,-1)
程序实现
img4 = cv.flip(img,1) #垂直镜像
img5 = cv.flip(img,0) #水平镜像
img6 = cv.flip(img,-1) #水平垂直镜像同时进行
show(np.hstack([img4,img5,img6]))
显示
5 旋转变换
原理、旋转矩阵推导
读入图像
img = cv.imread('pic/rabbit500x333.jpg')
show(img)
显示
图像旋转
beta = np.pi/4
#旋转矩阵
M = np.array([
[np.cos(beta),np.sin(beta),0],
[-np.sin(beta),np.cos(beta),0]
],dtype=np.float32)
img2 = cv.warpAffine(img,M,(633,300))
show(img2)
显示
opencv内置获取旋转矩阵函数:
M = cv.getRotationMatrix2D(center,angle,scale)
center是旋转中心,angle是旋转角度,scale表示放大还是缩小
用上面函数获取旋转矩阵并实现图像旋转
h,w,c = img.shape #获取图像的高度和宽度,方便后面设置旋转中心
M2 = cv.getRotationMatrix2D((w//2,h//2),45,1)
img3 = cv.warpAffine(img,M2,(533,500)) #仿射函数实现
show(img3
显示
opencv内置实现图像旋转函数
img_rotate =cv.rotate(img,cv.ROTATE_90_COUNTERCLOCKWISE)
只能进行90度倍数的旋转
程序实现
# 逆时针旋转90度
img_rotate = cv.rotate(img,cv.ROTATE_90_COUNTERCLOCKWISE)
show(img_rotate)
显示
6 透视变换
M = cv.getPerspectiveTransform(str,dst)
str:原始图像矩阵端点位置,dst:目标图像矩阵位置
img2 = cv.warpPerspective(img,M,(w,h))
读入图像
img = cv.imread('pic/parthenon500x750.jpg')
show(img)
显示
程序实现
#在原图中定位四个点,这里找的是柱子前面四个点的大概位置,眼睛观察法找的
str = np.array([
[210,50],
[610,270],
[650,470],
[150,450]
],dtype=np.float32)
#目标图像中矩阵
dst = np.array([
[150,50],
[650,50],
[650,470],
[150,470]
],dtype=np.float32)
h,w,c = img.shape
#透视变换将一个类似矩形的图形拉成一个矩形
M = cv.getPerspectiveTransform(str,dst)
img2 = cv.warpPerspective(img,M,(w,h))
show(img2)
显示
应用:车道检测、图片矫正
7 最近邻插值、双线性插值
原理:
最近邻插值图示:
双线性插值图示
读入图像
img = cv.imread('pic/rabbit50x33.jpg')
show(img)
显示
程序实现
img1 = cv.resize(img,(330,500),interpolation=cv.INTER_NEAREST) #最近邻插值
img2 = cv.resize(img,(330,500),interpolation=cv.INTER_LINEAR_EXACT) #精确双线新插值
show(np.hstack([img1,img2]))
显示
可以看出最近邻插值还是比较模糊的,过渡结果没有双线性插值平滑
来源:https://blog.csdn.net/weixin_43498449/article/details/121874204
猜你喜欢
- 前言汉诺塔问题是一个经典的问题。汉诺塔(Hanoi Tower),又称河内塔,源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,
- <%'asp事务处理。'测试数据库为sql server,服务器为本机,数据库名为test,表名为a,两个字段id(i
- 实现在线人数统计最常用的方法就是golobal.asa结合session做,但这种方法有两个不利: 1、每个session要占用12k的服务
- Socket有一个缓冲区,缓冲区是一个流,先进先出,发送和取出的可自定义大小的,如果取出的数据未取完缓冲区,则可能存在数据怠慢。其中【rec
- 目录logging的简单使用|2logging常见对象|3logging基本使用|4logging之Formatter对象|5logging
- 因为写js经常需要用到访问样式,我们常用的做法是通过 DOM.style.XXX来读写样式信息的。可是DOM.style这种写法只能访问&l
- 字符函数——返回字符值这些函数全都接收的是字符族类型的参数(CHR除外)并且返回字符值.除了特别说明的之外,这些函数大部分返回VARCHAR
- JavaScript: <script type="text/javascript"> var level1
- javascript的分号代表语句的结束符,但由于javascript具有分号自动插入规则,所以它是一个十分容易让人模糊的东西,在一般情况下
- 现在对于python2版本,直接修改python.exe名字为python2.exe,命令python2 -m pip install --
- 简介django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddlewa
- 本文实例讲述了python妹子图简单爬虫实现方法。分享给大家供大家参考。具体如下:#!/usr/bin/env python#coding:
- 复制一个文件夹的文件到指定目录下import osimport shutilimport timestart_time = time.tim
- 实例如下所示:#!/usr/bin/python# -*- coding: UTF-8 -*-import smtplibimport em
- 对于每个程序开发者来说,调试几乎是必备技能。代码写到一半卡住了,不知道这个函数执行完的返回结果是怎样的?调试一下看看代码运行到一半报错了,什
- 一、对列表(list)进行排序推荐的排序方式是使用内建的sort()方法,速度最快而且属于稳定排序>>> a = [1,9
- 翻译自https://pytorch.org/docs/stable/torchvision/models.html主要讲解了torchvi
- 刚才好无聊,突然想起来之前做一个课表的点子,于是百度了起来。刚开始,我是这样想的:在写微信墙的时候,用到了urllib2【两行代码抓网页】,
- 前言如果说写代码最害怕什么,那无疑是Bug。而对于新手来说,刚刚接触编程,在享受写代码的成就感时,往往也会被各式各样的Bug弄得晕头转向。今
- python线程池ThreadPoolExecutor,传单个参数和多个参数这是线程池传单个参数的from concurrent.futur