【数字图像处理】图像内插“双线性内插法 Bilinear interpolation”代码演示(以像素中心点确定像素位置)(图像放大缩小)具有低通滤波性质,使高频分量受损,图像轮廓可能会有一点模糊
文章目錄
- 原理
- 代碼
- 開了個jit加速(沒有提高太多)
- 開numexpr加速
- 總結
- 直接調用opencv庫(不知為啥那么快)
原理
雙線性內插法是使用目標點四周最近的四個點,沿距目標點x方向、y方向的權重關系,去分配給目標點顏色值
如圖,P點是目標點,Q1、Q2、Q3、Q4是目標點周圍的四個點,先分別對Q1、Q2和Q3、Q4沿x方向進行內插,得到R1、R2兩個點,再對R1、R2沿y方向進行內插,得到目標點P
計算公式如下
注意:上面點p(x,y)里的x為換算到原圖的(pos_x - 1),y為換算到原圖后的(pos_y - 1)
我怎么想了一下,以像素右下角貌似不對,應該以像素中心點確定位置!!!
距離應該以絕對值來表示的,另外,以先計算四個點的方法確實好使,減少判斷(先計算點,再判斷點是否重合)
具體以正式運行的代碼為準
代碼
開了個jit加速(沒有提高太多)
# -*- coding: utf-8 -*- """ @File : 雙線性內插法(續).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)# 列外層,行內層for y in range(dstH):for x in range(dstW):print(y, x)pos_y = (y + 0.5) / dstH * srcH # 比較的時候要以像素實際的位置(像素四方塊中心點),不能以像素下標pos_x = (x + 0.5) / dstW * srcW # 比較的時候要以像素實際的位置(像素四方塊中心點),不能以像素下標if pos_y <= 0.5 or pos_y >= srcH - 0.5: # 上區或下區# 先判斷是上區還是下區if pos_y <= 0.5: # 上區y_lim_index = 0else: # 下區y_lim_index = srcH - 1if pos_x <= 0.5: # 左上區或左下區img_[y, x] = img[y_lim_index, 0]elif pos_x >= srcW - 0.5: # 右上區或右下區img_[y, x] = img[y_lim_index, srcW - 1]else: # 中上區或中下區(需要判斷)if pos_x - int(pos_x) == 0.5: # 剛好與像素點重合# 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: # 與像素點不重合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: # 中區(y向)if pos_x <= 0.5 or pos_x >= srcW - 0.5: # 左中區或右中區if pos_x <= 0.5:x_lim_index = 0else:x_lim_index = srcW - 1if pos_y - int(pos_y) == 0.5: # 剛好與像素點重合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: # 與像素點不重合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: # 正中區if pos_x - int(pos_x) == 0.5: # x方向點剛好與像素點重合x_min_index = x_max_index = int(pos_x - 0.5)if pos_y - int(pos_y) == 0.5: # y方向點剛好與像素點重合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方向點與像素點不重合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方向點剛好與像素點重合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方向點與像素點不重合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_# 在這里設置圖片最終分辨率(縱,橫) 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)結果:
原圖:
開numexpr加速
開了還沒numba.jit快,不開了。。。
總結
代碼的適應性比較強,無論分辨率是多少的圖片,放大或縮小,成比例變換或非成比例變換,都不會產生bug,但是代碼邏輯有些混亂,代碼重復率較高,計算公式最好多使用函數的形式表示,同時這樣在使用numba加速時,能獲得較好的效果
參考文章1:雙線性插值算法進行圖像縮放及性能效果優化
另外,引用中又發現了一些端倪
他說這樣能夠提高運算速度
直接調用opencv庫(不知為啥那么快)
# -*- coding: utf-8 -*- """ @File : 雙線性內插法3(直接調用opencv庫).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)原圖:
結果:
參考文章:opencv庫實現圖像最近鄰、雙線性、雙三次插值
總結
以上是生活随笔為你收集整理的【数字图像处理】图像内插“双线性内插法 Bilinear interpolation”代码演示(以像素中心点确定像素位置)(图像放大缩小)具有低通滤波性质,使高频分量受损,图像轮廓可能会有一点模糊的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python 如何判断一个数为整数?(判
- 下一篇: 图像变清晰 图像放大 提高分辨率 提高清