2019-06-02 16:37:58 tesla233 阅读数 385
function nearest_neighbor = nearest_neighbor( filename,N )
%最近邻插值
%输入图像文件及放大倍数
%输出根据放大倍数变化后的新图像
ima=imread(filename);

[row,col,color]=size(ima);
row_n=round(row*N);
col_n=round(col*N);

ima_new=zeros(row_n,col_n,color,class(ima));

for i=1:row_n
    for j=1:col_n
        for n=1:color
            m=round(i/N);
            k=round(j/N);
            if m<1
                m=1;
            end
            if k<1
                k=1;
            end
            if m>row
                m=row;
            end
            if k>col
                k=col;
            end
            ima_new(i,j,n)=ima(m,k,n);
        end
    end
end

imwrite(ima_new,'C:\Users\10594\Desktop\new_filename.jpg');

end

 

2016-11-01 16:32:10 yi_tech_blog 阅读数 3863

基本原理

1、最近邻插值:变换后的目标图像某点像素值等于源图像中与变换前相应点最近的点的像素值。具体操作为,设水平方向和垂直方向缩放的比例分别为w和h,那么目标图像中的点des(x,y)对应的源图像中的点src的坐标为(x0,y0)=(x/w,y/h)。其中,x0,y0可能为小数,故对其四舍五入,即(x0,y0)=int(x0+0.5,y0+0.5),因此点des(x,y)的像素值就是点src(x0,y0)的像素值。

