Python實(shí)現(xiàn)RGB等圖片的圖像插值算法
前言
問(wèn)題:我們?cè)诜糯髨D片的過(guò)程中,放大的目標(biāo)圖像和原圖圖像之間會(huì)存在不同。
放大的基本思想:
第一步:
將目標(biāo)圖像進(jìn)行縮小到原圖像的尺寸,虛擬的將二者進(jìn)行對(duì)重疊在一起,這樣目標(biāo)圖像上面的像素點(diǎn)就和原圖像上面的像素點(diǎn)并不是一一對(duì)應(yīng)的。
第二步:
將目標(biāo)圖像與原圖像的像素點(diǎn)進(jìn)行建立一個(gè)映射關(guān)系,這個(gè)像素點(diǎn)的映射關(guān)系不是單一的像素映射,因?yàn)槲覀儼褕D片存放在三維數(shù)組里面,所以我們?cè)诘玫綀D像的像素點(diǎn)時(shí),我們是通過(guò)索引數(shù)組的高和寬,在坐標(biāo)系中對(duì)應(yīng)的就是x坐標(biāo)、y坐標(biāo).
第三步:
怎樣建立映射關(guān)系呢?
- 最臨近插值法
- 線性插值法
- 雙線性插值法
- 三線性插值法
本文中用到了前面三種插值算法,并且進(jìn)行了代碼實(shí)現(xiàn),代碼僅供參考,大佬隨便看一下小菜雞的就行了,還希望大佬能指出其中的錯(cuò)誤或不足之處,跪謝。
RGB彩色圖像和數(shù)組理解
對(duì)于這個(gè)圖片讀取到數(shù)組中形成的三維數(shù)組,我剛理解了很久,在網(wǎng)上找大佬的資料自己看等等,然后慢慢的才形成了自己的理解,大佬們都是縱說(shuō)紛紜,自己走了很多彎路,這里吧我的理解寫下來(lái),第一,方便自以后學(xué)習(xí)查看;第二,方便和我一樣的初學(xué)者理解。
先話不多說(shuō),直接上一個(gè)圖:
這里我直接把彩色圖片的三個(gè)通道數(shù)畫成了三位圖片顯示出來(lái)方面自己理解。彩色圖片是三通道的,分別為R、G、B,這三個(gè)通道的重疊,通過(guò)調(diào)節(jié)每個(gè)通道數(shù)灰度值的亮度,從而構(gòu)成了五顏六色的彩色世界??!
紅色區(qū)域?yàn)榈?通道(R),以此類推,第1通道(G)、第2通道(B)。讀取回來(lái)的數(shù)組是一個(gè)三維數(shù)組,這個(gè)三維數(shù)組又分為了很多二維矩陣,每個(gè)二維矩陣有三個(gè)列(三個(gè)通道)。上圖中有多少個(gè)i(高h(yuǎn)),就表示三維數(shù)組中有多少個(gè)二維數(shù)組,有多少個(gè)j(寬h),就表示二維數(shù)組有多少個(gè)行,通道數(shù)k表示通道數(shù),彩色圖像有三個(gè)通道,所以 k 是個(gè)固定值 3。
數(shù)組中的值怎么理解欸?
下面插入我這個(gè)靈魂畫師的一張圖示來(lái)說(shuō)明吧哈哈哈哈哈哈(不禁默默的流下了眼淚)
上圖中左邊給出了一個(gè)圖片讀入到數(shù)組(假設(shè))中的樣子,不同顏色的線條表示組成的不同通道圖片,然后再把這三個(gè)通道里面的圖片按照上上圖片一樣堆疊起來(lái),就構(gòu)成了這個(gè)三維空間圖了。
RGB圖像的理解就說(shuō)到這里吧,希望能幫助到和我一樣的初學(xué)者少走彎路。
圖片坐標(biāo)對(duì)其
要問(wèn)這公式怎么來(lái)的,第一個(gè)可以根據(jù)放大后像素點(diǎn)的位置成比例算出來(lái),第二個(gè)公式暫時(shí)還沒想出來(lái)咋個(gè)算出來(lái)的,要是有大佬給我指出來(lái)就好了。
在代碼中有傳入?yún)?shù)指定使用哪一種對(duì)齊方式align = left,該參數(shù)默認(rèn)是居中對(duì)其center。
左對(duì)齊
src_X = dst_X*(src_Width/dst_Width) src_Y = dst_Y*(src_Height/dst_Height)
這里的src_X 就是目標(biāo)圖像上的點(diǎn)映射到原圖像上的x坐標(biāo)點(diǎn),同理src_Y 就是映射到原圖像上的y坐標(biāo)點(diǎn)。
dst_X表示目標(biāo)圖像的x坐標(biāo),dst_Y表示目標(biāo)圖像的y坐標(biāo)。
中心對(duì)齊
src_X = (dst_X+0.5)*(src_Width/dst_Width) - 0.5 src_Y = (dst_Y+0.5)*(src_Height/dst_Height) - 0.5
這里的src_X 就是目標(biāo)圖像上的點(diǎn)映射到原圖像上的x坐標(biāo)點(diǎn),同理src_Y 就是映射到原圖像上的y坐 標(biāo)點(diǎn)。
dst_X表示目標(biāo)圖像的x坐標(biāo),dst_Y表示目標(biāo)圖像的y坐標(biāo)。
臨近插值算法
最鄰近插值算法是最簡(jiǎn)單的,我們算出來(lái)的坐標(biāo)點(diǎn):i ,j,使用round函數(shù)對(duì)其進(jìn)行四舍五入,就可以得到img[i,j]這個(gè)像素點(diǎn)的臨近值了(是一個(gè)像素值)。
這個(gè)圖片中就能看出,A點(diǎn)是目標(biāo)圖像映射到原圖像上面的位置,整個(gè)背景是原圖像,圖中的Q1、Q2、Q3、Q4四個(gè)點(diǎn)就是A點(diǎn)的最鄰近的四個(gè)像素點(diǎn)。
最鄰近插值算法的代碼是最簡(jiǎn)單的,但是放大后的圖片效果是最差的,下面看代碼實(shí)現(xiàn):
def nearest_inter(self): """最鄰近插值法""" new_img = np.zeros((self.goal_h, self.goal_w, self.goal_channel), dtype=np.uint8) for i in range(0, new_img.shape[0]): for j in range(0, new_img.shape[1]): src_i, src_j = self.convert2src_axes(i, j) new_img[i, j] = self.img[round(src_i), round(src_j)] return new_img
線性插值法
線性插值公式說(shuō)白了就是,咱們數(shù)學(xué)中的直線的參數(shù)方程形式。我們知道兩點(diǎn)可以確定一條直線,但是在確定好的這條直線中我們?cè)趺创_定直線中的某個(gè)點(diǎn)呢,這樣我們就可以根據(jù)兩條平行線之間的關(guān)系來(lái)建立該兩點(diǎn)確定的直線方程??聪旅娴膱D(圖是我在網(wǎng)上搬的,勿噴,侵刪)
所以這樣就能得該直線方程了。
這里給出線性插值算法的代碼:
def linear_inter(self): """線性插值算法""" new_img = np.zeros((self.goal_h, self.goal_w, self.goal_channel), dtype=np.uint8) for i in range(0, new_img.shape[0]): for j in range(0, new_img.shape[1]): src_i, src_j = self.convert2src_axes(i, j) if ((src_j - int(src_j)) == 0 and (src_i - int(src_i)) == 0) \ or ((src_i - int(src_i)) == 0) \ or ( (src_j - int(src_j)) == 0): # 表明border_src_j是一個(gè)整數(shù) 如果是整數(shù),直接將原圖的灰度值付給目標(biāo)圖像即可 new_img[i, j] = self.img[round(src_i), round(src_j)] # 直接將原圖的灰度值賦值給目標(biāo)圖像即可 else: """否則進(jìn)行向上和向下取整,然后進(jìn)行(一維)線性插值算法""" src_i, src_j = self.convert2src_axes(i, j) j1 = int(src_j) # 向下取整 j2 = math.ceil(src_j) # 向上取整 new_img[i, j] = (j2 - src_j)*self.img[round(src_i), j1] + (src_j-j1)*self.img[round(src_i), j2] return new_img
雙線性插值
雙線性插值算法實(shí)現(xiàn)起來(lái)就比線性插值算法要難一些,本質(zhì)上還是和線性插值算法一樣,都是為了去找更目標(biāo)圖像映射到原圖像上的點(diǎn),把這個(gè)點(diǎn)周圍盡像素盡可能多的信息傳遞到這個(gè)點(diǎn)中。線性插值使用到了周圍的兩個(gè)點(diǎn),這里的雙線性就是使用到了周圍的四個(gè)點(diǎn)的像素值信息,所以理論上來(lái)說(shuō),采用雙線線性插值算法的效果會(huì)明顯優(yōu)于線性插值算法(單線性插值算法)。更具體的圖示我這里就不畫出來(lái)了,就使用我自己手繪的簡(jiǎn)化版(因?yàn)閼校?,網(wǎng)上其他帖子講得更加明白,這里只貼出我自己的理解,這樣以后來(lái)看的時(shí)候也能一目了然。
圖中的x就是圖片的高h(yuǎn),y就是圖片的寬度w,因?yàn)槲覀冏x出來(lái)的圖片是彩色圖片,所以這樣操作的同時(shí),圖片的三個(gè)通道也會(huì)同步更新這樣的操作。
下面給出雙線性插值算法的python代碼:
def double_linear_inter(self): new_img = np.zeros((self.goal_h-2, self.goal_w-2, self.goal_channel), dtype=np.uint8) # 這里減的目的就是為了可以進(jìn)行向上向下取整 for i in range(0, new_img.shape[0]): # 減1的目的就是為了可以進(jìn)行向上向下取整數(shù) for j in range(0, new_img.shape[1]): inner_src_i, inner_src_j = self.convert2src_axes(i, j) # 將取得到的變量參數(shù)坐標(biāo)映射到原圖中,并且返回映射到原圖中的坐標(biāo) inner_i1 = int(inner_src_i) # 對(duì)行進(jìn)行向上向下取整數(shù) inner_i2 = math.ceil(inner_src_i) inner_j1 = int(inner_src_j) # 對(duì)列進(jìn)行向上向下取整數(shù) inner_j2 = math.ceil(inner_src_j) Q1 = (inner_j2 - inner_src_j) * self.img[inner_i1, inner_j1] + \ (inner_src_j - inner_j1) * self.img[inner_i1, inner_j2] Q2 = (inner_j2 - inner_src_j) * self.img[inner_i2, inner_j1] + \ (inner_src_j - inner_j1) * self.img[inner_i2, inner_j2] new_img[i, j] = (inner_i2 - inner_src_i) * Q1 + (inner_src_i - inner_i1) * Q2 return new_img
三種插值算法的綜合使用
在進(jìn)行圖片處理的時(shí)候,對(duì)于圖片的四個(gè)角,沒有四個(gè)或者兩個(gè)鄰域,所以四個(gè)角就采用最鄰近插值算法實(shí)現(xiàn),二上下,左右這幾行,沒有四個(gè)鄰域,所以采用線性插值算法,其余中心部分每個(gè)點(diǎn)都有四個(gè)鄰域,所以采用雙線性插值算法來(lái)實(shí)現(xiàn),這樣的圖片效果會(huì)更好,以下是這三種算法的具體實(shí)現(xiàn):
def all_transform(self): # source_h, source_w, source_channel = self.img.shape # 獲得原圖像的高度,寬度和通道量 # goal_h, goal_w = round(source_h*self.h_rate), round(source_w*self.w_rate) # 將原圖像的size進(jìn)行按照傳入進(jìn)來(lái)的rate參數(shù)等比的放大 # goal_channel = source_channel """進(jìn)行圖像轉(zhuǎn)換了""" new_img = np.zeros((self.goal_h-1, self.goal_w-1, self.goal_channel), dtype=np.uint8) # 得到一個(gè)空的數(shù)組用來(lái)存放轉(zhuǎn)換后的值,即為新的圖片 """邊界使用線性插值算法""" temp_row = [0, new_img.shape[0]-1] # 上下兩行進(jìn)行線性插值 for i in temp_row: # i -> h -> x # j -> w -> y for j in range(0, new_img.shape[1]): """邊界線(除了四個(gè)角落)采用線性插值法""" t_border_src_i, t_border_src_j = self.convert2src_axes(i, j) if ((t_border_src_j - int(t_border_src_j)) == 0 and (t_border_src_i - int(t_border_src_i)) == 0) \ or (t_border_src_i - int(t_border_src_i)) == 0 \ or (t_border_src_j - int(t_border_src_j)) == 0: # 表明t_border_src_j是一個(gè)整數(shù) 如果是整數(shù),直接將原圖的灰度值付給目標(biāo)圖像即可 new_img[i, j] = self.img[round(t_border_src_i), round(t_border_src_j)] # 直接將原圖的灰度值賦值給目標(biāo)圖像即可 else: """否則進(jìn)行向上和向下取整,然后進(jìn)行(一維)線性插值算法""" t_border_src_i, t_border_src_j = self.convert2src_axes(i, j) j1 = int(t_border_src_j) # 向下取整 j2 = math.ceil(t_border_src_j) # 向上取整 new_img[i, j] = self.img[round(t_border_src_i), j1] + (t_border_src_j - j1) * \ (self.img[round(t_border_src_i), j2] - self.img[round(t_border_src_i), j1]) # 左右兩列進(jìn)行線性插值 temp_col = [0, new_img.shape[1]-1] for i in temp_col: # i -> w -> y # j -> h -> x for j in range(0, new_img.shape[0]): """邊界線(除了四個(gè)角落)采用線性插值法""" t_border_src_i, t_border_src_j = self.convert2src_axes(i, j) if ((t_border_src_j - int(t_border_src_j)) == 0 and (t_border_src_i - int(t_border_src_i)) == 0) \ or (t_border_src_i - int(t_border_src_i)) == 0 \ or (t_border_src_j - int(t_border_src_j)) == 0: # 表明border_src_j是一個(gè)整數(shù) 如果是整數(shù),直接將原圖的灰度值付給目標(biāo)圖像即可 new_img[j, i] = self.img[round(t_border_src_i), round(t_border_src_j)] # 直接將原圖的灰度值賦值給目標(biāo)圖像即可 else: """否則進(jìn)行向上和向下取整,然后進(jìn)行(一維)線性插值算法""" t_border_src_i, t_border_src_j = self.convert2src_axes(j, i) j1 = int(t_border_src_i) # 向下取整 j2 = math.ceil(t_border_src_i) # 向上取整 new_img[j, i] = self.img[j1, round(t_border_src_j)] + (t_border_src_i - j1) * \ (self.img[j2, round(t_border_src_j)] - self.img[j1, round(t_border_src_j)]) """四個(gè)角落(頂點(diǎn))使用最臨近插值算法""" corner_low = [0, new_img.shape[0]-1] corner_height = [0, new_img.shape[1]-1] for i in corner_low: for j in corner_height: src_i, src_j = self.convert2src_axes(i, j) new_img[i, j] = self.img[round(src_i), round(src_j)] """中間的使用雙線性插值法""" for i in range(1, new_img.shape[0] - 1): # 減1的目的就是為了可以進(jìn)行向上向下取整數(shù) for j in range(1, new_img.shape[1] - 1): inner_src_i, inner_src_j = self.convert2src_axes(i, j) # 將取得到的變量參數(shù)坐標(biāo)映射到原圖中,并且返回映射到原圖中的坐標(biāo) inner_i1 = int(inner_src_i) # 對(duì)行進(jìn)行向上向下取整數(shù) inner_i2 = math.ceil(inner_src_i) inner_j1 = int(inner_src_j) # 對(duì)列進(jìn)行向上向下取整數(shù) inner_j2 = math.ceil(inner_src_j) Q1 = (inner_j2 - inner_src_j) * self.img[inner_i1, inner_j1] + \ (inner_src_j - inner_j1) * self.img[inner_i1, inner_j2] Q2 = (inner_j2 - inner_src_j) * self.img[inner_i2, inner_j1] + \ (inner_src_j - inner_j1) * self.img[inner_i2, inner_j2] new_img[i, j] = (inner_i2 - inner_src_i) * Q1 + (inner_src_i - inner_i1) * Q2 return new_img
附件
下面附上我這個(gè)插值算法所有的代碼
import numpy as np
import cv2
import math
import logging
class Image_inter_lines(object):
"""設(shè)置傳入?yún)?shù)"""
def __init__(self, img, modify_size=(3, 3), *, align='center'):
self.img = img
self.h_rate = modify_size[0] # 高度的縮放率
self.w_rate = modify_size[1] # 寬度的縮放率
self.align = align # 設(shè)置居中模式,進(jìn)而進(jìn)行判斷其對(duì)齊方式
self.source_h = img.shape[0] # 對(duì)應(yīng) i 列 -> x
self.source_w = img.shape[1] # 對(duì)飲 j 列 -> y
self.goal_channel = img.shape[2] # 通道數(shù)
self.goal_h = round(self.source_h * self.h_rate) # 將原圖像的size進(jìn)行按照傳入進(jìn)來(lái)的rate參數(shù)等比的放大
self.goal_w = round(self.source_w * self.w_rate)
if self.align not in ['center', 'left']:
logging.exception(f'{self.align} is not a valid align parameter')
self.align = 'center' # 如果傳入的參數(shù)不是居中或者居左,則強(qiáng)制將其置為居中
pass
def set_rate(self, new_modify_size=(None, None)):
self.h_rate = new_modify_size[0]
self.w_rate = new_modify_size[1]
def convert2src_axes(self, des_x, des_y):
if self.align == 'left': # 左對(duì)齊
src_x = float(des_x * (self.source_w / self.goal_w))
src_y = float(des_y * (self.source_h / self.goal_h))
src_x = min((self.source_h - 1), src_x)
src_y = min((self.source_w - 1), src_y)
else: # 幾何中心對(duì)齊
src_x = float(des_x * (self.source_w / self.goal_w) + 0.5 * (self.source_w / self.goal_w))
src_y = float(des_y * (self.source_h / self.goal_h) + 0.5 * (self.source_h / self.goal_h))
src_x = min((self.source_h - 1), src_x)
src_y = min((self.source_w - 1), src_y)
return src_x, src_y # 這里返回的數(shù)值可以是小數(shù),也可能是整數(shù)例如:23.00,但是這個(gè)數(shù)仍然是小數(shù)
def nearest_inter(self):
"""最鄰近插值法"""
new_img = np.zeros((self.goal_h, self.goal_w, self.goal_channel), dtype=np.uint8)
for i in range(0, new_img.shape[0]):
for j in range(0, new_img.shape[1]):
src_i, src_j = self.convert2src_axes(i, j)
new_img[i, j] = self.img[round(src_i), round(src_j)]
return new_img
def linear_inter(self):
"""線性插值算法"""
new_img = np.zeros((self.goal_h, self.goal_w, self.goal_channel), dtype=np.uint8)
for i in range(0, new_img.shape[0]):
for j in range(0, new_img.shape[1]):
src_i, src_j = self.convert2src_axes(i, j)
if ((src_j - int(src_j)) == 0 and (src_i - int(src_i)) == 0) \
or ((src_i - int(src_i)) == 0) \
or (
(src_j - int(src_j)) == 0): # 表明t_border_src_j是一個(gè)整數(shù) 如果是整數(shù),直接將原圖的灰度值付給目標(biāo)圖像即可
new_img[i, j] = self.img[round(src_i), round(src_j)] # 直接將原圖的灰度值賦值給目標(biāo)圖像即可
else:
"""否則進(jìn)行向上和向下取整,然后進(jìn)行(一維)線性插值算法"""
src_i, src_j = self.convert2src_axes(i, j)
j1 = int(src_j) # 向下取整
j2 = math.ceil(src_j) # 向上取整
new_img[i, j] = (j2 - src_j)*self.img[round(src_i), j1] + (src_j-j1)*self.img[round(src_i), j2]
return new_img
def double_linear_inter(self):
new_img = np.zeros((self.goal_h-2, self.goal_w-2, self.goal_channel), dtype=np.uint8) # 這里減的目的就是為了可以進(jìn)行向上向下取整
for i in range(0, new_img.shape[0]): # 減1的目的就是為了可以進(jìn)行向上向下取整數(shù)
for j in range(0, new_img.shape[1]):
inner_src_i, inner_src_j = self.convert2src_axes(i, j) # 將取得到的變量參數(shù)坐標(biāo)映射到原圖中,并且返回映射到原圖中的坐標(biāo)
inner_i1 = int(inner_src_i) # 對(duì)行進(jìn)行向上向下取整數(shù)
inner_i2 = math.ceil(inner_src_i)
inner_j1 = int(inner_src_j) # 對(duì)列進(jìn)行向上向下取整數(shù)
inner_j2 = math.ceil(inner_src_j)
Q1 = (inner_j2 - inner_src_j) * self.img[inner_i1, inner_j1] + \
(inner_src_j - inner_j1) * self.img[inner_i1, inner_j2]
Q2 = (inner_j2 - inner_src_j) * self.img[inner_i2, inner_j1] + \
(inner_src_j - inner_j1) * self.img[inner_i2, inner_j2]
new_img[i, j] = (inner_i2 - inner_src_i) * Q1 + (inner_src_i - inner_i1) * Q2
return new_img
def all_transform(self):
# source_h, source_w, source_channel = self.img.shape # 獲得原圖像的高度,寬度和通道量
# goal_h, goal_w = round(source_h*self.h_rate), round(source_w*self.w_rate) # 將原圖像的size進(jìn)行按照傳入進(jìn)來(lái)的rate參數(shù)等比的放大
# goal_channel = source_channel
"""進(jìn)行圖像轉(zhuǎn)換了"""
new_img = np.zeros((self.goal_h-1, self.goal_w-1, self.goal_channel), dtype=np.uint8) # 得到一個(gè)空的數(shù)組用來(lái)存放轉(zhuǎn)換后的值,即為新的圖片
"""邊界使用線性插值算法"""
temp_row = [0, new_img.shape[0]-1]
# 上下兩行進(jìn)行線性插值
for i in temp_row:
# i -> h -> x
# j -> w -> y
for j in range(0, new_img.shape[1]):
"""邊界線(除了四個(gè)角落)采用線性插值法"""
t_border_src_i, t_border_src_j = self.convert2src_axes(i, j)
if ((t_border_src_j - int(t_border_src_j)) == 0 and (t_border_src_i - int(t_border_src_i)) == 0) \
or (t_border_src_i - int(t_border_src_i)) == 0 \
or (t_border_src_j - int(t_border_src_j)) == 0: # 表明t_border_src_j是一個(gè)整數(shù) 如果是整數(shù),直接將原圖的灰度值付給目標(biāo)圖像即可
new_img[i, j] = self.img[round(t_border_src_i), round(t_border_src_j)] # 直接將原圖的灰度值賦值給目標(biāo)圖像即可
else:
"""否則進(jìn)行向上和向下取整,然后進(jìn)行(一維)線性插值算法"""
t_border_src_i, t_border_src_j = self.convert2src_axes(i, j)
j1 = int(t_border_src_j) # 向下取整
j2 = math.ceil(t_border_src_j) # 向上取整
new_img[i, j] = self.img[round(t_border_src_i), j1] + (t_border_src_j - j1) * \
(self.img[round(t_border_src_i), j2] - self.img[round(t_border_src_i), j1])
# 左右兩列進(jìn)行線性插值
temp_col = [0, new_img.shape[1]-1]
for i in temp_col:
# i -> w -> y
# j -> h -> x
for j in range(0, new_img.shape[0]):
"""邊界線(除了四個(gè)角落)采用線性插值法"""
t_border_src_i, t_border_src_j = self.convert2src_axes(i, j)
if ((t_border_src_j - int(t_border_src_j)) == 0 and (t_border_src_i - int(t_border_src_i)) == 0) \
or (t_border_src_i - int(t_border_src_i)) == 0 \
or (t_border_src_j - int(t_border_src_j)) == 0: # 表明border_src_j是一個(gè)整數(shù) 如果是整數(shù),直接將原圖的灰度值付給目標(biāo)圖像即可
new_img[j, i] = self.img[round(t_border_src_i), round(t_border_src_j)] # 直接將原圖的灰度值賦值給目標(biāo)圖像即可
else:
"""否則進(jìn)行向上和向下取整,然后進(jìn)行(一維)線性插值算法"""
t_border_src_i, t_border_src_j = self.convert2src_axes(j, i)
j1 = int(t_border_src_i) # 向下取整
j2 = math.ceil(t_border_src_i) # 向上取整
new_img[j, i] = self.img[j1, round(t_border_src_j)] + (t_border_src_i - j1) * \
(self.img[j2, round(t_border_src_j)] - self.img[j1, round(t_border_src_j)])
"""四個(gè)角落(頂點(diǎn))使用最臨近插值算法"""
corner_low = [0, new_img.shape[0]-1]
corner_height = [0, new_img.shape[1]-1]
for i in corner_low:
for j in corner_height:
src_i, src_j = self.convert2src_axes(i, j)
new_img[i, j] = self.img[round(src_i), round(src_j)]
"""中間的使用雙線性插值法"""
for i in range(1, new_img.shape[0] - 1): # 減1的目的就是為了可以進(jìn)行向上向下取整數(shù)
for j in range(1, new_img.shape[1] - 1):
inner_src_i, inner_src_j = self.convert2src_axes(i, j) # 將取得到的變量參數(shù)坐標(biāo)映射到原圖中,并且返回映射到原圖中的坐標(biāo)
inner_i1 = int(inner_src_i) # 對(duì)行進(jìn)行向上向下取整數(shù)
inner_i2 = math.ceil(inner_src_i)
inner_j1 = int(inner_src_j) # 對(duì)列進(jìn)行向上向下取整數(shù)
inner_j2 = math.ceil(inner_src_j)
Q1 = (inner_j2 - inner_src_j) * self.img[inner_i1, inner_j1] + \
(inner_src_j - inner_j1) * self.img[inner_i1, inner_j2]
Q2 = (inner_j2 - inner_src_j) * self.img[inner_i2, inner_j1] + \
(inner_src_j - inner_j1) * self.img[inner_i2, inner_j2]
new_img[i, j] = (inner_i2 - inner_src_i) * Q1 + (inner_src_i - inner_i1) * Q2
return new_img
if __name__ == '__main__':
pic1 = cv2.imread(r'C:\Users\heshijie\Desktop\Py_study\image processing\Carmen.jpg')
pic2 = cv2.imread(r'C:\Users\heshijie\Desktop\Py_study\image processing\girl.jpg')
pic3 = cv2.imread(r'C:\Users\heshijie\Desktop\Py_study\image processing\architecture.jpg')
Obj_pic1 = Image_inter_lines(pic1, modify_size=(2, 2), align='center')
new_pic1 = Obj_pic1.nearest_inter()
cv2.imshow('origin', pic1)
cv2.imshow('nearest_inter', new_pic1)
new_pic2 = Obj_pic1.linear_inter()
cv2.imshow('liner_inter', new_pic2)
new_pic3 = Obj_pic1.all_transform()
cv2.imshow('double_liner_inter', new_pic3)
cv2.waitKey()
到此這篇關(guān)于Python實(shí)現(xiàn)RGB等圖片的圖像插值算法的文章就介紹到這了,更多相關(guān)Python 圖像插值算法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python unittest裝飾器實(shí)現(xiàn)原理及代碼
這篇文章主要介紹了Python unittest裝飾器實(shí)現(xiàn)原理及代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09Python?Django源碼運(yùn)行過(guò)程解析
這篇文章主要介紹了Python?Django源碼運(yùn)行過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08使用 prometheus python 庫(kù)編寫自定義指標(biāo)的方法(完整代碼)
這篇文章主要介紹了使用 prometheus python 庫(kù)編寫自定義指標(biāo)的方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-068段用于數(shù)據(jù)清洗Python代碼(小結(jié))
這篇文章主要介紹了8段用于數(shù)據(jù)清洗Python代碼(小結(jié)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10python 如何將兩個(gè)實(shí)數(shù)矩陣合并為一個(gè)復(fù)數(shù)矩陣
這篇文章主要介紹了使用python實(shí)現(xiàn)將兩個(gè)實(shí)數(shù)矩陣合并為一個(gè)復(fù)數(shù)矩陣的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2021-05-05