算法思想:
基于双线性算法的分解,分别进行水平与垂直两个方向的放缩,完成对整张图像的放大或
者缩小。基于的数学思想为矩阵的乘法,对一个scale矩阵可以拆分为水平与垂直方向的两
个关联矩阵,具体如下:
关于什么是双线性插值参加这里:http://blog.csdn.net/jia20003/article/details/6915185
程序解释:
类ScaleFilter完成对图像的快速放大与缩小,接受输入参数为XY方向的放缩比例值。
hscal, vscale的默认值为1.5f即将输入图像在XY放大1.5倍。XY方向的Scale方法参考与运用
了移动窗口的算法。感兴趣可以自己研究,我也是改写一段c语言代码得到。感觉非常的精妙。
程序效果如下:
Scale Filter的源代码如下:
package com.gloomyfish.filter.study;
/**
* @author gloomyfish
* @date 2012-09-23
* @BLOGPAGE:http://blog.csdn.net/jia20003
*/
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
public class ScaleFilter extends AbstractBufferedImageOp {
/**
* default will zoom in 2.0 * input size of original image.
*/
private float hscale = 1.5f;
private float vscale = 1.5f;
public ScaleFilter() {
}
public void setHscale(float hscale) {
this.hscale = hscale;
}
public void setVscale(float vscale) {
this.vscale = vscale;
}
@Override
public BufferedImage filter(BufferedImage src, BufferedImage dest) {
int width = src.getWidth();
int height = src.getHeight();
if ( dest == null )
dest = createCompatibleDestImage( src, null );
// initialization pixel data
int[] inPixels = new int[width*height];
int outwidth = (int)(hscale * (float)width);
int outheight = (int)(vscale * (float)height);
int[] outhPixels = new int[outwidth*height];
int[] outPixels = new int[outwidth*outheight];
// start to zoom in/out here
getRGB( src, 0, 0, width, height, inPixels );
hscale(inPixels, outhPixels, width, height);
vscale(outhPixels, outPixels, outwidth, height);
// create buffered image and return it with result image data
setRGB( dest, 0, 0, outwidth, outheight, outPixels);
return dest;
}
public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
if ( dstCM == null )
dstCM = src.getColorModel();
int outwidth = (int)(hscale * (float)src.getWidth());
int outheight = (int)(vscale * (float)src.getHeight());
return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(outwidth, outheight), dstCM.isAlphaPremultiplied(), null);
}
private void hscale(int[] input, int[] output, int width, int height) {
int ta1 = 0, tr1 = 0, tg1 = 0, tb1 = 0;
int ta2 = 0, tr2 = 0, tg2 = 0, tb2 = 0;
int sumred = 0, sumgreen = 0, sumblue = 0;
double accred = 0, accgreen = 0, accblue = 0;
int p, q;
int outwidth = (int)(this.hscale * width);
double area = (outwidth * width);
int inCol = 0, outCol = 0;
int inIndex1 = 0, inIndex2 = 0, outIndex = 0;
for (int row = 0; row < height; row++) {
q = width;
p = outwidth;
accred = accgreen = accblue = 0;
inCol = outCol = 0;
while (outCol < outwidth) {
if(outCol == 299) {
System.out.println("what are you doing...");
}
if ((inCol + 1) < 2) {
inIndex1 = row * width + inCol;
inIndex2 = row * width + (inCol + 1);
ta1 = (input[inIndex1] >> 24) & 0xff;
tr1 = (input[inIndex1] >> 16) & 0xff;
tg1 = (input[inIndex1] >> 8) & 0xff;
tb1 = input[inIndex1] & 0xff;
ta2 = (input[inIndex2] >> 24) & 0xff;
tr2 = (input[inIndex2] >> 16) & 0xff;
tg2 = (input[inIndex2] >> 8) & 0xff;
tb2 = input[inIndex2] & 0xff;
sumred = p * tr1 + (outwidth - p) * tr2;
sumgreen = p * tg1 + (outwidth - p) * tg2;
sumblue = p * tb1 + (outwidth - p) * tb2;
}
else
{
inIndex1 = row * width + inCol;
ta1 = (input[inIndex1] >> 24) & 0xff;
tr1 = (input[inIndex1] >> 16) & 0xff;
tg1 = (input[inIndex1] >> 8) & 0xff;
tb1 = input[inIndex1] & 0xff;
sumred = outwidth * tr1;
sumgreen = outwidth * tg1;
sumblue = outwidth * tb1;
}
if (p < q) {
accred += sumred * p;
accgreen += sumgreen * p;
accblue += sumblue * p;
q -= p;
p = outwidth;
inCol++;
} else {
accred += sumred * q;
accgreen += sumgreen * q;
accblue += sumblue * q;
outIndex = row * outwidth + outCol;
output[outIndex] = ta1 << 24 | ((int)(accred / area) << 16) | ((int)(accgreen / area) << 8) | (int)(accblue / area);
accred = accgreen = accblue = 0;
p -= q;
q = width;
outCol++;
}
}
}
}
private void vscale(int[] input, int[] output, int width, int height) {
int ta1 = 0, tr1 = 0, tg1 = 0, tb1 = 0;
int ta2 = 0, tr2 = 0, tg2 = 0, tb2 = 0;
int sumred = 0, sumgreen = 0, sumblue = 0;
double accred = 0, accgreen = 0, accblue = 0;
int inRow = 0, outRow = 0;
int inIndex1 = 0, inIndex2 = 0, outIndex = 0;
int p, q;
int ih = height;
int oh = (int)(height * vscale);
int area = (ih * oh);
for (int col = 0; col < width; col++) {
q = ih;
p = oh;
accred = accgreen = accblue = 0;
inRow = outRow = 0;
while (outRow < oh) {
if (inRow+1 < ih) {
inIndex1 = inRow * width + col;
inIndex2 = (inRow+1) * width + col;
ta1 = (input[inIndex1] >> 24) & 0xff;
tr1 = (input[inIndex1] >> 16) & 0xff;
tg1 = (input[inIndex1] >> 8) & 0xff;
tb1 = input[inIndex1] & 0xff;
ta2 = (input[inIndex2] >> 24) & 0xff;
tr2 = (input[inIndex2] >> 16) & 0xff;
tg2 = (input[inIndex2] >> 8) & 0xff;
tb2 = input[inIndex2] & 0xff;
sumred = p * tr1 + (oh - p) * tr2;
sumgreen = p * tg1 + (oh - p) * tg2;
sumblue = p * tb1 + (oh - p) * tb2;
}
else
{
inIndex1 = inRow * width + col;
ta1 = (input[inIndex1] >> 24) & 0xff;
tr1 = (input[inIndex1] >> 16) & 0xff;
tg1 = (input[inIndex1] >> 8) & 0xff;
tb1 = input[inIndex1] & 0xff;
sumred = oh * tr1;
sumgreen = oh * tg1;
sumblue = oh * tb1;
}
if (p < q) {
accred += sumred * p;
accgreen += sumgreen * p;
accblue += sumblue * p;
q -= p;
p = oh;
inRow++;
} else {
accred += sumred * q;
accgreen += sumgreen * q;
accblue += sumblue * q;
outIndex = outRow * width + col;
output[outIndex] = ta1 << 24 | ((int)(accred / area) << 16) | ((int)(accgreen / area) << 8) | (int)(accblue / area);
accred = accgreen = accblue = 0;
p -= q;
q = ih;
outRow++;
}
}
}
}
}
后注:其效果近似与双线性内插值算法,但是运行速度却是它的几十倍之多,感兴趣者
可以自己测试。证明我没有信口开河。
分享到:
相关推荐
图像放缩,双线性内插值,这只是其中一种方法
对一副彩色图或者灰度图直接imread后就可以传入该双三次放缩函数了,函数的第二个参数和第三个参数为放缩后的h和w。函数返回放缩后的图像,可以直接imshow看结果。
对于想自己写算法缩放图像的童鞋比较有用,opencv神马的一般有现成函数的
使用VC中CImage在单文档的情况下实现图像的显示,放缩等功能,代码简单,易看懂,其中实现了双缓存!!
BMP旋转放缩(双线性插值,三次卷积插值)的c语言实现(含主程序可直接运行) 内含有使用说明书,代码清晰易懂。学习的好帮手,我就想要点下载积分/哭/哭/哭/哭
实验1 图像插值,图像几何变换:图像旋转、缩放 实验2 离散傅里叶变换和离散余弦变换 实验3 图像增强:局部对比度增强、USM滤镜功能实现、直方图均衡 实验4 图像复原 实验5 JPEG编解码方法设计与实现
函数的第一个参数为灰度图的文件路径,第二个参数和第三个参数为放缩后的h和w。运行函数即可查看结果。
具体讲解了双线性插值图像放大缩小算法,希望对大家有帮助
在VC++下实现加载图像,截取图像,插值放缩图像,获取像素坐标等
基于CImage图像基本处理,读写,放缩,旋转
主要讨论图像处理中的插值与检索算法,具体研究内容如下: (1)图像插值有着广泛的应用背景,被大量应用在图像的放缩、旋转等几何操作中。对于图像的放缩操作,较成熟的插值算法有最邻近插值、双线性插值以及样条插值等...
图像缩放模块-最大支持10放缩放 压缩包中包括缩放源码,仿真源码、仿真照片及照片、bin、txt装换工具,使用平台是xilinx
根据.raw文件还原了原始位图,并且用双线性插值法实现对位图的放缩,
用java1.6写的 基于双线性插值的图片缩放代码。另外还含有对于Ruge函数的拉格朗日插值算法
实现功能有:图像加运算、两种插值旋转、图像反色、图像放缩、二次曝光、扣去蓝色、 扣去绿色、图像线性增强、利用log函数实现增强、利用幂次函数实现增强、 直方图均衡化、算数均值滤波、中值滤波、拉普拉斯算子...
采用最临近 双线性 三次卷积插值三种技术方案对图像进行缩放
在图像处理中,插值算法可以用于图像的放缩和旋转等操作,以及图像的去噪和增强等处理。 ## 3. 优化算法 优化算法是一种用于寻找函数最小值或最大值的方法。在Matlab中,有许多种不同的优化算法可供选择,如梯度...
精通系列\精通Visual C++数字图像处理技术与工程案例\chap01\图像的缩放变换.rar
图像旋转、放缩、滤波、canny等等,MATLAB实现可运行,真的良心了,详解呀!!!
图像增广--仿射变换实现图像的平移 旋转 翻转 放缩 错切