日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

python皮同_Python OpenCV 图像的双线性插值算法,全网最细致的算法说明_橡皮擦,一个逗趣的互联网高级网虫-CSDN博客...

發(fā)布時間:2023/11/27 生活经验 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python皮同_Python OpenCV 图像的双线性插值算法,全网最细致的算法说明_橡皮擦,一个逗趣的互联网高级网虫-CSDN博客... 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原文作者:夢想橡皮擦

原文標題:Python OpenCV 圖像的雙線性插值算法,全網(wǎng)最細致的算法說明

發(fā)布時間:2021-02-17 20:55:32

Python OpenCV 365 天學習計劃,與橡皮擦一起進入圖像領域吧。本篇博客是這個系列的第 42 篇。

該系列文章導航參考:https://blog.csdn.net/hihell/category_10688961.html

基礎知識鋪墊

本篇博客實現(xiàn)雙線性插值算法的編寫,順便修改一下 上篇博客 最近鄰插值算法最后實現(xiàn)與 OpenCV 提供的內(nèi)置參數(shù)不一致問題。

還有一個問題,是執(zhí)行速度問題,該問題一并在學習雙線性插值算法之后解決。

圖像的雙線性插值算法

雙線性內(nèi)插值算法是一種比較好的圖像縮放算法,它利用了源圖像中虛擬點四周四個真實存在的像素值,依據(jù)權(quán)重來決定目標圖中的一個像素值。

先摘抄一些原理性的描述:

對于一個目標像素,通過反向變換可以得到源圖像的虛擬坐標,大概率是浮點坐標,格式為(i+u,j+v),其中 i、j 為整數(shù)部分,u、v 為小數(shù)部分,取值 [0,1),這時在源圖像中 (i+u,j+v) 可以由周邊的四個像素坐標 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1) 計算獲得,也就是存在公式:

f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)

這一步的變換被省略了很多內(nèi)容,橡皮擦也是查閱了很多資料,接下來為你補充上。

先畫一張輔助理解的圖~

首先在 X 方向上進行兩次線性插值計算,然后在 Y 方向上進行一次插值計算。

在計算之前,又要補充知識了,叫做線性插值,已知數(shù)據(jù)

(

x

0

,

y

0

)

(x_0,y_0)

(x0?,y0?) 和

(

x

1

,

y

1

)

(x_1,y_1)

(x1?,y1?),要計算

[

x

0

,

x

1

]

[x_0,x_1]

[x0?,x1?] 區(qū)間內(nèi)某一位置 x 在直線上的 y 值,公式如下:

y

?

y

0

x

?

x

0

=

y

1

?

y

0

x

1

?

x

0

\cfrac{y-y_0}{x-x_0}=\cfrac{y_1-y_0}{x_1-x_0}

x?x0?y?y0??=x1??x0?y1??y0??

公式進行變形得到:

y

=

x

1

?

x

x

1

?

x

0

y

0

+

x

?

x

0

x

1

?

x

0

y

1

y=\cfrac{x_1-x}{x_1-x_0}y_0+\cfrac{x-x_0}{x_1-x_0}y_1

y=x1??x0?x1??x?y0?+x1??x0?x?x0??y1?

變換之后大概等用

x

0

x_0

x0? 和

x

1

x_1

x1? 的距離作為一個權(quán)重,用于

y

0

y_0

y0? 和

y

1

y_1

y1? 的加權(quán),雙線性插值就是在兩個方向上做線性插值。

繼續(xù)看上圖,在點 1 與點 2 區(qū)間內(nèi)尋找一點,依據(jù)公式可得:

f

(

1

)

x

2

?

x

x

2

?

x

1

f

(

1

)

+

x

?

x

1

x

2

?

x

1

f

(

2

)

f(插值點1)\approx\cfrac{x_2-x}{x_2-x_1}f(點1)+\cfrac{x-x_1}{x_2-x_1}f(點2)

f(插值點1)≈x2??x1?x2??x?f(點1)+x2??x1?x?x1??f(點2) 其中插值點 1 =

(

x

,

y

1

)

(x,y_1)

(x,y1?)

同樣的算法獲取插值點 2:

f

(

2

)

x

2

?

x

x

2

?

x

1

f

(

3

)

+

x

?

x

1

x

2

?

x

1

f

(

4

)

f(插值點2)\approx\cfrac{x_2-x}{x_2-x_1}f(點3)+\cfrac{x-x_1}{x_2-x_1}f(點4)

f(插值點2)≈x2??x1?x2??x?f(點3)+x2??x1?x?x1??f(點4) 其中插值點 2 =

(

x

,

y

2

)

(x,y_2)

(x,y2?)

接下來在 Y 方向進行線性插值計算:

f

(

P

)

y

2

?

y

y

2

?

y

1

f

(

1

)

+

y

?

y

1

y

2

?

y

1

f

(

2

)

f(P)\approx\cfrac{y_2-y}{y_2-y_1}f(插值點1)+\cfrac{y-y_1}{y_2-y_1}f(插值點2)

