【OpenCV 】插值的方法原理,图片缩放,矫正,边界填充

图像旋转 缩放

计算机中的图像是以数组的方式储存,每个位置储存了像素点的像素值。对图像进行旋转缩放,就是对数组进行操作,乘以对应的矩阵,进行空间变换,而矩阵的行列式的值,就是缩放的倍数。

进行缩放旋转操作时,会产生像素点的变化,空间和数量的变化,所以需要对变化的图片进行插值

插值是通过变化后图像的像素点的坐标,通过缩放倍数,找到原图对应的像素点坐标,通过权重得到新的像素值

其中目标像素点与原图像的像素点的对应公式如下所示:
s r c X = d s t X ∗ s r c W i d t h d s t W i d t h s r c X=d s t X*{\frac{s r c W i d t h}{d s t W i d t h}} srcX=dstXdstWidthsrcWidth

s r c Y = d s t Y ∗ s r c H e i g h t d s t H e i g h t s r c Y=d s t Y*{\frac{s r c H e i g h t}{d s t H e i g h t}} srcY=dstYdstHeightsrcHeight

src是原图,dst是变换后的图像,通过缩放倍数,得到对应原图的x和y的坐标,是个小数。

  • 最近零插值INTER_NEAREST

    • 通过对得到的坐标向下取整,直接获得原图对应位置的像素值
  • 双线性插值INTER_LINEAR

    • 根据得到的小数坐标重新取像素值,权重取决于和周围点的距离,越近权重越高

    • 小数的坐标对应原图周围四个像素点,对两个方向分别根据距离加权求和,之后再对的到的两个值进行加权求和

    • 把p分为到两个点R1 R2 分别通过Q12Q22 和 Q11Q21根据距离获得像素值,再根据距离由R1R2得到p的像素值

    • 在这里插入图片描述

在这里插入图片描述

  • f ( R 1 ) ≈ x 2 − x x 2 − x 1 f ( Q 11 ) + x − x 1 x 2 − x 1 f ( Q 21 ) f(R_{1})\approx\frac{x_{2}-x}{x_{2}-x_{1}}f(Q_{11})+\frac{x-x_{1}}{x_{2}-x_{1}}f(Q_{21}) f(R1)x2x1x2xf(Q11)+x2x1xx1f(Q21)

    f ( R 2 ) ≈ x 2 − x x 2 − x 1 f ( Q 12 ) + x − x 1 x 2 − x 1 f ( Q 22 ) f(R_{2})\approx\frac{x_{2}-x}{x_{2}-x_{1}}f(Q_{12})+\frac{x-x_{1}}{x_{2}-x_{1}}f(Q_{22}) f(R2)x2x1x2xf(Q12)+x2x1xx1f(Q22)

    f ( P ) ≈ y 2 − y y 2 − y 1 f ( R 1 ) + y − y 1 y 2 − y 1 f ( R 2 ) f(P)\approx{\frac{y_{2}-y}{y_{2}-y_{1}}}f(R_{1})+{\frac{y-y_{1}}{y_{2}-y_{1}}}f(R_{2}) f(P)y2y1y2yf(R1)+y2y1yy1f(R2)

  • v

  • 像素区域插值INTER_AREA

    • 缩小图像,变成均值滤波
    • 放大图像
      • 整数倍是最近邻插值
      • 否则就是双线性插值
  • 双三次插值INTER_CUBIC

    • 使用原图中的16像素点进行加权求像素值

    • 像素点的权重通过公式分别求出水平方向和垂直方向的权重,再相乘

    • BiCubic函数

      在这里插入图片描述

    • a为-0.5或-0.75

  • Lanczos插值INTER_LANCZOS4

    • 和双三次插值相似,但是使用了64个像素点

    • 使用新的权重公式

    • 在这里插入图片描述

    • a = 2是适用于缩小,a=3适用放大

import cv2
import numpy

nut = cv2.imread('./media/nut.png')
w = nut.shape[0]
h = nut.shape[1]

mat = cv2.getRotationMatrix2D((0,0),0,2)
nut1 = cv2.warpAffine(nut,mat,(h*2,w*2),flags=cv2.INTER_LINEAR)
nut2 = cv2.warpAffine(nut,mat,(h*2,w*2),flags=cv2.INTER_CUBIC)
nut3 = cv2.warpAffine(nut,mat,(h*2,w*2),flags=cv2.INTER_LANCZOS4)
nut4 = cv2.warpAffine(nut,mat,(h*2,w*2),flags=cv2.INTER_NEAREST)