2、双线性插值:由1中最近邻插值中的四舍五入前的点src(x0,y0)得到它的2*2区域4个邻域像素点的坐标,即(x1,y1)=(int(x0),int(y0))(x1,y2)=int(x1,y1+1),(x2,y1)=(x1+1,y1),(x2,y2)=(x1+1,y1+1),然后计算权重q1=(x0-x1)*(y0-y1),q2=(1.0-(x0-x1))*(y0-y1),q4=(x0-x1)*(1.0-(y0-y1)),q3=(1.0-(x0-x1))*(1.0-(y0-y1),用value(x,y)表示点(x,y)处的像素值,则目标图像中的点des(x,y)对应像素值value(x,y)=value(x2,y2)*q1+value(x1,y2)*q2+value(x1,y1)*q3+value(x2,y1)*q4,


c/c++实现及处理效果:

void GeometryTrans::Zoom(float ratioX, float ratioY)
{
     
    //释放旧的输出图像缓冲区
    if(m_pImgDataOut!=NULL){
        delete []m_pImgDataOut;
        m_pImgDataOut=NULL;
    }
     
    //输出图像的宽和高
    m_imgWidthOut=int(m_imgWidth*ratioX+0.5) ;
    m_imgHeightOut=int(m_imgHeight*ratioY+0.5); 
 
    //输入图像每行像素字节数
    int lineByteIn=(m_imgWidth*m_nBitCount/8+3)/4*4;
     
    //输出图像每行像素字节数
    int lineByteOut=(m_imgWidthOut*m_nBitCount/8+3)/4*4;
 
    //申请缓冲区,存放输出结果
    m_pImgDataOut=new unsigned char[lineByteOut*m_imgHeightOut];
 
    //每像素字节数,输入图像与输出图像相同
    int pixelByte=m_nBitCount/8;
     
    //输出图像在输入图像中待插值的位置坐标
    int coordinateX, coordinateY;
     
    //循环变量,输出图像的坐标
    int i, j;
     
    //循环变量,像素的每个通道
    int k;
     
    //近邻插值
    for(i=0; i< m_imgHeightOut; i++){
        for(j=0; j<m_imgWidthOut; j++){  
            //输出图像坐标为(j,i)的像素映射到原图中的坐标值,即插值位置
            coordinateX=j/ratioX+0.5;
            coordinateY=i/ratioY+0.5;
             
            //若插值位置在输入图像范围内,则近邻插值
            if(0<=coordinateX&&coordinateX<m_imgWidth
                && coordinateY>=0&&coordinateY<m_imgHeight){
                for(k=0;k<pixelByte;k++)
                    *(m_pImgDataOut + i * lineByteOut + j*pixelByte + k) 
                    =*(m_pImgData+ coordinateY*lineByteIn+ coordinateX*pixelByte + k) ;
            }
            else //若不在输入图像范围内,则置255  
            {
                for(k=0;k<pixelByte;k++)
                    *(m_pImgDataOut + i * lineByteOut + j*pixelByte+k) = 255;
            }          
        }
    }
}


最近邻插值处理结果

2、双线性插值

void GeometryTrans::Zoom(float ratioX, float ratioY)
{
     
    //释放旧的输出图像缓冲区
    if(m_pImgDataOut!=NULL){
        delete []m_pImgDataOut;
        m_pImgDataOut=NULL;
    }
     
    //输出图像的宽和高
    m_imgWidthOut=int(m_imgWidth*ratioX+0.5) ;
    m_imgHeightOut=int(m_imgHeight*ratioY+0.5); 
 
    //输入图像每行像素字节数
    int lineByteIn=(m_imgWidth*m_nBitCount/8+3)/4*4;
     
    //输出图像每行像素字节数
    int lineByteOut=(m_imgWidthOut*m_nBitCount/8+3)/4*4;
 
    //申请缓冲区,存放输出结果
    m_pImgDataOut=new unsigned char[lineByteOut*m_imgHeightOut];
 
    //每像素字节数,输入图像与输出图像相同
    int pixelByte=m_nBitCount/8;
     
    //输出图像在输入图像中待插值的位置坐标
    float coordinateX, coordinateY;
     
    //循环变量,输出图像的坐标
    int i, j;
     
    //循环变量,像素的每个通道
    int k;
 
    int y1,y2, x1,x2;
    float fx1,fx2, fy1, fy2;
     
    //双线性插值
    for(i=0; i< m_imgHeightOut; i++)
    {
        coordinateY = i/ratioY;
        y1 = (int)coordinateY;
        if(y1 == m_imgHeightOut-1)    
            y2 = y1;
        else y2 = y1 + 1;
 
        fy1 = coordinateY-y1; 
        fy2 = (float)1.0 - fy1;
 
        for(j=0; j<m_imgWidthOut; j++)
        {  
            coordinateX = j/ratioX;
            x1 = (int)coordinateX;
            if(x1 == m_imgWidthOut-1)    
                x2 = x1;
            else x2 = x1+1;
 
            fx1 = coordinateX-x1;
            fx2 = (float)1.0 - fx1;
            //所求的源图像中的2*2区域4个邻近象素点坐标为(x1, y1) (x1, y2) (x2, y1) (x2,y2)
            //计算4个权重
            float s1 = fx1*fy1;
            float s2 = fx2*fy1;
            float s3 = fx2*fy2;
            float s4 = fx1*fy2;
            //输出图像坐标为(j,i)的像素映射到原图中的坐标值,即插值位置
             
            //若插值位置在输入图像范围内,则双线性插值
            if(0<=coordinateX&&coordinateX<m_imgWidth
                && coordinateY>=0&&coordinateY<m_imgHeight)
            {
                for(k=0;k<pixelByte;k++)
                    *(m_pImgDataOut + i * lineByteOut + j*pixelByte + k) 
                    =(int)((*(m_pImgData+ y2*lineByteIn+ x2*pixelByte + k))*s1+
                           (*(m_pImgData+ y2*lineByteIn+ x1*pixelByte + k))*s2+
                           (*(m_pImgData+ y1*lineByteIn+ x1*pixelByte + k))*s3+
                           (*(m_pImgData+ y1*lineByteIn+ x2*pixelByte + k))*s4);
            }
            else //若不在输入图像范围内,则置255  
            {
                for(k=0;k<pixelByte;k++)
                    *(m_pImgDataOut + i * lineByteOut + j*pixelByte+k) = 255;
            }
             
        }
    }
}


双线性插值处理结果

比较结果可知,双线性插值处理的图像比最近邻插值处理的图像平滑、清晰。

2019-11-14 19:03:26 qq_41398808 阅读数 19

内插是使用已知数据来估计未知位置的数据的处理方法。以图像放大为例,将一张50X50像素的图片放大10倍到500X500。通过其缩放的比例,来获取原图中最接近的像素,并把该像素灰度赋值给新像素。

设:原图大小为n*m像素的图片,要扩展到a*b像素的图片

则纵向缩放比例为:Z_{r}=a/n,同理横向缩放比例为:Z_{l}=b/m

那么未知像素点(x,y),对应的原图像的像素点(x_{0},y_{0}),对应关系为:

                                                                          x_{0}=x * Z_{r}y_{0}=y*Z_{l}

下面使用Python实现任意RGB彩色图片,缩放到任意像素大小:

使用的图片如下:

 引用使用到的第三方库:

from PIL import Image
import matplotlib.pyplot as plt
import numpy as np

 读取图片数据并可视化:

img = Image.open('灰原.jpg')
plt.axis('off')
plt.imshow(img)
plt.show()

 将图像数据转换为numpy数组:

img_data = np.array(img)

查看图像大小和通道数:

np.shape(img_data)

 可以看到,原图片是300*533像素,RGB三通道的彩色图片

(300, 533, 3)

 定义最近邻内插值法的实现函数:

def Nearest_neighbor_interpolation(n, m, img):
    new_img = [[] for _ in range(n)]
    r = n / float(np.shape(img)[0])
    l = m / float(np.shape(img)[1])
    for i in range(n):
        for j in range(m):
            x0 = int(i / r)
            y0 = int(j / l)
            new_img[i].append(list(img[x0][y0]))
    return new_img

新图片数据暂时使用数组存储 

下面来看看结果:

调用函数,得到新图片,这里对原图片大小扩大一倍

new_img = Nearest_neighbor_interpolation(600, 1066, img_data)

 查看新图片大小:

np.shape(new_img)

大小与预期一致

(600, 1066, 3)

 将数组数据,转换为图片数据:

new_img = Image.fromarray(np.uint8(new_img))

 可视化结果:

plt.figure(figsize=(60,107))
plt.subplot(121)
plt.imshow(new_img)
plt.axis('off')
plt.subplot(122)
plt.imshow(img_data)
plt.axis('off')
plt.show()

 左侧为缩放结果,右侧为原图像:

 

2018-09-14 17:22:11 ch190029975 阅读数 519

图像插值算法包括向上插值和向下插值,向上插值就是对图像进行放大,向下插值就是对图像进行缩小,插值算法在图像预处理过程中经常被使用,通过插值算法,可以将图像尺寸变换为任意尺寸,下面以举例子的方式来说明两种常见的插值算法:
假设图像原始尺寸为wi,hi,缩放后的图像尺寸为wo, ho,对于缩放后图像中任意坐标(i, j),该位置处的像素值的计算方法如下:

最近邻插值算法

对于坐标i, 对应于原图像的坐标为 x=(int)(i/hohi+0.5)
对于坐标j, 对应于原图像的坐标为 y=(int)(j/wowi+0.5)
所以,缩放后图像(i, j)处的像素值等于原始图像的(x, y)处的像素值,即:F(i,j)=F(x,y)

双线性插值算法

对于坐标i,对应于原图像的坐标为x=i/hohi
对于坐标j,对应于原图像的坐标为y=j/wo/wi
假设(x,y)的坐标为(100.21, 200.65),则
F(100,200.65)=(10.65)F(100,200)+0.65F(100,201)
F(101,200.65)=(10.65)F(101,200)+0.65F(101,201)
F(100.21,200.65)=(10.21)F(100,200.65)+0.21F(101,200.65)
从而可以计算缩放后图像中任意坐标(i,j)处的像素值

2018-11-19 16:50:42 u010608296 阅读数 868

图片缩放的两种常见算法:

最近邻域内插法(Nearest Neighbor interpolation)

双向性内插法(bilinear interpolation)

本文主要讲述最近邻插值(Nearest Neighbor interpolation算法的原理以及python实现

基本原理
最简单的图像缩放算法就是最近邻插值。顾名思义,就是将目标图像各点的像素值设为源图像中与其最近的点。算法优点在与简单、速度快。

如下图所示,一个4*4的图片缩放为8*8的图片。步骤:

1. 生成一张空白的8*8的图片,然后在缩放位置填充原始图片值(可以这么理解)

2. 在图片的未填充区域(黑色部分),填充为原有图片最近的位置的像素值。

è¿éåå¾çæè¿°

实现代码如下:
def nearest_neighbor_resize(img, new_w, new_h):
    # height and width of the input img
    h, w = img.shape[0], img.shape[1]
    # new image with rgb channel
    ret_img = np.zeros(shape=(new_h, new_w, 3), dtype='uint8')
    # scale factor
    s_h, s_c = (h * 1.0) / new_h, (w * 1.0) / new_w

    # insert pixel to the new img
    for i in xrange(new_h):
        for j in xrange(new_w):
            p_x = int(j * s_c)
            p_y = int(i * s_h)

            ret_img[i, j] = img[p_y, p_x]

    return ret_img


测试代码如下:

def test():
    img_path = 'F:/nearest_neighbor.jpg'
    img = cv2.imread(img_path)

    ret_img = nearest_neighbor_resize(img, 222, 220)

    cv2.imshow("source image", img)
    cv2.imshow("after bilinear image", ret_img)
    cv2.waitKey()
    cv2.destroyAllWindows()

运行结果如下:

è¿éåå¾çæè¿°

主要参考:

http://tech-algorithm.com/articles/nearest-neighbor-image-scaling/

最近邻内插值与双线性插值的实现

博文 来自: zhangla1220
没有更多推荐了,返回首页