图像几何变换
绘图
目录
目标:
1.实现旋转、平移和缩放图片
2.OpenCV函数:cv2.resize(),cv2.flip(),cv2.warpAffine()
3.绘制各种几何形状、添加文字
4.OpenCV函数:cv2.line(),cv2.circle(),cv2.rectangle(),cv2.ellipse(),cv2.putText()
图像几何变换
旋转、平移、缩放和翻转图片
缩放
缩放就是调整图片的大小,使用cv2.resize()函数实现缩放
可按照比例缩放,也可按照指定大小缩放:
import cv2
img = cv2.imread('drawing.jpg')
# 按照指定的宽度、高度缩放图片
res = cv2.resize(img, (132, 150))
# 按照比例缩放,如x,y轴均放大一倍
res2 = cv2.resize(img, None, fx=2, fy=2, interpolation=cv2.INTER_LINEAR)
cv2.imshow('shrink', res), cv2.imshow('zoom', res2)
cv2.waitKey(0)
可指定缩放方法interpolation(插值方法),默认是INTER_LINEAR
翻转
镜像翻转图片,可以用cv2.flip()
dst = cv2.flip(img, 1)
其中,参数2 = 0:垂直翻转(沿x轴),
参数2 > 0: 水平翻转(沿y轴),
参数2 < 0: 水平垂直翻转。
平移
要平移图片,我们需要定义下面这样一个矩阵,tx,ty是向x和y方向平移的距离:
平移是用仿射变换函数cv2.warpAffine()实现的:
# 平移图片
import numpy as np
rows, cols = img.shape[:2]
# 定义平移矩阵,需要是numpy的float32类型
# x轴平移100,y轴平移50
M = np.float32([[1, 0, 100], [0, 1, 50]])
# 用仿射变换实现平移
dst = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('shift', dst)
cv2.waitKey(0)
旋转
旋转同平移一样,也是用仿射变换实现的,因此也需要定义一个变换矩阵。
OpenCV直接提供了cv2.getRotationMatrix2D()函数来生成这个矩阵,该函数有三个参数:
参数1:图片的旋转中心
参数2:旋转角度(正:逆时针,负:顺时针)
参数3:缩放比例,0.5表示缩小一半
# 45°旋转图片并缩小一半
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 45, 0.5)
dst = cv2.warpAffine(img, M, (cols, rows))
cv2.imshow('rotation', dst)
cv2.waitKey(0)
绘图
学习画线、圆和矩形等多种几何形状,给图片添加文字
绘制形状的函数有一些共同参数,提前在此说明一下:
img:要绘制形状的图片
color:绘制的颜色
彩色图,传入BGR的一组值,如蓝色就是(255,0,0)
灰度图,传入一个灰度值就行
thickness:线宽,默认为1;对于矩形/圆之类的封闭形状而言,传入-1表示填充形状
需要导入的模块和显示图片的通用代码:
import cv2
import numpy as np
import matplotlib.pyplot as plt
cv2.imshow('img', img)
cv2.waitKey(0)
画线
画直线只需指定起点和终点的坐标就行:
# 创建一副黑色的图片
img = np.zeros((512, 512, 3), np.uint8)
# 画一条线宽为5的蓝色直线,参数2:起点,参数3:终点
cv2.line(img, (0, 0), (512, 512), (255, 0, 0), 5)
注:所有绘图函数均会直接影响原图片,这点要注意。
矩形
画矩形需要知道左上角和右下角的坐标:
# 画一个绿色边框的矩形,参数2:左上角坐标,参数3:右下角坐标
cv2.rectangle(img, (384, 0), (510, 128), (0, 255, 0), 3)
圆
画圆需要指定圆心和半径,注意下面例子中线宽=-1代表填充:
# 画一个填充红色的圆,参数2:圆心坐标,参数3:半径
cv2.circle(img, (447, 63), 63, (0, 0, 255), -1)
椭圆
画椭圆需要的参数比较多,请对照后面的代码理解这几个参数:
参数2:椭圆中心(x,y)
参数3:x/y轴的长度
参数4:angle---椭圆的旋转角度
参数5:startAngle---椭圆的起始角度
参数6:endAngle---椭圆的结束角度
注:OpenCV中原点在左上角,所以这里的角度是以顺时针方向计算的。
# 在图中心画一个填充的半圆
cv2.ellipse(img, (256, 256), (100, 50), 0, 0, 180, (255, 0, 0), -1)
多边形
画多边形需要指定一系列多边形的顶点坐标,相当于从第一个点到第二个点画直线,再从第二个点到第三个点画直线....
OpenCV中需要先将多边形的顶点坐标需要变成顶点数×1×2维的矩阵,再来绘制:
# 定义四个顶点坐标
pts = np.array([[10, 5], [50, 10], [70, 20], [20, 30]], np.int32)
# 顶点个数:4,矩阵变成4*1*2维
pts = pts.reshape((-1, 1, 2))
cv2.polylines(img, [pts], True, (0, 255, 255))
cv2.polylines()的参数3如果是False的话,多边形就不闭合
注:如果需要绘制多条直线,使用cv2.polylines()要比cv2.line()高效很多,例如:
# 使用cv2.polylines()画多条直线
line1 = np.array([[100, 20], [300, 20]], np.int32).reshape((-1, 1, 2))
line2 = np.array([[100, 60], [300, 60]], np.int32).reshape((-1, 1, 2))
line3 = np.array([[100, 100], [300, 100]], np.int32).reshape((-1, 1, 2))
cv2.polylines(img, [line1, line2, line3], True, (0, 255, 255))
添加文字
使用cv2.putText()添加文字,它的参数也比较多,同样要对照后面的代码理解这几个参数:
参数2:要添加的文本
参数3:文字的起始坐标(左下角为起点)
参数4:字体
参数5:文字大小(缩放比例)
# 添加文字
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, 'ex2tron', (10, 500), font,
4, (255, 255, 255), 2, lineType=cv2.LINE_AA)
字体可参考HersheyFonts
另外,这里有个线型lineType参数,LINE_AA表示抗锯齿线型,具体可见LineTypes
例子
上述成品如图
小结
1.cv2.resize() 缩放图片,可按指定大小缩放,也可按比例缩放
2.cv2.flip()翻转图片,可以指定水平/垂直/水平垂直翻转三种方式
3.平移/旋转是靠仿射变换cv2.warpAffine()实现的
4.cv2.line()画直线,cv2.circle()画圆,cv2.rectangle()画矩形,cv2.ellipse()画椭圆,cv2.polylines()画多边形,cv2.putText()添加文字
5.画多条直线时,cv2.polylines()要比cv2.line()高效很多
练习
1.能用已学的绘图功能画出OpenCV的logo吗?(提示:椭圆和圆)
import cv2
import numpy as np
img = np.zeros((200, 200, 3), np.uint8)
# 画OpenCV的logo
# 1.先画一个0°到300°的圆
# 2.再在中心画一个跟背景颜色一样的小圆
# 3.重复前两部,并且旋转一定的角度即可
# 画绿色的部分
cv2.ellipse(img, (43, 125), (45, 45), 0, 0, 300,
(0, 255, 0), -1, lineType=cv2.LINE_AA)
cv2.circle(img, (43, 125), 15, (0, 0, 0), -1, lineType=cv2.LINE_AA)
# 画红色的部分
cv2.ellipse(img, (90, 40), (45, 45), 120, 0, 300,
(0, 0, 255), -1, lineType=cv2.LINE_AA)
cv2.circle(img, (90, 40), 15, (0, 0, 0), -1, lineType=cv2.LINE_AA)
# 画蓝色的部分
cv2.ellipse(img, (137, 125), (45, 45), -60, 0, 300,
(255, 0, 0), -1, lineType=cv2.LINE_AA)
cv2.circle(img, (137, 125), 15, (0, 0, 0), -1, lineType=cv2.LINE_AA)
cv2.imshow('img', img)
cv2.waitKey(0)
执行如图