cv2.imshow('nut1',nut1)
cv2.imshow('nut2',nut2)
cv2.imshow('nut3',nut3)
cv2.imshow('nut4',nut4)
cv2.imshow('nut',nut)
cv2.waitKey(0)

在这里插入图片描述

边界填充

import cv2
import numpy as np

# 边界复制  BORDER_REPLICATE  把边界的像素值作为边缘的填充

# 边界反射 BORDER_REFLECT  以边界为对称线反转过去作为边缘填充 

# 边界反射101 BORDER_REFLECT_101  边界放射不同之处在于 不把边界作为对称的部分 

# 边界常数 BORDER_CONSTANT  指定常数 以常数填充

# 边界包裹 BORDER_WRAP 平铺

img = cv2.imread('./media/nut.png')
shape = img.shape
m = cv2.getRotationMatrix2D((shape[0]//2,shape[1]//2),45,0.25)  

img2 = cv2.warpAffine(img,m,(shape[1],shape[0]),flags=cv2.INTER_LINEAR,borderMode=cv2.BORDER_REPLICATE)  

img3 = cv2.warpAffine(img,m,(shape[1],shape[0]),cv2.INTER_AREA,borderMode=cv2.BORDER_REFLECT)  

img4 = cv2.warpAffine(img,m,(shape[1],shape[0]),cv2.INTER_CUBIC,borderMode=cv2.BORDER_REFLECT_101)  

img5 = cv2.warpAffine(img,m,(shape[1],shape[0]),cv2.INTER_LANCZOS4,borderMode=cv2.BORDER_CONSTANT,borderValue=127)  

img6 = cv2.warpAffine(img,m,(shape[1],shape[0]),cv2.INTER_LANCZOS4,borderMode=cv2.BORDER_WRAP)  


cv2.imshow('img',img)
cv2.imshow('img2',img2)
cv2.imshow('img3',img3)
cv2.imshow('img4',img4)
cv2.imshow('img5',img5)
cv2.imshow('img6',img6)
cv2.waitKey(0)

在这里插入图片描述

图片翻转

import cv2
import numpy as np

img = cv2.imread('./media/nut.png')
img1 = img[::-1] # 垂直翻转
img2 = cv2.flip(img,0) # 0 垂直翻转 
img3 = cv2.flip(img,1) # 大于0 水平翻转
img4 = cv2.flip(img,-1)  # 小于0 水平垂直翻转
cv2.imshow('img',img)
cv2.imshow('img1',img1)
cv2.imshow('img2',img2)
cv2.imshow('img3',img3)
cv2.imshow('img4',img4)
cv2.waitKey(0)

在这里插入图片描述

图片缩放

import cv2
import numpy as np

img1 = cv2.imread('./media/shapan.jpg')
img2 = cv2.resize(img1,dsize=None,fx=0.25,fy=0.25,interpolation=cv2.INTER_LINEAR)
# x方向缩放  y方向缩放 插值方式
cv2.imshow('img1',img1)
cv2.imshow('img2',img2)
# cv2.imwrite('./media/shapan.jpg',img2)
cv2.waitKey(0)

图片矫正

import cv2
import numpy as np
img = cv2.imread('./media/liner_road.png')
w,h,_ = img.shape

potion = [
    [415,50],
    [506,50],
    [60,560],
    [872,560]
]
new_p = np.float32([
    [0,0],
    [h,0],
    [0,w],
    [h,w]
])
p = np.float32(potion)

# cv2.line(img,p[0].astype(np.int64).tolist(),p[1].astype(np.int64).tolist(),(0,0,255),2,cv2.LINE_AA)
# cv2.line(img,p[1].astype(np.int64).tolist(),p[3].astype(np.int64).tolist(),(0,0,255),2,cv2.LINE_AA)
# cv2.line(img,p[3].astype(np.int64).tolist(),p[2].astype(np.int64).tolist(),(0,0,255),2,cv2.LINE_AA)
# cv2.line(img,p[2].astype(np.int64).tolist(),p[0].astype(np.int64).tolist(),(0,0,255),2,cv2.LINE_AA)
mat = cv2.getPerspectiveTransform(p,new_p)
img2 = cv2.warpPerspective(img,mat,(h,w))

cv2.imshow('img',img)
cv2.imshow('img2',img2)
cv2.waitKey(0)

在这里插入图片描述

在这里插入图片描述

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值