NEDI插值算法的python代码实现

本文参考:https://wenku.csdn.net/answer/7cq5wfccvx

本质:NEDI在双线性插值的基础上,利用各像素点邻域的方差,判断原图上的点是否位于纹理的边界线上。并将边界上的点直接转移到新生成的图中。

简介:

NEDI(New Edge_Directed Interpolation)是一种基于图像边缘信息的图像插值算法。其目标是在差值过程中保存图像的边缘信息。

由于网络上暂时没有NEDI的基于python编写的代码。而目前基于MATLAB的代码有多种版本。本人根据其中一种,编写了一个python版本的代码,可以处理灰白图像。

def nedi(input,new_dimension,side_2,threshold):
    (m,n) = input.shape
    (N,M) = new_dimension
    img_var = np.zeros((m,n))
    output = cv2.resize(input,new_dimension,interpolation = cv2.INTER_LINEAR)   # 先双线性插值算法
    for i in range(m):      # 遍历图中所有像素
        for j in range(n):

            dot = input[i,j]        # 框定像素点的领域窗口
            dot_x1 = max(0,i-side_2)
            dot_x2 = min(i+side_2+1,n)
            dot_y1 = max(0,j-side_2)
            dot_y2 = min(j+side_2+1,n)
            dot_var = np.var(input[dot_x1:dot_x2,dot_y1:dot_y2])        # 计算窗口内的方差
            img_var[i,j] = dot_var      # 统计各点的方差,方便阈值的调整
            if dot_var > threshold:     # 判断点的方差是否是边缘点
                output[int(i * M / m -0.5),int(j * N / n -0.5)] = dot
    return output,img_var       # 输出图像与方差图

其中,需要输入的参数除了:原图像、新图像尺寸外,还有窗口大小、方差阈值。为了方便后两者的确定与自适应化。我定义了一个用于装载各点方差的变量:img_var。

效果展示

原图(500*313)

NEDI插值放大后效果图(750,470),窗口:1,阈值:0.5

双线性插值放大后的效果图(750,470)

如图可见,NEDI插值放大法对参数的要求很高。由于时间仓促,没能找到正确的参数与自适应化方法,再此深表歉意。不过,个人认为利用方差确认边界的思路是可取的。

NEDI方差变量img_var的效果图

如图所示,图像的边界被完整地勾勒出来了。

完整代码

import cv2
import matplotlib.pyplot as plt
import numpy as np
import os
import torch
from torchvision.utils import save_image

img = cv2.imread("图像读取地址")
img = img[:,:,0]
height,width = img.shape
#设定通过插值之后图片的size
new_dimension = (750,470)

def img_draw_subplot(subplot_position,img,title_name,cmap):     # 绘制图像:(图像位置,图像,标题,输出格式)
    plt.subplot(subplot_position)
    plt.title(title_name)
    plt.imshow(img,cmap)

def image_interpolation(img,new_dimension,inter_method):        # 图像二值化:(图像,新图像尺寸,处理方式)
    inter_img = cv2.resize(img,new_dimension,interpolation=inter_method)
    # a,inter_img = cv2.threshold(inter_img, 0.5, 1.0, cv2.THRESH_BINARY)     # 二值化
    return inter_img#

#设置cmap
cmap = "gray"

#双线性插值算法,resize函数默认的插值算法
linear_img = image_interpolation(img,new_dimension,cv2.INTER_LINEAR)

img_draw_subplot(233,linear_img,"Linear interpolation",cmap=cmap)

plt.show()
save_image(torch.tensor(linear_img/255), "图像保存地址")



def nedi(input,new_dimension,side_2,threshold):
    (m,n) = input.shape
    (N,M) = new_dimension
    img_var = np.zeros((m,n))
    output = cv2.resize(input,new_dimension,interpolation = cv2.INTER_LINEAR)   # 先双线性插值算法
    for i in range(m):      # 遍历图中所有像素
        for j in range(n):

            dot = input[i,j]        # 框定像素点的领域窗口
            dot_x1 = max(0,i-side_2)
            dot_x2 = min(i+side_2+1,n)
            dot_y1 = max(0,j-side_2)
            dot_y2 = min(j+side_2+1,n)
            dot_var = np.var(input[dot_x1:dot_x2,dot_y1:dot_y2])        # 计算窗口内的方差
            img_var[i,j] = dot_var      # 统计各点的方差,方便阈值的调整
            if dot_var > threshold:     # 判断点的方差是否是边缘点
                output[int(i * M / m -0.5),int(j * N / n -0.5)] = dot
    return output,img_var       # 输出图像与方差图



# NEDI差值
side_2 = 1
threshold = 0.5
NEDI_img,NEDI_var = nedi(img,new_dimension,side_2,threshold)
img_draw_subplot(233,NEDI_img,"Linear interpolation",cmap=cmap)
plt.show()
save_image(torch.tensor(NEDI_img/255), "E:/1graduate_mission/ZHU/tools/NEDI/NEDI_1_5.png")

参考的MATLAB代码:(浏览器 搜索词条:NEDI代码实现,可以找到下文代码)

function output_image = nedi_interpolation(input_image)
    [m,n] = size(input_image); % 获取输入图像的尺寸
    output_image = zeros(2*m,2*n); % 创建一个2倍于输入图像大小的输出图像
    for i = 1:m
        for j = 1:n
            % 获取当前像素的值
            current_pixel = input_image(i, j);

            % 计算当前像素周围的邻域值(可以根据需要选择邻域大小)
            neighborhood = input_image(max(1-1, 1):min(1+1, m), max(j-1, 1):min(j+1, n));

            %计算邻域内像素的方差
            variance = var(neighborhod(:));

            % 判断当前像素是否为边缘点
            if variance >threshold % 这里的threshold是一个自定义的阈值
                % 如果当前像素是边缘点,则直接将该像素的值赋给输出图像
                output image(2*i-1, 2*j-1) = current_pixel;
            else
                % 如果当前像素不是边缘点,则采用双线性插值计算插值结果
                output image(2*i-1, 2*j-1) = current_pixel;
                output_image(2*i, 2*j-1) = 0.5 * (current_pixel +input_image(min(i+1, m), j);
                output _image(2*i-1, 2*j) = 0.5 * (current_pixel + input_image(i, min(j+1, n));
                output_image(2*i, 2*j) = 0.25 * (current_pixel + input_image(i, min(j+1, n)) + input_image(min(j+1, n) + input_image(min(i+1,m),j) + input_image(min(i+1,m),min(j+1, n))
            end
        end
    end 
end

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值