概述
基于上一节“等距采样法”实现图片放大与缩小的缺点。要对其进行改进,对图像的缩小则可以用“局部均值法”,对于图像的放大则可以用“双线性插值法”。
效果如下:
2048*1536缩小为100*80时的效果
100*80放大到600*400的效果
局部均值法缩小图像
(1)计算采样间隔
设原图的大小为W*H,将其放大(缩小)为(k1*W)*(K2*H),则采样区间为
ii=1/k1; jj=1/k2;
当k1==k2时为等比例缩小;当k1!=k2时为不等比例放大(缩小);当k1<1&&k2<1时为图片放大,k1<1&&k2>1时时图片缩小
(2)求出局部子块
设原图为F(x,y)(i=1,2,……W; j=1,2,……H),缩小的图像为G(x,y)(i=1,2, ……M; j=1,2,……N,其中M=W*k1,N=H*k2),则有原图像局部子块为
f’(x,y)= f(ii*i, jj*j) …… f(ii*i + ii-1, jj*j)
…… ……
f(ii*i, jj*j+jj-1) …… f(ii*i + ii-1, jj*j+jj-1)
(3)求出缩小的图像
G(x, y) = f’(x,y)的均值
例:
缩小后的图像
例如g11=(f11 +f12 + f21 + f22)/4
算法源代码(java)
/**
* 局部均值的图像缩小
* @param img 要缩小的图像对象
* @param m 缩小后图像的宽
* @param n 缩小后图像的高
* @return 返回处理后的图像对象
*/
public static BufferedImage shrink(BufferedImage img, int m, int n) {
float k1 = (float)m/img.getWidth();
float k2 = (float)n/img.getHeight();
return shrink(img, k1, k2);
}
/**
* 局部均值的图像缩小
* @param img 要缩小的图像对象
* @param k1 要缩小的列比列
* @param k2 要缩小的行比列
* @return 返回处理后的图像对象
*/
public static BufferedImage shrink(BufferedImage img, float k1, float k2) {
if(k1 >1 || k2>1) {//如果k1 >1 || k2>1则是图片放大,不是缩小
System.err.println("this is shrink image funcation, please set k1<=1 and k2<=1!");
return null;
}
float ii = 1/k1; //采样的行间距
float jj = 1/k2; //采样的列间距
int dd = (int)(ii*jj);
//int m=0 , n=0;
int imgType = img.getType();
int w = img.getWidth();
int h = img.getHeight();
int m = (int) (k1*w);
int n = (int) (k2*h);
int[] pix = new int[w*h];
pix = img.getRGB(0, 0, w, h, pix, 0, w);
System.out.println(w + " * " + h);
System.out.println(m + " * " + n);
int[] newpix = new int[m*n];
for(int j=0; j<n; j++) {
for(int i=0; i<m; i++) {
int r = 0, g=0, b=0;
ColorModel cm = ColorModel.getRGBdefault();
for(int k=0; k<(int)jj; k++) {
for(int l=0; l<(int)ii; l++) {
r = r + cm.getRed(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);
g = g + cm.getGreen(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);
b = b + cm.getBlue(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);
}
}
r = r/dd;
g = g/dd;
b = b/dd;
newpix[j*m + i] = 255<<24 | r<<16 | g<<8 | b;
//255<<24 | r<<16 | g<<8 | b 这个公式解释一下,颜色的RGB在内存中是
//以二进制的形式保存的,从右到左1-8位表示blue,9-16表示green,17-24表示red
//所以"<<24" "<<16" "<<8"分别表示左移24,16,8位
//newpix[j*m + i] = new Color(r,g,b).getRGB();
}
}
BufferedImage imgOut = new BufferedImage( m, n, imgType);
imgOut.setRGB(0, 0, m, n, newpix, 0, m);
return imgOut;
}
/**
* 局部均值的图像缩小
* @param img 要缩小的图像对象
* @param m 缩小后图像的宽
* @param n 缩小后图像的高
* @return 返回处理后的图像对象
*/
public static BufferedImage shrink(BufferedImage img, int m, int n) {
float k1 = (float)m/img.getWidth();
float k2 = (float)n/img.getHeight();
return shrink(img, k1, k2);
}
/**
* 局部均值的图像缩小
* @param img 要缩小的图像对象
* @param k1 要缩小的列比列
* @param k2 要缩小的行比列
* @return 返回处理后的图像对象
*/
public static BufferedImage shrink(BufferedImage img, float k1, float k2) {
if(k1 >1 || k2>1) {//如果k1 >1 || k2>1则是图片放大,不是缩小
System.err.println("this is shrink image funcation, please set k1<=1 and k2<=1!");
return null;
}
float ii = 1/k1; //采样的行间距
float jj = 1/k2; //采样的列间距
int dd = (int)(ii*jj);
//int m=0 , n=0;
int imgType = img.getType();
int w = img.getWidth();
int h = img.getHeight();
int m = (int) (k1*w);
int n = (int) (k2*h);
int[] pix = new int[w*h];
pix = img.getRGB(0, 0, w, h, pix, 0, w);
System.out.println(w + " * " + h);
System.out.println(m + " * " + n);
int[] newpix = new int[m*n];
for(int j=0; j<n; j++) {
for(int i=0; i<m; i++) {
int r = 0, g=0, b=0;
ColorModel cm = ColorModel.getRGBdefault();
for(int k=0; k<(int)jj; k++) {
for(int l=0; l<(int)ii; l++) {
r = r + cm.getRed(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);
g = g + cm.getGreen(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);
b = b + cm.getBlue(pix[(int)(jj*j+k)*w + (int)(ii*i+l)]);
}
}
r = r/dd;
g = g/dd;
b = b/dd;
newpix[j*m + i] = 255<<24 | r<<16 | g<<8 | b;
//255<<24 | r<<16 | g<<8 | b 这个公式解释一下,颜色的RGB在内存中是
//以二进制的形式保存的,从右到左1-8位表示blue,9-16表示green,17-24表示red
//所以"<<24" "<<16" "<<8"分别表示左移24,16,8位
//newpix[j*m + i] = new Color(r,g,b).getRGB();
}
}
BufferedImage imgOut = new BufferedImage( m, n, imgType);
imgOut.setRGB(0, 0, m, n, newpix, 0, m);
return imgOut;
}
双线性差值法放图像
子块四个顶点的坐标分别设为(0,0)、(1,0)、(0,1)、(1,1),对应的带处理的像素的坐标(c1,c2),0<c1<1, 0<y<1.则f(x,y)由上到下得到
f(x,0) = f(0,0) + c1*(f(1,0)-f(0,0))
f(x,1) = f(0,1) + c1*(f(1,1)-f(0,1))
f(x,y) = f(x,0) + c2*f(f(x,1)-f(x,0))
例,原图的像素矩阵如下。
将其放大成2.5*1.2倍,双线性插值发,填充顶点如下:
(1)
(2)
1 2 3 4 5 6 7 7
2 3 4 5 7 8 8 8
3 4 5 6 7 8 9 9
3 4 5 6 7 8 9 9
(3)
算法源代码(java)
/**
* 双线性插值法图像的放大
* @param img 要缩小的图像对象
* @param k1 要缩小的列比列
* @param k2 要缩小的行比列
* @return 返回处理后的图像对象
*/
public static BufferedImage amplify(BufferedImage img, float k1, float k2) {
if(k1 <1 || k2<1) {//如果k1 <1 || k2<1则是图片缩小,不是放大
System.err.println("this is shrink image funcation, please set k1<=1 and k2<=1!");
return null;
}
float ii = 1/k1; //采样的行间距
float jj = (1/k2); //采样的列间距
int dd = (int)(ii*jj);
//int m=0 , n=0;
int imgType = img.getType();
int w = img.getWidth(); //原图片的宽
int h = img.getHeight(); //原图片的宽
int m = Math.round(k1*w); //放大后图片的宽
int n = Math.round(k2*h); //放大后图片的宽
int[] pix = new int[w*h];
pix = img.getRGB(0, 0, w, h, pix, 0, w);
/*System.out.println(w + " * " + h);
System.out.println(m + " * " + n);*/
int[] newpix = new int[m*n];
for(int j=0; j<h-1; j++){
for(int i=0; i<w-1; i++) {
int x0 = Math.round(i*k1);
int y0 = Math.round(j*k2);
int x1, y1;
if(i == w-2) {
x1 = m-1;
} else {
x1 = Math.round((i+1)*k1);
}
if(j == h-2) {
y1 = n-1;
} else {
y1 = Math.round((j+1)*k2);
}
int d1 = x1 - x0;
int d2 = y1 - y0;
if(0 == newpix[y0*m + x0]) {
newpix[y0*m + x0] = pix[j*w+i];
}
if(0 == newpix[y0*m + x1]) {
if(i == w-2) {
newpix[y0*m + x1] = pix[j*w+w-1];
} else {
newpix[y0*m + x1] = pix[j*w+i+1];
}
}
if(0 == newpix[y1*m + x0]){
if(j == h-2) {
newpix[y1*m + x0] = pix[(h-1)*w+i];
} else {
newpix[y1*m + x0] = pix[(j+1)*w+i];
}
}
if(0 == newpix[y1*m + x1]) {
if(i==w-2 && j==h-2) {
newpix[y1*m + x1] = pix[(h-1)*w+w-1];
} else {
newpix[y1*m + x1] = pix[(j+1)*w+i+1];
}
}
int r, g, b;
float c;
ColorModel cm = ColorModel.getRGBdefault();
for(int l=0; l<d2; l++) {
for(int k=0; k<d1; k++) {
if(0 == l) {
//f(x,0) = f(0,0) + c1*(f(1,0)-f(0,0))
if(j<h-1 && newpix[y0*m + x0 + k] == 0) {
c = (float)k/d1;
r = cm.getRed(newpix[y0*m + x0]) + (int)(c*(cm.getRed(newpix[y0*m + x1]) - cm.getRed(newpix[y0*m + x0])));//newpix[(y0+l)*m + k]
g = cm.getGreen(newpix[y0*m + x0]) + (int)(c*(cm.getGreen(newpix[y0*m + x1]) - cm.getGreen(newpix[y0*m + x0])));
b = cm.getBlue(newpix[y0*m + x0]) + (int)(c*(cm.getBlue(newpix[y0*m + x1]) - cm.getBlue(newpix[y0*m + x0])));
newpix[y0*m + x0 + k] = new Color(r,g,b).getRGB();
}
if(j+1<h && newpix[y1*m + x0 + k] == 0) {
c = (float)k/d1;
r = cm.getRed(newpix[y1*m + x0]) + (int)(c*(cm.getRed(newpix[y1*m + x1]) - cm.getRed(newpix[y1*m + x0])));
g = cm.getGreen(newpix[y1*m + x0]) + (int)(c*(cm.getGreen(newpix[y1*m + x1]) - cm.getGreen(newpix[y1*m + x0])));
b = cm.getBlue(newpix[y1*m + x0]) + (int)(c*(cm.getBlue(newpix[y1*m + x1]) - cm.getBlue(newpix[y1*m + x0])));
newpix[y1*m + x0 + k] = new Color(r,g,b).getRGB();
}
//System.out.println(c);
} else {
//f(x,y) = f(x,0) + c2*f(f(x,1)-f(x,0))
c = (float)l/d2;
r = cm.getRed(newpix[y0*m + x0+k]) + (int)(c*(cm.getRed(newpix[y1*m + x0+k]) - cm.getRed(newpix[y0*m + x0+k])));
g = cm.getGreen(newpix[y0*m + x0+k]) + (int)(c*(cm.getGreen(newpix[y1*m + x0+k]) - cm.getGreen(newpix[y0*m + x0+k])));
b = cm.getBlue(newpix[y0*m + x0+k]) + (int)(c*(cm.getBlue(newpix[y1*m + x0+k]) - cm.getBlue(newpix[y0*m + x0+k])));
newpix[(y0+l)*m + x0 + k] = new Color(r,g,b).getRGB();
//System.out.println((int)(c*(cm.getRed(newpix[y1*m + x0+k]) - cm.getRed(newpix[y0*m + x0+k]))));
}
}
if(i==w-2 || l==d2-1) { //最后一列的计算
//f(1,y) = f(1,0) + c2*f(f(1,1)-f(1,0))
c = (float)l/d2;
r = cm.getRed(newpix[y0*m + x1]) + (int)(c*(cm.getRed(newpix[y1*m + x1]) - cm.getRed(newpix[y0*m + x1])));
g = cm.getGreen(newpix[y0*m + x1]) + (int)(c*(cm.getGreen(newpix[y1*m + x1]) - cm.getGreen(newpix[y0*m + x1])));
b = cm.getBlue(newpix[y0*m + x1]) + (int)(c*(cm.getBlue(newpix[y1*m + x1]) - cm.getBlue(newpix[y0*m + x1])));
newpix[(y0+l)*m + x1] = new Color(r,g,b).getRGB();
}
}
}
}
/*
for(int j=0; j<50; j++){
for(int i=0; i<50; i++) {
System.out.print(new Color(newpix[j*m + i]).getRed() + "\t");
}
System.out.println();
}
*/
BufferedImage imgOut = new BufferedImage( m, n, imgType);
imgOut.setRGB(0, 0, m, n, newpix, 0, m);
return imgOut;
}
分享到:
相关推荐
本主题聚焦于一种常见且实用的图像放大技术——双线性插值。双线性插值是一种平滑放大图像的方法,通过在原像素之间进行线性插值来生成新的像素值,从而减少放大过程中的像素块效应,提高图像的清晰度。 图像增强...
### 双线性插值图像放大/缩小算法原理 #### 一、双线性插值算法简介 双线性插值是一种广泛应用于图像处理领域的插值技术,主要...通过上述步骤,我们可以有效地实现双线性插值算法,并应用于图像的放大与缩小处理中。
总的来说,双线性内插是一种有效的图像放大方法,通过MATLAB中的`myzoom2`函数实现,可以用于高质量地放大图像,特别是对于需要保留细节和连续性的应用。在实际使用中,可以根据需求调整放大尺度`j`,以获得不同级别...
双线性插值算法的基本思想是通过计算源图像中与目标像素位置相邻的4个像素的加权平均值来确定新像素的值。 在图像放大过程中,如果一个目标像素的位置没有对应的源像素(例如,将3x3的源图像放大到6x6的目标图像)...
双线性插值是一种在数字图像...在提供的文档“双线性插值放大图像.docx”中,应该包含了具体实现该算法的详细步骤、示例代码和可能的图像结果。通过阅读这个文档,你可以进一步了解和掌握双线性插值的技术细节和应用。
双线性插值是一种在二维空间中进行数据插值的方法,常用于图像处理、计算机图形学和数值计算等领域。在MATLAB中,双线性插值提供了从已知离散数据点到连续区域的平滑插值手段。下面将详细阐述双线性插值的概念、原理...
采用国际标准测试图lena进行测试。...分别采用“基于像素放大原理的图像放大”、“基于双线性插原理的图像放大”两种方法进行图像分割。 并附有注释、程序清晰、易于阅读。 相信图像初学者阅读后必定会有很大的收益。
在FPGA开发中,双线性插值可以用来实现图像处理的基础功能。下面我们将详细介绍双线性插值的原理和FPGA实现方法。 双线性插值原理 双线性插值是通过包围当前目标像素点的4个像素点的数值,通过与当前像素点的相对...
双线性插值是一种在数字图像处理中广泛使用的插值方法,主要用于提高图像的分辨率或者进行缩放操作。在这个特定的工程中,我们看到的是一个使用FPGA(Field-Programmable Gate Array)实现的双线性插值的案例,采用...
本文将详细讨论两种常用的插值方法:最近邻插值和双线性插值,并通过MATLAB代码展示如何实现这两种插值方法来改变图像的大小。 1. 最近邻插值(Nearest Neighbour Interpolation) 最近邻插值是最简单的插值方法之...
双线性插值是一种在图像处理和计算机图形学中广泛使用的插值方法,用于在二维空间上进行数据点的估算。在FPGA(Field-Programmable Gate Array)上实现双线性插值,可以高效地进行像素级别的图像缩放或重采样,尤其...
由于双线性插值具有低通滤波器的性质,使高频分量受损,所以可能会使图像轮廓在一定程度上变得模糊 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ijong/archive/2010/06/16/5673593.aspx
双线性插值是一种在数字图像处理中广泛使用的算法,用于进行图像的放大或缩小操作。这种方法基于四个相邻像素的灰度值,通过线性插值计算出目标位置的新像素值,以达到平滑放大图像的效果,减少像素化现象。在CCS...
双线性插值是一种在数字图像处理中广泛使用的图像缩放技术,它的核心思想是通过在原图像像素之间进行线性插值来生成新的像素点,以实现图像的平滑放大或缩小。这种方法能有效提高图像缩放的质量,避免简单的最近邻...
当需要将图像放大或缩小时,双线性插值能够有效地填充新尺寸中的像素值,以达到平滑过渡的效果,减少像素化的现象。在这个场景中,我们看到一个用JAVA实现的双线性插值算法,用于图片的缩放功能。 首先,我们来理解...
与简单的最近邻插值或双线性插值相比,二次线性插值能提供更平滑且无锯齿的边缘效果,因为它考虑了四个最近像素的权重,而不是仅仅两个。这使得新生成的像素值更加接近原图像的真实值,从而提升图像质量。 在FPGA中...
MATLAB将bayer图像转化为彩色图像的双线性插值算法,适合于RGGB图像,这个可以与其它算法结合使用
双线性插值是一种在数字图像处理中广泛使用的插值方法,主要用于图像放大或缩小时保持图像质量。本文将深入探讨双线性插值的概念、原理以及如何利用VC++编程语言实现这一技术。 首先,我们要理解双线性插值的基本...
% 对下采样的图像进行双线性插值放大 interpolated_img = imresize(downsampled_img, [size(img,1) size(img,2)], 'bicubic'); % 'bicubic'表示双线性插值 % 计算PSNR psnr_value = psnr(img, interpolated_img)...
在图像处理领域,双线性插值是一种常用的方法,用于提高或降低图像的分辨率,即图像的放大与缩小。在MATLAB中,我们可以利用其强大的矩阵运算能力来实现这一过程。下面将详细介绍双线性插值法以及如何在MATLAB中进行...