Geometric Transformation(几何变换)

图像坐标系是笛卡尔坐标系顺时针旋转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

本例中就是\begin{bmatrix} x\\ y\end{bmatrix} =\begin{bmatrix} 1 &0 \\ 0& 1\end{bmatrix} * \begin{bmatrix} x_{0}\\ y_{0}\end{bmatrix}+\begin{bmatrix} 50\\ 100 \end{bmatrix}

# 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()

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深海鱼肝油ya

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值