博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
三种常见的图像处理双三次插值算法
阅读量:4676 次
发布时间:2019-06-09

本文共 6677 字,大约阅读时间需要 22 分钟。

三种常见的图像处理双三次插值算法

双立方插值计算涉及16像素,间(i’, j’)像中的包括

小数部分的像素坐标。dx表示X方向的小数坐标。dy表示Y方向的小数坐标。

详细

能够看下图:

依据上述图示与双立方插值的数学表达式能够看出。双立方插值本质上图像16个像素点

权重卷积之和作为新的像素值。

当中R(x)表示插值表达式,能够依据须要选择的表达式不同。常见有基于三角取值、Bell

分布表达、B样条曲线表达式。

1. 基于三角形採样数学公式为

最简单的线性分布,代码实现例如以下:

private double triangleInterpolation( double f ){	f = f / 2.0;	if( f < 0.0 )	{		return ( f + 1.0 );	}	else	{		return ( 1.0 - f );	}}
2.基于Bell分布採样的数学公式例如以下:

Bell分布採样数学公式基于三次卷积计算实现。代码实现例如以下:

private double bellInterpolation( double x ){	double f = ( x / 2.0 ) * 1.5;	if( f > -1.5 && f < -0.5 )	{		return( 0.5 * Math.pow(f + 1.5, 2.0));	}	else if( f > -0.5 && f < 0.5 )	{		return 3.0 / 4.0 - ( f * f );	}	else if( ( f > 0.5 && f < 1.5 ) )	{		return( 0.5 * Math.pow(f - 1.5, 2.0));	}	return 0.0;}
3.基于B样条曲线採样的数学公式例如以下:

是一种基于多项式的四次卷积的採样计算,代码例如以下:

private double bspLineInterpolation( double f ){	if( f < 0.0 )	{		f = -f;	}	if( f >= 0.0 && f <= 1.0 )	{		return ( 2.0 / 3.0 ) + ( 0.5 ) * ( f* f * f ) - (f*f);	}	else if( f > 1.0 && f <= 2.0 )	{		return 1.0 / 6.0 * Math.pow( ( 2.0 - f  ), 3.0 );	}	return 1.0;}
实现图像双立方插值的完整源码例如以下:

