图像坐标系是笛卡尔坐标系顺时针旋转90度。如下:
注意若是matplotlib表示的图片,点的坐标和CV的坐标是颠倒的,需要把x,y倒过来!!!!
eg:
(图为鱼眼镜头)
几种几何变换:
defination:
变换只是坐标发生变换,像素值是不改变的,即像素点的移动。
common geometric transformation:
平移
为方便运算,要按照笛卡尔坐标系来运算。用线代的矩阵运算表示。
上图中的第二个图片可见将图像向右下角移动,文件大小不变,只是空出部分的像素值要统一设置0或255。
移出的部分就看不到了。
第三幅图是扩展(放大)了画布,文件大小改变。
镜像
有水平镜像和垂直镜像两种。
旋转
旋转之后一般都会变大,因为怕部分图像跑出去
缩放
缩小(采样抽取)和放大(填充估计)
整数放大
放大倍数过大,会出现马赛克效应
拉伸
灰度级插值
找最近的像素点,重复其像素值。
1234每个点两两之间求灰度平均值,,横着的两个再拼平均值作为x,竖着的两个求平均值作为y,再带入上面公式
several instances:
declare:以下源码均来自于我的授课老师,出于重在掌握的目的,仅有部分改动(不搞形式主义),自己的部分理解在注释中,时间关系后续会放上自己的 manual program
Program1 缩放和平移
cv.resize()函数解析:
void resize(InputArray src, OutputArray dst,
Size dsize, double fx=0, double fy=0,
int interpolation=INTER_LINEAR )
参数说明:
-
src:输入图像
-
dst:输出图像,dst的数据类型与src相同.
-
dsize:这个参数是输出图像的尺寸,两种情况,如果该参数设置为0(None),api会自动计算
输出参数,否则按照输入尺寸 -
fx和fy是图像width方向和height方向的缩放比例。
fx:width方向的缩放比例,如果它是0,那么它就会按照(double)dsize.width/src.cols来计算;
fy:height方向的缩放比例,如果它是0,那么它就会按照(double)dsize.height/src.rows来计算; -
interpolation:插值方法.
在opencv中提供了5中插值方式:
INTER_NEAREST:最邻近插值
INTER_LINEAR:双线性插值,默认情况下使用该方式进行插值.
INTER_AREA:基于区域像素关系的一种重采样或者插值方式.该方法是图像抽取的首选方法,它可以产生更少的波纹,但是当图像放大时,它的效果与INTER_NEAREST效果相似.
INTER_CUBIC:4×4邻域双3次插值
INTER_LANCZOS4:8×8邻域兰索斯插值
使用技巧:
若要缩小图像,一般情况下最好用CV_INTER_AREA来插值,
而若要放大图像,一般情况下最好用CV_INTER_CUBIC(效率不高,慢,不推荐使用)或CV_INTER_LINEAR(效率较高,速度较快,推荐使用)。
zoom为缩放的意思
仿射变换函数cv.warpAffine()解析:
cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst
参数说明:
src - 输入图像。
M - 变换矩阵。
dsize - 输出图像的大小。
flags - 插值方法的组合(int 类型!)
borderMode - 边界像素模式(int 类型!)
borderValue - (重点!)边界填充值; 默认情况下,它为0。
仿射变换原理可refer to this article
本例中就是 = * +
# Author triple[:,None,None]
#!/usr/bin/python
# -*- coding:utf-8
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread("/home/image/Pictures/home.jpg")
cv.imshow('Original image ',img)
cv.waitKey(0)
#双线性插值
#.INTER_LINEAR is default,means double liner interpolation(n.)#插入,插值
#最临近插值
#.INTER_CUBIC is 4X4 neighbourhood interploration
#.INTER_AREA is turn small
imgtrans = cv.resize(img,None,fx=2,fy=2 ,interpolation=cv.INTER_CUBIC)#x和y方向均扩大两倍
row,col,channel = img.shape
print('row=',row,'col=',col)
cv.imshow('zoom in fx=2,fy=2 image',imgtrans)
imgtrans = cv.resize(img,None,fx=2,fy=1 ,interpolation=cv.INTER_CUBIC)#和笛卡尔坐标系一样
cv.imshow("zoom in fx=2 ,fy=1",imgtrans)
imgtrans = cv.resize(img,None,fx=1,fy=2 ,interpolation=cv.INTER_CUBIC)
cv.imshow("zoom in fx=1 ,fy=2",imgtrans)
imgtrans = cv.resize(src=img,dsize=None,fx=0.8,fy=0.7 ,interpolation=cv.INTER_AREA)
cv.imshow("zoom in fx=0.8 ,fy=0.7",imgtrans)
#define trans Martix
#m =[1,0,tx]
# [0,1,ty]
#is np.float32s
m = np.float32([[1,0,100],[0,1,50]])#变换矩阵
# warpAfiine() is block tans function
# 1st is original image ,2nd is tansmatrix ,3th is output image size
dst = cv.warpAffine(src=img,M=m,dsize=(col,row))#相反
print(dst.shape)
#observe pixel location
plt.imshow(dst)
plt.show()
cv.waitKey(0)
cv.imshow('Block trans image', dst)
cv.waitKey(0)
cv.destroyAllWindows()
运行结果:
只放一个matplotlib输出的平移图片,方便observe pixel points‘ location和坐标系样式(其他的太多就不放了,大同小异)
program2 mirror transformation
代码通俗易懂,就不再赘述了
# Author me
#!/usr/bin/python
# -*- coding:utf-8
# A simple function hist
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
image = cv.imread("/home/image/Pictures/lena512gray.jpg",1)
print(image.shape)
size = (image.shape)
print (size)
iUD = np.zeros(size,np.uint8)
iLR = np.zeros(size,np.uint8)
iCR = np.zeros(size,np.uint8)
h = size[0]
w = size[1]
t1 =cv.getTickCount()
for i in range(h):
for j in range(w):
iUD[h-1-i,j] = image[i,j] #I=M -i +1 ,J=i,上下翻转
iLR[i,w-1-j] = image[i,j] #I =i,J=N-j+1,左右翻转
iCR[h-1-i,w-1-j] = image[i,j] #I=M -i +1 ,J=N-j+1,上下左右皆反转
images = [image,iUD,iLR,iCR]
titles = ['1.original image','2.UP-DOWN iUD','3.Left-right iLR','4.Acorss iUP']
t2 = cv.getTickCount()
print( "trans time",(t2-t1)/cv.getTickFrequency())
for i in range(4):
plt.subplot(2,2,i+1),plt.imshow(images[i]),plt.xticks([]),plt.yticks([]),plt.title(titles[i])
plt.show()
运行结果:
program3 rotation
cv.getRotationMatrix2D()函数解析:
主要用于获得图像绕着 某一点的旋转矩阵 。
Mat getRotationMatrix2D(Point2f center, double angle, double scale)
参数说明:
Point2f center:表示旋转的中心点
double angle:表示旋转的角度
double scale:图像缩放因子
代码:
openCV配置的时候应该是多了依赖包,用cv.namedWindow()的时候会多出现一个黑框,怕麻烦我就不管了(手动滑稽)
可能这就是老师不用它的原因吧
# -*- coding:utf-8
import cv2 as cv
img = cv.imread("/home/image/Pictures/lena256.jpg")
rows,cols,channel = img.shape
#cv.namedWindow('Original image',cv.WINDOW_AUTOSIZE)
#cv.resizeWindow('Original image',640,480)
cv.imshow('Original image ',img)
# rotation image:getRotationMatrix2D function
trans= cv.getRotationMatrix2D((cols/2,rows/2),-20,0.6)#此时以原点为中心顺时针旋转20度,缩小为原来的1.6倍
#Affine transformation: 1st is orignal img ,2nd is rotation object ,3th is row/col
dst = cv.warpAffine(img,trans,(cols,rows))#原图,转换矩阵,输出尺寸(要颠倒)
cv.waitKey(0)
cv.imshow('Rotated image',dst)
cv.waitKey(0)
cv.destroyAllWindows()
运行结果:
program4 拉伸
仿射变换,又称仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。仿射变换需要一个M矩阵,但是由于仿射变换比较复杂,一般直接找很难找到这个矩阵,opencv提供了根据变换前后三个点的对应关系来自动求解M的函数,这个函数就是:
M=cv2.GetAffineTransform(src, dst)
参数说明:
src:原始图像中的三个点的坐标
dst:变换后的这三个点对应的坐标
M:根据三个对应点求出的仿射变换矩阵
然后再使用函数cv2.warpAffine()利用得到的M对原始图像进行变换即可
代码:
# -*- coding:utf-8
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread("/home/image/Pictures/lena256.jpg")
rows, cols, channel = img.shape
pts1 = np.float32([[50, 50], [200, 50], [50, 200]])
pts2 = np.float32([[10, 100], [200, 50], [100, 250]])
M = cv.getAffineTransform(pts1, pts2)
print(M)
dst = cv.warpAffine(img, M,(cols, rows))
plt.subplot(1,2,1), plt.imshow(img), plt.title('Input'),plt.xticks([]),plt.yticks([])
plt.subplot(122), plt.imshow(dst), plt.title('Output'),plt.xticks([]),plt.yticks([])
plt.show()
cv.destroyAllWindows()
运行结果:
one more instance(another function):
和上面那个差不多,refer to this article
代码:
# -*- coding:utf-8
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread("/home/image/Pictures/lena256.jpg")
pts1 = np.float32([[56, 65], [368, 52], [28, 387], [389, 390]])
pts2 = np.float32([[100, 50], [300, 0], [0, 300], [300, 300]])
M = cv.getPerspectiveTransform(pts1, pts2)
dst = cv.warpPerspective(img, M, (300, 300))
plt.subplot(121), plt.imshow(img), plt.title('Input')
plt.subplot(122), plt.imshow(dst), plt.title('Output')
plt.show()
运行结果: