【数字图像处理】图像内插“双线性内插法 Bilinear interpolation”代码演示(以像素中心点确定像素位置)(图像放大缩小)具有低通滤波性质,使高频分量受损,图像轮廓可能会有一点模糊
文章目錄
- 原理
- 代碼
- 開了個(gè)jit加速(沒(méi)有提高太多)
- 開numexpr加速
- 總結(jié)
- 直接調(diào)用opencv庫(kù)(不知為啥那么快)
原理
雙線性內(nèi)插法是使用目標(biāo)點(diǎn)四周最近的四個(gè)點(diǎn),沿距目標(biāo)點(diǎn)x方向、y方向的權(quán)重關(guān)系,去分配給目標(biāo)點(diǎn)顏色值
如圖,P點(diǎn)是目標(biāo)點(diǎn),Q1、Q2、Q3、Q4是目標(biāo)點(diǎn)周圍的四個(gè)點(diǎn),先分別對(duì)Q1、Q2和Q3、Q4沿x方向進(jìn)行內(nèi)插,得到R1、R2兩個(gè)點(diǎn),再對(duì)R1、R2沿y方向進(jìn)行內(nèi)插,得到目標(biāo)點(diǎn)P
計(jì)算公式如下
注意:上面點(diǎn)p(x,y)里的x為換算到原圖的(pos_x - 1),y為換算到原圖后的(pos_y - 1)
我怎么想了一下,以像素右下角貌似不對(duì),應(yīng)該以像素中心點(diǎn)確定位置!!!
距離應(yīng)該以絕對(duì)值來(lái)表示的,另外,以先計(jì)算四個(gè)點(diǎn)的方法確實(shí)好使,減少判斷(先計(jì)算點(diǎn),再判斷點(diǎn)是否重合)
具體以正式運(yùn)行的代碼為準(zhǔn)
代碼
開了個(gè)jit加速(沒(méi)有提高太多)
# -*- coding: utf-8 -*- """ @File : 雙線性內(nèi)插法(續(xù)).py @Time : 2020/6/27 21:05 @Author : Dontla @Email : sxana@qq.com @Software: PyCharm """ import cv2 as cv import numpy as np import numexpr as ne from numba import jit@jit(nopython=True) # # Set "nopython" mode for best performance, equivalent to @njit def BI(img, resolution):srcH, srcW, _ = img.shapedstH, dstW = resolution# img_ = np.zeros((dstH, dstW, 3), dtype=np.uint8)img_ = np.zeros((dstH, dstW, 3), dtype=np.uint8)# 列外層,行內(nèi)層for y in range(dstH):for x in range(dstW):print(y, x)pos_y = (y + 0.5) / dstH * srcH # 比較的時(shí)候要以像素實(shí)際的位置(像素四方塊中心點(diǎn)),不能以像素下標(biāo)pos_x = (x + 0.5) / dstW * srcW # 比較的時(shí)候要以像素實(shí)際的位置(像素四方塊中心點(diǎn)),不能以像素下標(biāo)if pos_y <= 0.5 or pos_y >= srcH - 0.5: # 上區(qū)或下區(qū)# 先判斷是上區(qū)還是下區(qū)if pos_y <= 0.5: # 上區(qū)y_lim_index = 0else: # 下區(qū)y_lim_index = srcH - 1if pos_x <= 0.5: # 左上區(qū)或左下區(qū)img_[y, x] = img[y_lim_index, 0]elif pos_x >= srcW - 0.5: # 右上區(qū)或右下區(qū)img_[y, x] = img[y_lim_index, srcW - 1]else: # 中上區(qū)或中下區(qū)(需要判斷)if pos_x - int(pos_x) == 0.5: # 剛好與像素點(diǎn)重合# x_min_pos = x_max_pos = pos_xx_min_index = x_max_index = int(pos_x - 0.5)img_[y, x] = img[0, int((x_min_index + x_max_index) / 2)]else: # 與像素點(diǎn)不重合if pos_x - int(pos_x) < 0.5: # 左距大于等于右距x_min_pos = int(pos_x) - 0.5x_max_pos = int(pos_x) + 0.5else: # 左距小于右距x_min_pos = int(pos_x) + 0.5x_max_pos = int(pos_x) + 1.5x_min_index = int(x_min_pos - 0.5)x_max_index = int(x_max_pos - 0.5)fq1 = img[y_lim_index, x_min_index]fq2 = img[y_lim_index, x_max_index]img_[y, x] = (fq1 * (x_max_pos - pos_x) + fq2 * (pos_x - x_min_pos)) / (x_max_pos - x_min_pos)else: # 中區(qū)(y向)if pos_x <= 0.5 or pos_x >= srcW - 0.5: # 左中區(qū)或右中區(qū)if pos_x <= 0.5:x_lim_index = 0else:x_lim_index = srcW - 1if pos_y - int(pos_y) == 0.5: # 剛好與像素點(diǎn)重合y_min_index = y_max_index = int(pos_y - 0.5)img_[y, x] = img[0, int((y_min_index + y_max_index) / 2)]else: # 與像素點(diǎn)不重合if pos_y - int(pos_y) < 0.5: # 上距大于等于下距y_min_pos = int(pos_y) - 0.5y_max_pos = int(pos_y) + 0.5else: # 左距小于右距y_min_pos = int(pos_y) + 0.5y_max_pos = int(pos_y) + 1.5y_min_index = int(y_min_pos - 0.5)y_max_index = int(y_max_pos - 0.5)fq1 = img[y_min_index, x_lim_index]fq3 = img[y_max_index, x_lim_index]img_[y, x] = (fq1 * (y_max_pos - pos_y) + fq3 * (pos_y - y_min_pos)) / (y_max_pos - y_min_pos)else: # 正中區(qū)if pos_x - int(pos_x) == 0.5: # x方向點(diǎn)剛好與像素點(diǎn)重合x_min_index = x_max_index = int(pos_x - 0.5)if pos_y - int(pos_y) == 0.5: # y方向點(diǎn)剛好與像素點(diǎn)重合y_min_index = y_max_index = int(pos_y - 0.5)img_[y, x] = img[int((y_min_index + y_max_index) / 2), int((x_min_index + x_max_index) / 2)]else: # y方向點(diǎn)與像素點(diǎn)不重合if pos_y - int(pos_y) < 0.5: # 上距大于等于下距y_min_pos = int(pos_y) - 0.5y_max_pos = int(pos_y) + 0.5else: # 左距小于右距y_min_pos = int(pos_y) + 0.5y_max_pos = int(pos_y) + 1.5y_min_index = int(y_min_pos - 0.5)y_max_index = int(y_max_pos - 0.5)fq1 = img[y_min_index, int((x_min_index + x_max_index) / 2)]fq3 = img[y_max_index, int((x_min_index + x_max_index) / 2)]img_[y, x] = (fq1 * (y_max_pos - pos_y) + fq3 * (pos_y - y_min_pos)) / (y_max_pos - y_min_pos)else:if pos_x - int(pos_x) < 0.5: # 左距大于等于右距x_min_pos = int(pos_x) - 0.5x_max_pos = int(pos_x) + 0.5else: # 左距小于右距x_min_pos = int(pos_x) + 0.5x_max_pos = int(pos_x) + 1.5x_min_index = int(x_min_pos - 0.5)x_max_index = int(x_max_pos - 0.5)if pos_y - int(pos_y) == 0.5: # y方向點(diǎn)剛好與像素點(diǎn)重合y_min_index = y_max_index = int(pos_y - 0.5)fq1 = img[int((y_min_index + y_max_index) / 2), x_min_index]fq2 = img[int((y_min_index + y_max_index) / 2), x_max_index]img_[y, x] = (fq1 * (x_max_pos - pos_x) + fq2 * (pos_x - x_min_pos)) / (x_max_pos - x_min_pos)else: # y方向點(diǎn)與像素點(diǎn)不重合if pos_y - int(pos_y) < 0.5: # 上距大于等于下距y_min_pos = int(pos_y) - 0.5y_max_pos = int(pos_y) + 0.5else: # 左距小于右距y_min_pos = int(pos_y) + 0.5y_max_pos = int(pos_y) + 1.5y_min_index = int(y_min_pos - 0.5)y_max_index = int(y_max_pos - 0.5)fq1 = img[y_min_index, x_min_index]fq2 = img[y_min_index, x_max_index]fq3 = img[y_max_index, x_min_index]fq4 = img[y_max_index, x_max_index]fr1 = (fq1 * (x_max_pos - pos_x) + fq2 * (pos_x - x_min_pos)) / (x_max_pos - x_min_pos)fr2 = (fq3 * (x_max_pos - pos_x) + fq4 * (pos_x - x_min_pos)) / (x_max_pos - x_min_pos)img_[y, x] = (fr1 * (y_max_pos - pos_y) + fr2 * (pos_y - y_min_pos)) / (y_max_pos - y_min_pos)# print(fq1, fq2, fq3, fq4, img_[y, x])# print(x_min_index, x_max_index, y_min_index, y_max_index) # 0.0 1.0 1.0 2.0# lx, ly = x_max_index - x_min_index, y_max_index - y_min_index# fr1 = ((x_max_index - x) * fq1 + (x - x_min_index) * fq2) / lx# fr2 = ((x_max_index - x) * fq3 + (x - x_min_index) * fq4) / lx# img_[y, x] = ((y_max_index - y) * fr1 + (y - y_min_index) * fr2) / lyreturn img_# 在這里設(shè)置圖片最終分辨率(縱,橫) resolution = 1800, 2400 # print(type(scale)) # <class 'tuple'> img = cv.imread('cat.jpg') print(img.shape) # (600, 800, 3) img_ = BI(img, resolution) cv.imshow('win1', img) cv.imshow('win2', img_) cv.waitKey(0)結(jié)果:
原圖:
開numexpr加速
開了還沒(méi)numba.jit快,不開了。。。
總結(jié)
代碼的適應(yīng)性比較強(qiáng),無(wú)論分辨率是多少的圖片,放大或縮小,成比例變換或非成比例變換,都不會(huì)產(chǎn)生bug,但是代碼邏輯有些混亂,代碼重復(fù)率較高,計(jì)算公式最好多使用函數(shù)的形式表示,同時(shí)這樣在使用numba加速時(shí),能獲得較好的效果
參考文章1:雙線性插值算法進(jìn)行圖像縮放及性能效果優(yōu)化
另外,引用中又發(fā)現(xiàn)了一些端倪
他說(shuō)這樣能夠提高運(yùn)算速度
直接調(diào)用opencv庫(kù)(不知為啥那么快)
# -*- coding: utf-8 -*- """ @File : 雙線性內(nèi)插法3(直接調(diào)用opencv庫(kù)).py @Time : 2020/6/29 17:14 @Author : Dontla @Email : sxana@qq.com @Software: PyCharm """ import cv2 as cvdef BI(img, resolution):return cv.resize(img, (resolution[1], resolution[0]), interpolation=cv.INTER_CUBIC)# return cv.resize(img, (resolution[1], resolution[0]), interpolation=cv.INTER_LINEAR)# return cv.resize(img, (resolution[1], resolution[0]), interpolation=cv.INTERSECT_PARTIAL)img = cv.imread('cat_150-200.jpg') # print(img.shape) # (600, 800, 3) resolution = 600, 800 img_ = BI(img, resolution) cv.imshow('win1', img) cv.imshow('win2', img_) # cv.imwrite('cat_150-200.jpg', BI(img, resolution)) cv.waitKey(0)原圖:
結(jié)果:
參考文章:opencv庫(kù)實(shí)現(xiàn)圖像最近鄰、雙線性、雙三次插值
總結(jié)
以上是生活随笔為你收集整理的【数字图像处理】图像内插“双线性内插法 Bilinear interpolation”代码演示(以像素中心点确定像素位置)(图像放大缩小)具有低通滤波性质,使高频分量受损,图像轮廓可能会有一点模糊的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: python 如何判断一个数为整数?(判
- 下一篇: 图像变清晰 图像放大 提高分辨率 提高清