package com.gloomyfish.zoom.study;import java.awt.image.BufferedImage;import java.awt.image.ColorModel;import com.gloomyfish.filter.study.AbstractBufferedImageOp;public class BicubicInterpolationFilter extends AbstractBufferedImageOp  {	public final static int TRIANGLE__INTERPOLATION = 1;	public final static int BELL__INTERPOLATION = 2;	public final static int BSPLINE__INTERPOLATION = 4;	public final static int CATMULLROOM__INTERPOLATION = 8;    public final static double B = 0.0;    public final static double C = 0.5; // constant	private int destH; // zoom height	private int destW; // zoom width	private int type;	public BicubicInterpolationFilter()	{		this.type = BSPLINE__INTERPOLATION;	}	public void setType(int type) {		this.type = type;	}	public void setDestHeight(int destH) {		this.destH = destH;	}	public void setDestWidth(int destW) {		this.destW = destW;	}		private double bellInterpolation( double x )	{		double f = ( x / 2.0 ) * 1.5;		if( f > -1.5 && f < -0.5 )		{			return( 0.5 * Math.pow(f + 1.5, 2.0));		}		else if( f > -0.5 && f < 0.5 )		{			return 3.0 / 4.0 - ( f * f );		}		else if( ( f > 0.5 && f < 1.5 ) )		{			return( 0.5 * Math.pow(f - 1.5, 2.0));		}		return 0.0;	}		private double bspLineInterpolation( double f )	{		if( f < 0.0 )		{			f = -f;		}		if( f >= 0.0 && f <= 1.0 )		{			return ( 2.0 / 3.0 ) + ( 0.5 ) * ( f* f * f ) - (f*f);		}		else if( f > 1.0 && f <= 2.0 )		{			return 1.0 / 6.0 * Math.pow( ( 2.0 - f  ), 3.0 );		}		return 1.0;	}		private double triangleInterpolation( double f )	{		f = f / 2.0;		if( f < 0.0 )		{			return ( f + 1.0 );		}		else		{			return ( 1.0 - f );		}	}		private double CatMullRomInterpolation( double f )	{	    if( f < 0.0 )	    {	        f = Math.abs(f);	    }	    if( f < 1.0 )	    {	        return ( ( 12 - 9 * B - 6 * C ) * ( f * f * f ) +	            ( -18 + 12 * B + 6 *C ) * ( f * f ) +	            ( 6 - 2 * B ) ) / 6.0;	    }	    else if( f >= 1.0 && f < 2.0 )	    {	        return ( ( -B - 6 * C ) * ( f * f * f )	            + ( 6 * B + 30 * C ) * ( f *f ) +	            ( - ( 12 * B ) - 48 * C  ) * f +	            8 * B + 24 * C)/ 6.0;	    }	    else	    {	        return 0.0;	    }	} 	@Override	public BufferedImage filter(BufferedImage src, BufferedImage dest) {		int width = src.getWidth();		int height = src.getHeight();		if (dest == null)			dest = createCompatibleDestImage(src, null);		int[] inPixels = new int[width * height];		int[] outPixels = new int[destH * destW];		getRGB(src, 0, 0, width, height, inPixels);		float rowRatio = ((float) height) / ((float) destH);		float colRatio = ((float) width) / ((float) destW);		int index = 0;		for (int row = 0; row < destH; row++) {			int ta = 0, tr = 0, tg = 0, tb = 0;			double srcRow = ((float) row) * rowRatio;			// 获取整数部分坐标 row Index			double j = Math.floor(srcRow);			// 获取行的小数部分坐标			double t = srcRow - j;			for (int col = 0; col < destW; col++) {				double srcCol = ((float) col) * colRatio;				// 获取整数部分坐标 column Index				double k = Math.floor(srcCol);				// 获取列的小数部分坐标				double u = srcCol - k;				double[] rgbData = new double[3];				double rgbCoffeData = 0.0;				for(int m=-1; m<3; m++)				{					for(int n=-1; n<3; n++)					{						int[] rgb = getPixel(j+m, k+n, width, height, inPixels);						double f1 = 0.0d;						double f2 = 0.0d;						if(type == TRIANGLE__INTERPOLATION)						{							f1  = triangleInterpolation( ((double) m ) - t );							f2 = triangleInterpolation ( -(( (double) n ) - u ) );							}						else if(type == BELL__INTERPOLATION)						{							f1  = bellInterpolation( ((double) m ) - t );							f2 = bellInterpolation ( -(( (double) n ) - u ) );							}						else if(type == BSPLINE__INTERPOLATION)						{							f1  = bspLineInterpolation( ((double) m ) - t );							f2 = bspLineInterpolation ( -(( (double) n ) - u ) );							}						else						{							f1  = CatMullRomInterpolation( ((double) m ) - t );							f2 = CatMullRomInterpolation ( -(( (double) n ) - u ) );													}						// sum of weight						rgbCoffeData += f2*f1;						// sum of the RGB values						rgbData[0] += rgb[0] * f2 * f1;						rgbData[1] += rgb[1] * f2 * f1;						rgbData[2] += rgb[2] * f2 * f1;					}				}				ta = 255;				// get Red/green/blue value for sample pixel				tr = (int) (rgbData[0]/rgbCoffeData);				tg = (int) (rgbData[1]/rgbCoffeData);				tb = (int) (rgbData[2]/rgbCoffeData);				index = row * destW + col;				outPixels[index] = (ta << 24) | (clamp(tr) << 16)						| (clamp(tg) << 8) | clamp(tb);			}		}		setRGB(dest, 0, 0, destW, destH, outPixels);		return dest;	}		public int clamp(int value) {		return value > 255 ? 255 :			(value < 0 ? 0 : value);	}		private int[] getPixel(double j, double k, int width, int height,			int[] inPixels) {		int row = (int) j;		int col = (int) k;		if (row >= height) {			row = height - 1;		}		if (row < 0) {			row = 0;		}		if (col < 0) {			col = 0;		}		if (col >= width) {			col = width - 1;		}		int index = row * width + col;		int[] rgb = new int[3];		rgb[0] = (inPixels[index] >> 16) & 0xff;		rgb[1] = (inPixels[index] >> 8) & 0xff;		rgb[2] = inPixels[index] & 0xff;		return rgb;	}	public BufferedImage createCompatibleDestImage(			BufferedImage src, ColorModel dstCM) {        if ( dstCM == null )            dstCM = src.getColorModel();        return new BufferedImage(dstCM,         		dstCM.createCompatibleWritableRaster(destW, destH),         		dstCM.isAlphaPremultiplied(), null);    }}
执行效果:原图

双立方插值放大以后:

总结:

基于这里三种方法实现的双立方插值以后图片跟原图像相比,都有一定模糊

这里时候能够通过兴许处理实现图像锐化与对照度提升就可以得到Sharpen版本号

当然也能够通过寻找更加合适的R(x)函数来实现双立方卷积插值过程时保留

图像边缘与对照度。

一定要包括转载

版权声明:本文博主原创文章。博客,未经同意不得转载。

转载于:https://www.cnblogs.com/blfshiye/p/4823027.html

你可能感兴趣的文章
Remove Mapping
查看>>
NSLog打印信息的从新设置
查看>>
关于TCP/IP与数据传输
查看>>
用Python监视进程是否结束
查看>>
[转] 对WM_NCHITTEST消息的了解+代码实例进行演示
查看>>
方程整数解-2015省赛C语言A组第一题
查看>>
flask环境配置
查看>>
WEB应用的安全的登录认证
查看>>
C#网络编程.套接字.TcpListener.TcpClient
查看>>
Day3 02判定两个对象的引用是否相同
查看>>
极光推送
查看>>
PCB MongoDB 监控
查看>>
springmvc接收JSON类型的数据
查看>>
mybatis配置文件详解
查看>>
Objective-C plist文件与KVC 的使用
查看>>
jqGrid(2)
查看>>
杂题 UVAoj 107 The Cat in the Hat
查看>>
关于jquery-weui.js中时间控件datetimepicker的使用
查看>>
单页面应用程序(SPA)的优缺点
查看>>
http请求和http响应详细解析
查看>>