f(P)≈y2??y1?y2??y?f(插值點1)+y2??y1?y?y1??f(插值點2)

將上述式子展開,就可以得到最后的結(jié)果了,這個沒多少難度,寫的時候與看的時候都仔細點就好:

f

(

x

,

y

)

f

(

1

)

(

x

2

?

x

)

(

y

2

?

y

)

(

x

2

?

x

1

)

(

y

2

?

y

1

)

+

f

(

2

)

(

x

?

x

1

)

(

y

2

?

y

)

(

x

2

?

x

1

)

(

y

2

?

y

1

)

+

f

(

3

)

(

x

2

?

x

)

(

y

?

y

1

)

(

x

2

?

x

1

)

(

y

2

?

y

1

)

+

f

(

4

)

(

x

?

x

1

)

(

y

?

y

1

)

(

x

2

?

x

1

)

(

y

2

?

y

1

)

f(x,y)\approx\cfrac{f(點1)(x_2-x)(y_2-y)}{(x_2-x_1)(y_2-y_1)}+\cfrac{f(點2)(x-x_1)(y_2-y)}{(x_2-x_1)(y_2-y_1)}+\cfrac{f(點3)(x_2-x)(y-y_1)}{(x_2-x_1)(y_2-y_1)}+\cfrac{f(點4)(x-x_1)(y-y_1)}{(x_2-x_1)(y_2-y_1)}

f(x,y)≈(x2??x1?)(y2??y1?)f(點1)(x2??x)(y2??y)?+(x2??x1?)(y2??y1?)f(點2)(x?x1?)(y2??y)?+(x2??x1?)(y2??y1?)f(點3)(x2??x)(y?y1?)?+(x2??x1?)(y2??y1?)f(點4)(x?x1?)(y?y1?)?

該式子可以進一步的簡化,因為兩個相鄰點插值是 1,所以簡化如下:

f

(

x

,

y

)

f

(

1

)

(

x

2

?

x

)

(

y

2

?

y

)

+

f

(

2

)

(

x

?

x

1

)

(

y

2

?

y

)

+

f

(

3

)

(

x

2

?

x

)

(

y

?

y

1

)

+

f

(

4

)

(

x

?

x

1

)

(

y

?

y

1

)

f(x,y)\approx f(點1)(x_2-x)(y_2-y)+f(點2)(x-x_1)(y_2-y)+f(點3)(x_2-x)(y-y_1)+f(點4)(x-x_1)(y-y_1)

f(x,y)≈f(點1)(x2??x)(y2??y)+f(點2)(x?x1?)(y2??y)+f(點3)(x2??x)(y?y1?)+f(點4)(x?x1?)(y?y1?)

在將所有點的坐標帶入

f

(

x

,

y

)

f

(

x

1

,

y

1

)

(

x

2

?

x

)

(

y

2

?

y

)

+

f

(

x

2

,

y

1

)

(

x

?

x

1

)

(

y

2

?

y

)

+

f

(

x

1

,

y

2

)

(

x

2

?

x

)

(

y

?

y

1

)

+

f

(

x

2

,

y

2

)

(

x

?

x

1

)

(

y

?

y

1

)

f(x,y)\approx f(x_1,y_1)(x_2-x)(y_2-y)+f(x_2,y_1)(x-x_1)(y_2-y)+f(x_1,y_2)(x_2-x)(y-y_1)+f(x_2,y_2)(x-x_1)(y-y_1)

f(x,y)≈f(x1?,y1?)(x2??x)(y2??y)+f(x2?,y1?)(x?x1?)(y2??y)+f(x1?,y2?)(x2??x)(y?y1?)+f(x2?,y2?)(x?x1?)(y?y1?)

將 (x,y) 替換成最開始的寫法 (i+u,j+v) ,其他的坐標分別為 點 1~點 4 分別為:(i,j)、(i+1,j)、(i,j+1)、(i+1,j+1) ,帶入上述公式,變化結(jié)果如所示:

f

(

i

+

u

,

j

+

v

)

f

(

i

,

j

)

(

i

+

1

?

(

i

+

u

)

)

(

j

+

1

?

(

j

+

v

)

)

+

f

(

i

+

1

,

j

)

(

i

+

u

?

i

)

(

j

+

1

?

(

j

+

v

)

)

+

f

(

i

,

j

+

1

)

(

i

+

1

?

(

i

+

u

)

)

(

j

+

v

?

j

)

+

f

(

i

+

1

,

j

+

1

)

(

i

+

u

?

i

)

(

j

+

v

?

j

)

f(i+u,j+v)\approx f(i,j)(i+1-(i+u))(j+1-(j+v))+f(i+1,j)(i+u-i)(j+1-(j+v))+f(i,j+1)(i+1-(i+u))(j+v-j)+f(i+1,j+1)(i+u-i)(j+v-j)

f(i+u,j+v)≈f(i,j)(i+1?(i+u))(j+1?(j+v))+f(i+1,j)(i+u?i)(j+1?(j+v))+f(i,j+1)(i+1?(i+u))(j+v?j)+f(i+1,j+1)(i+u?i)(j+v?j)

