- 浏览: 872382 次
文章分类
最新评论
-
angel6709:
怎么下载啊
Android 蓝牙开发实例--蓝牙聊天程序的设计和实现 -
再_见孙悟空:
能识别中文不?
借@阿里巴巴 耍了个帅——HTML5 JavaScript实现图片文字识别与提取 -
在下个路口:
连接时总是报Unable to start Service D ...
Android 蓝牙开发实例--蓝牙聊天程序的设计和实现 -
mike.liu:
如果在社会上,站在政府的立场思考问题,是会被人说5毛的。但是在 ...
项目预估激发的矛盾 -
kjmmlzq19851226:
我的意思是说,公司采取两种策略:
1. 每月4k的基本工资,另 ...
项目预估激发的矛盾
图像处理之高斯金字塔
一:图像金字塔基本操作
对一张图像不断的模糊之后向下采样,得到不同分辨率的图像,同时每次得到的
新的图像宽与高是原来图像的1/2, 最常见就是基于高斯的模糊之后采样,得到的
一系列图像称为高斯金字塔。
高斯金字塔不同(DoG)又称为拉普拉斯金字塔,其计算公式如下:
L(i) = G(i) – expand(G(i+1))
第i层拉普拉斯金字塔是由第i层高斯金字塔减去第i+1层高斯金字塔expand之后得到。
本文得到的DoG(Difference of Gaussian)结果如下:
二:关键代码解析
金字塔reduce操作实现代码如下:
private BufferedImage pyramidReduce(BufferedImage src) { int width = src.getWidth(); int height = src.getHeight(); BufferedImage dest = createSubCompatibleDestImage(src, null); int[] inPixels = new int[width*height]; int ow = width/2; int oh = height/2; int[] outPixels = new int[ow*oh]; getRGB(src, 0, 0, width, height, inPixels ); int inRow=0, inCol = 0, index = 0, oudex =0, ta = 0; float[][] keneralData = this.getHVGaussianKeneral(); for(int row=0; row<oh; row++) { for(int col=0; col<ow; col++) { inRow = 2* row; inCol = 2* col; if(inRow >= height) { inRow = 0; } if(inCol >= width) { inCol = 0; } float sumRed = 0, sumGreen = 0, sumBlue = 0; for(int subRow = -2; subRow <= 2; subRow++) { int inRowOff = inRow + subRow; if(inRowOff >= height || inRowOff < 0) { inRowOff = 0; } for(int subCol = -2; subCol <= 2; subCol++) { int inColOff = inCol + subCol; if(inColOff >= width || inColOff < 0) { inColOff = 0; } index = inRowOff * width + inColOff; ta = (inPixels[index] >> 24) & 0xff; int red = (inPixels[index] >> 16) & 0xff; int green = (inPixels[index] >> 8) & 0xff; int blue = inPixels[index] & 0xff; sumRed += keneralData[subRow + 2][subCol + 2] * red; sumGreen += keneralData[subRow + 2][subCol + 2] * green; sumBlue += keneralData[subRow + 2][subCol + 2] * blue; } } oudex = row * ow + col; outPixels[oudex] = (ta << 24) | (clamp(sumRed) << 16) | (clamp(sumGreen) << 8) | clamp(sumBlue); } } setRGB( dest, 0, 0, ow, oh, outPixels ); return dest; }金字塔expand实现代码如下:
public BufferedImage pyramidExpand(BufferedImage src) { int width = src.getWidth(); int height = src.getHeight(); int[] inPixels = new int[width*height]; getRGB(src, 0, 0, width, height, inPixels ); int ow = 2*width; int oh =2*height; int[] outPixels = new int[ow * oh]; int index = 0, outdex = 0, ta = 0; float[][] keneralData = this.getHVGaussianKeneral(); BufferedImage dest = createTwiceCompatibleDestImage(src, null); for(int row=0; row<oh; row++) { for(int col=0; col<ow; col++) { float sumRed = 0, sumGreen = 0, sumBlue = 0; for(int subRow = -2; subRow <= 2; subRow++) { double srcRow = (row + subRow)/2.0; double j = Math.floor(srcRow); double t = srcRow - j; if(t > 0) { continue; } if(srcRow >= height || srcRow < 0) { srcRow = 0; } for(int subCol = -2; subCol <= 2; subCol++) { double srcColOff = (col + subCol)/2.0; j = Math.floor(srcColOff); t = srcColOff - j; if(t > 0) { continue; } if(srcColOff >= width || srcColOff < 0) { srcColOff = 0; } index = (int)(srcRow * width + srcColOff); ta = (inPixels[index] >> 24) & 0xff; int red = (inPixels[index] >> 16) & 0xff; int green = (inPixels[index] >> 8) & 0xff; int blue = inPixels[index] & 0xff; sumRed += keneralData[subRow + 2][subCol + 2] * red; sumGreen += keneralData[subRow + 2][subCol + 2] * green; sumBlue += keneralData[subRow + 2][subCol + 2] * blue; } } outdex = row * ow + col; outPixels[outdex] = (ta << 24) | (clamp(4.0f * sumRed) << 16) | (clamp(4.0f * sumGreen) << 8) | clamp(4.0f * sumBlue); // outPixels[outdex] = (ta << 24) | (clamp(sumRed) << 16) | (clamp(sumGreen) << 8) | clamp(sumBlue); } } setRGB( dest, 0, 0, ow, oh, outPixels ); return dest; }图像金字塔的reduce与expand过程都是卷积采样实现。特别注意的是expand
操作不是reduce的可逆操作。
关于什么是卷积,高斯滤波请参见博客上的其它相关文章。
高斯金字塔全部算法源代码如下:
package com.gloomyfish.image.pyramid; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; public class PyramidAlgorithm extends GaussianFilter { private float a; public PyramidAlgorithm() { a = 0.4f; } public void setParameter(float p) { this.a = p; } public BufferedImage[] pyramidDown(BufferedImage src, int level) { BufferedImage[] imagePyramids = new BufferedImage[level + 1]; imagePyramids[0] = src; for(int i=1; i<imagePyramids.length; i++) { imagePyramids[i] = pyramidReduce(imagePyramids[i-1]); } return imagePyramids; } public BufferedImage[] pyramidUp(BufferedImage[] srcImage) { BufferedImage[] imagePyramids = new BufferedImage[srcImage.length]; for(int i=0; i<srcImage.length; i++) { imagePyramids[i] = pyramidExpand(srcImage[i]); } return imagePyramids; } /*** * l1 = g1 - expand(g2) * l2 = g2 - expand(g3) * l0 = g0 - expand(g1) * @param reduceImages * @param expandImages * @return */ public BufferedImage[] getLaplacianPyramid(BufferedImage[] reduceImages) { BufferedImage[] laplaciImages = new BufferedImage[reduceImages.length -1]; for(int i=1; i<reduceImages.length; i++) { BufferedImage expandImage = pyramidExpand(reduceImages[i]); laplaciImages[i-1] = createCompatibleDestImage(expandImage, null); int width = reduceImages[i-1].getWidth(); int height = reduceImages[i-1].getHeight(); int ewidth = expandImage.getWidth(); width = (width > ewidth) ? ewidth : width; height = (height > expandImage.getHeight()) ? expandImage.getHeight():height; System.out.println(" width = " + width + " expand width = " + ewidth); int[] reducePixels = new int[width*height]; int[] expandPixels = new int[width*height]; int[] laPixels = new int[width*height]; getRGB( reduceImages[i-1], 0, 0, width, height, reducePixels); getRGB( expandImage, 0, 0, width, height, expandPixels ); int index = 0; int er = 0, eg = 0, eb = 0; for(int row=0; row<height; row++) { int ta = 0, tr = 0, tg = 0, tb = 0; for(int col=0; col<width; col++) { index = row * width + col; ta = (reducePixels[index] >> 24) & 0xff; tr = (reducePixels[index] >> 16) & 0xff; tg = (reducePixels[index] >> 8) & 0xff; tb = reducePixels[index] & 0xff; ta = (expandPixels[index] >> 24) & 0xff; er = (expandPixels[index] >> 16) & 0xff; eg = (expandPixels[index] >> 8) & 0xff; eb = expandPixels[index] & 0xff; tr = tr - er; tg = tg - eg; tb = tb - eb; laPixels[index] = (ta << 24) | (clamp(tr) << 16) | (clamp(tg) << 8) | clamp(tb); } } setRGB( laplaciImages[i-1], 0, 0, width, height, laPixels ); } return laplaciImages; } private BufferedImage pyramidReduce(BufferedImage src) { int width = src.getWidth(); int height = src.getHeight(); BufferedImage dest = createSubCompatibleDestImage(src, null); int[] inPixels = new int[width*height]; int ow = width/2; int oh = height/2; int[] outPixels = new int[ow*oh]; getRGB(src, 0, 0, width, height, inPixels ); int inRow=0, inCol = 0, index = 0, oudex =0, ta = 0; float[][] keneralData = this.getHVGaussianKeneral(); for(int row=0; row<oh; row++) { for(int col=0; col<ow; col++) { inRow = 2* row; inCol = 2* col; if(inRow >= height) { inRow = 0; } if(inCol >= width) { inCol = 0; } float sumRed = 0, sumGreen = 0, sumBlue = 0; for(int subRow = -2; subRow <= 2; subRow++) { int inRowOff = inRow + subRow; if(inRowOff >= height || inRowOff < 0) { inRowOff = 0; } for(int subCol = -2; subCol <= 2; subCol++) { int inColOff = inCol + subCol; if(inColOff >= width || inColOff < 0) { inColOff = 0; } index = inRowOff * width + inColOff; ta = (inPixels[index] >> 24) & 0xff; int red = (inPixels[index] >> 16) & 0xff; int green = (inPixels[index] >> 8) & 0xff; int blue = inPixels[index] & 0xff; sumRed += keneralData[subRow + 2][subCol + 2] * red; sumGreen += keneralData[subRow + 2][subCol + 2] * green; sumBlue += keneralData[subRow + 2][subCol + 2] * blue; } } oudex = row * ow + col; outPixels[oudex] = (ta << 24) | (clamp(sumRed) << 16) | (clamp(sumGreen) << 8) | clamp(sumBlue); } } setRGB( dest, 0, 0, ow, oh, outPixels ); return dest; } public BufferedImage createSubCompatibleDestImage(BufferedImage src, ColorModel dstCM) { if ( dstCM == null ) dstCM = src.getColorModel(); return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth()/2, src.getHeight()/2), dstCM.isAlphaPremultiplied(), null); } public BufferedImage createTwiceCompatibleDestImage(BufferedImage src, ColorModel dstCM) { if ( dstCM == null ) dstCM = src.getColorModel(); return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth()*2, src.getHeight()*2), dstCM.isAlphaPremultiplied(), null); } public BufferedImage pyramidExpand(BufferedImage src) { int width = src.getWidth(); int height = src.getHeight(); int[] inPixels = new int[width*height]; getRGB(src, 0, 0, width, height, inPixels ); int ow = 2*width; int oh =2*height; int[] outPixels = new int[ow * oh]; int index = 0, outdex = 0, ta = 0; float[][] keneralData = this.getHVGaussianKeneral(); BufferedImage dest = createTwiceCompatibleDestImage(src, null); for(int row=0; row<oh; row++) { for(int col=0; col<ow; col++) { float sumRed = 0, sumGreen = 0, sumBlue = 0; for(int subRow = -2; subRow <= 2; subRow++) { double srcRow = (row + subRow)/2.0; double j = Math.floor(srcRow); double t = srcRow - j; if(t > 0) { continue; } if(srcRow >= height || srcRow < 0) { srcRow = 0; } for(int subCol = -2; subCol <= 2; subCol++) { double srcColOff = (col + subCol)/2.0; j = Math.floor(srcColOff); t = srcColOff - j; if(t > 0) { continue; } if(srcColOff >= width || srcColOff < 0) { srcColOff = 0; } index = (int)(srcRow * width + srcColOff); ta = (inPixels[index] >> 24) & 0xff; int red = (inPixels[index] >> 16) & 0xff; int green = (inPixels[index] >> 8) & 0xff; int blue = inPixels[index] & 0xff; sumRed += keneralData[subRow + 2][subCol + 2] * red; sumGreen += keneralData[subRow + 2][subCol + 2] * green; sumBlue += keneralData[subRow + 2][subCol + 2] * blue; } } outdex = row * ow + col; outPixels[outdex] = (ta << 24) | (clamp(4.0f * sumRed) << 16) | (clamp(4.0f * sumGreen) << 8) | clamp(4.0f * sumBlue); // outPixels[outdex] = (ta << 24) | (clamp(sumRed) << 16) | (clamp(sumGreen) << 8) | clamp(sumBlue); } } setRGB( dest, 0, 0, ow, oh, outPixels ); return dest; } }特别注意:我没有处理像素的宽与高,如果宽与高不是偶数可能
会有问题,使用时请自己处理吧。
UI实现源代码如下:
package com.gloomyfish.image.pyramid; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.MediaTracker; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JPanel; public class PyramidDemoUI extends JComponent implements ActionListener { /** * */ private static final long serialVersionUID = 1L; private JButton upButton; private JButton downButton; private BufferedImage[] reduceImages; private BufferedImage[] expandImages; private BufferedImage sourceImage; private Dimension mySize; private MediaTracker tracker; public PyramidDemoUI(File f) { initComponents(f); } private void initComponents(File f) { // TODO Auto-generated method stub try { sourceImage = ImageIO.read(f); } catch (IOException e1) { e1.printStackTrace(); } tracker = new MediaTracker(this); tracker.addImage(sourceImage, 1); // blocked 10 seconds to load the image data try { if (!tracker.waitForID(1, 10000)) { System.out.println("Load error."); System.exit(1); }// end if } catch (InterruptedException e) { e.printStackTrace(); System.exit(1); }// end catch JPanel btnPanel = new JPanel(); btnPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)); upButton = new JButton("Laplacian Pyramid"); downButton = new JButton("Pyramid Down"); upButton.addActionListener(this); downButton.addActionListener(this); btnPanel.add(upButton); btnPanel.add(downButton); mySize = new Dimension(800, 800); JFrame mainFrame = new JFrame("Pyramid Demo - Gloomyfish"); mainFrame.getContentPane().setLayout(new BorderLayout()); mainFrame.getContentPane().add(this, BorderLayout.CENTER); mainFrame.getContentPane().add(btnPanel, BorderLayout.SOUTH); mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); mainFrame.pack(); mainFrame.setVisible(true); } @Override public Dimension getPreferredSize() { return mySize; } @Override protected void paintComponent(Graphics g) { // g.drawImage(sourceImage, 10, 10, sourceImage.getWidth(), sourceImage.getHeight(), null); int width = 10; // if(reduceImages != null) { // for(int i=1; i<reduceImages.length; i++) { // width += (10 + reduceImages[i-1].getWidth()); // g.drawImage(reduceImages[i], width, 10, reduceImages[i].getWidth(), reduceImages[i].getHeight(), null); // } // } width = 10; if(expandImages != null) { for(int i=0; i<expandImages.length; i++) { g.drawImage(expandImages[i], width, 15, expandImages[i].getWidth(), expandImages[i].getHeight(), null); // g.drawImage(expandImages[i], width, 15 + sourceImage.getHeight(), expandImages[i].getWidth(), expandImages[i].getHeight(), null); width += (10 + expandImages[i].getWidth()); } } super.paintComponent(g); } public static void main(String[] args) { JFileChooser chooser = new JFileChooser(); chooser.showOpenDialog(null); File f = chooser.getSelectedFile(); new PyramidDemoUI(f); } @Override public void actionPerformed(ActionEvent event) { if(event.getActionCommand().equals("Laplacian Pyramid")) { if(reduceImages != null) { // int size = reduceImages.length; PyramidAlgorithm pyramid = new PyramidAlgorithm(); expandImages = pyramid.getLaplacianPyramid(reduceImages); // expandImages = pyramid.pyramidUp(reduceImages); repaint(); } else { } } else if(event.getActionCommand().equals("Pyramid Down")) { // a.Smooth the image with Gaussian filter 5×5(1/4-a/2, 1/4, a, 1/4, 1/4-a/2) a = [0.3,0.6] // b.Sub sample the image by half - 选择偶数行与列 // c.If reached desired size stop, else send the result to step 1 PyramidAlgorithm pyramid = new PyramidAlgorithm(); reduceImages = pyramid.pyramidDown(sourceImage, 3); repaint(); } else { // do nothing } } }转载请务必注明出处-GloomyFish
相关推荐
3D图像高斯金字塔处理方法,imGaussPyramid_3D.m。
原理:首先将原图像作为最底层图像G0(高斯金字塔的第0层),利用高斯核(5*5)对其进行卷积,然后对卷积后的图像进行下采样(去除偶数行和列)得到上一层图像G1,将此图像作为输入,重复卷积和下采样操作得到更上一层...
2D图像高斯金字塔处理方法, imGaussPyramid_2D.m。
图像处理的例子,关于飞机场飞机定位,通过GUI开发的界面,然后运行进行定位。
matlab高斯金字塔代码图像拼接 这是来自的项目。图像拼接是将一系列具有重叠字段的图像组合成诸如全景图的混合结果的过程。 该实现包括通过SIFT描述符进行特征点检测,通过KNN(来自)进行图像匹配,最后通过alpha...
多曝光融合,用高斯金字塔和拉普拉斯金字塔实现
典型的图像算法用到高斯金字塔的概率较大, 在构造高斯金字塔的过程中其中一个步骤就是进行高斯模糊,利用MATLAB实现一张图片的高斯模糊,仅仅通过修改尺度因子便能对图像进行不同程度的模糊
针对雾天图像存在信息丢失、区域不清晰以及雾气遮挡等问题,提出了一种基于双边滤波的高斯金字塔变换Retinex图像增强算法,以提高雾天图像的对比度。首先,基于空间域核函数和像素差,建立了改进的双边滤波函数数学模型...
我使用了 "imfilter" ,它是图像处理工具箱的一部分。 如果您没有图像处理工具箱,请将“imfilter”更改为“filter2”,该功能应该可以正常工作。
matlab高斯金字塔代码此存储库包含“计算机视觉”中使用的一些技术。 这些所有文件都是UIC的ECE ...高斯金字塔用于获取最终的平滑图像,而拉普拉斯金字塔有助于获取具有锐化边缘的图像。 HW5文件夹处理功能匹
计算机图象处理,图象压缩处理,图像压缩的几个MATLAB算法:分块编码、高斯金字塔、离散余弦变换、单值分解。
常见的图像金字塔有下面两种: •高斯金字塔(Gaussian pyramid): 用来向下采样 •拉普拉斯金字塔(Laplacian pyramid): 用来从金字塔低层图像重建上层未采样图像 高斯金字塔 类似金字塔一样,高斯金字塔从底层原始...
DOG高斯金字塔,用于图像处理的sift算法,surf算法等
%高斯金字塔分成两步: 一对图像做高斯平滑, 二向下采样 %以演示开始.后面是处理过程
C#数字图像处理算法典型实例随书光盘 精选数字图像处理领域中的一些应用实例,以理论和实践相结合的方式,系统地介绍了如何使用C#进行数字图像处理。 C#数字图像处理算法典型实例共11章,分别讲述了图像的点运算、...
数字图像处理实验三,具体可见博客https://blog.csdn.net/gyx1549624673/article/details/103808536。本次实验的目标是使用多...本次实验帮助学生掌握高斯金字塔、拉普拉斯金字塔以及多分辨率图像还原等技术处理过程。
matlab高斯金字塔代码模拟曝光融合(SEF) 八度/ Matlab实现的Simulated Exposure Fusion (单图像对比度增强算符)。 Charles Hessel CMLA,ENS巴黎萨克莱 此实现是IPOL出版物的一部分: 《模拟曝光融合》 ,查尔斯...
但是特别情况下我们需要对同一个图像的不同分辨率的子图像进行处理,如查找图像中的某个目标,如人脸,我们不知道目标在图像中的尺寸大小。高斯金字塔高斯金字塔的顶部是通
matlab高斯金字塔代码简单的Matlab图像处理应用程序(某些功能仍在进行中:) 以下存储库包含一个简单的图像处理应用程序,您可以使用gui_test2.m代码在Matlab上运行,并且gui_test2.fig中提供了相应的设计代码。 它...
slip图像翻转、高斯平滑、金字塔采样、人脸检测、图像旋转及按比例缩放、lbp、直方图均衡化