別暈,估計這是全網(wǎng)最清晰的轉(zhuǎn)換方式了:

f

(

i

+

u

,

j

+

v

)

f

(

i

,

j

)

(

1

?

u

)

(

1

?

v

)

+

f

(

i

+

1

,

j

)

u

(

1

?

v

)

+

f

(

i

,

j

+

1

)

(

1

?

u

)

v

+

f

(

i

+

1

,

j

+

1

)

u

v

f(i+u,j+v)\approx f(i,j)(1-u)(1-v)+f(i+1,j)u(1-v)+f(i,j+1)(1-u)v+f(i+1,j+1)uv

f(i+u,j+v)≈f(i,j)(1?u)(1?v)+f(i+1,j)u(1?v)+f(i,j+1)(1?u)v+f(i+1,j+1)uv

到這里就與本篇博客最開始的公式呼應上了。

所以通過目標圖像反推出來的一點,可以通過四個點的坐標進行計算,每個坐標前面的叫做權(quán)重,假設存在這樣一個像素坐標為 (1,1),反推在源圖中得到的坐標是 (0.75,0.75),由于圖像中不可能存在浮點坐標,所以獲取周圍四個坐標分別是 (0,0)(0,1)(1,0)(1,1),由于 (0.75,0.75) 距離 (1,1) 最近,所以 (1,1) 點對該像素顏色作用最大,相應的 (1,1) 點對應的點是 f(i+1,i+1) ,該變量前面的系數(shù)權(quán)重為 0.75*0.75 ,結(jié)果最大,這個說明是通過真實的數(shù)據(jù)去說明。

拿到計算方式之后,就可以通過代碼實現(xiàn)雙線性插值算法了。

先通過內(nèi)置的縮放函數(shù),測試一下運行時間:

if __name__ == '__main__':

src = cv2.imread('./t.png')

start = time.time()

dst = cv2.resize(src, (600, 600))

print('內(nèi)置函數(shù)運行時間:%f' % (time.time() - start))

cv2.imshow('src', src)

cv2.imshow('dst', dst)

cv2.waitKey()

得到的時間為 內(nèi)置函數(shù)運行時間:0.002000 ,非常快。

接下來就是自寫函數(shù)驗證了,代碼的說明我寫在了注釋中,你可以研究一下,注意公式的運用

import cv2

import numpy as np

import time

def resize_demo(src, new_size):

# 目標圖像寬高

dst_h, dst_w = new_size

# 源圖像寬高

src_h, src_w = src.shape[:2]

# 如果圖像大小一致,直接復制返回即可

if src_h == dst_h and src_w == dst_w:

return src.copy()

# 計算縮放比例

scale_x = float(src_w) / dst_w

scale_y = float(src_h) / dst_h

# 遍歷目標圖像

dst = np.zeros((dst_h, dst_w, 3), dtype=np.uint8)

# return dst

# 對通道進行循環(huán)

# for n in range(3):

# 對 height 循環(huán)

for dst_y in range(dst_h):

# 對 width 循環(huán)

for dst_x in range(dst_w):

# 目標在源上的坐標

src_x = dst_x * scale_x

src_y = dst_y * scale_y

# 計算在源圖上 4 個近鄰點的位置

# i,j

i = int(np.floor(src_x))

j = int(np.floor(src_y))

u = src_x-i

v = src_y-j

if j == src_h-1:

j = src_h-2

if i == src_w-1:

i = src_h-2

# f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)

dst[dst_y, dst_x] = (1-u)*(1-v)*src[j, i]+u*(1-v) * \

src[j+1, i] + (1-u)*v*src[j, i+1]+u*v*src[j+1, i+1]

# dst[dst_y, dst_x] = 0.25*src[j, i]+0.25 * \

# src[j+1, i] + 0.25*src[j, i+1]+0.25*src[j+1, i+1]

# dst[dst_y,dst_x,n] = 255

return dst

if __name__ == '__main__':

src = cv2.imread('./t.png')

start = time.time()

dst = resize_demo(src, (500, 600))

print('自寫函數(shù)運行時間:%f' % (time.time() - start))

cv2.imshow('src', src)

cv2.imshow('dst', dst)

cv2.waitKey()

代碼運行消耗了 2s 多,確實比較費時間。

橡皮擦的小節(jié)

希望今天的 1 個小時你有所收獲,我們下篇博客見~

相關閱讀

技術專欄

今天是持續(xù)寫作的第 84 / 100 天。

如果你想跟博主建立親密關系,可以關注同名公眾號 夢想橡皮擦,近距離接觸一個逗趣的互聯(lián)網(wǎng)高級網(wǎng)蟲。

博主 ID:夢想橡皮擦,希望大家點贊、評論、收藏。

Post Views:

6

總結(jié)

以上是生活随笔為你收集整理的python皮同_Python OpenCV 图像的双线性插值算法,全网最细致的算法说明_橡皮擦,一个逗趣的互联网高级网虫-CSDN博客...的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。