- 浏览: 63346 次
- 性别:
- 来自: 北京
文章分类
最新评论
图像的采样与量化及灰度直方图
图像的采样
采样是把空域上或时域上连续的图像(模拟图像)转换成离散采样点(像素)集合(数字图像)的操作。
采样越细,像素越小,越能精细地表现图像。不同采样间距的效果如下:
a.采样间隔16 b.采样间隔32 c.采样间隔64
图1
算法源代码1(java):
/** * 对图像进行采样 * @param pix 保存图片像素 * @param iw 二维像素矩阵的宽 * @param ih 二维像素矩阵的高 * @param grey 采样间距 * @return */ private static int[] sample(int[] pix, int iw, int ih, int grey) { //对图像进行采样 ColorModel cm = ColorModel.getRGBdefault(); int d = (int)(256/grey); //采样间隔 int dd = d*d; for(int i = 0; i < ih; i = i+d) { for(int j = 0; j < iw; j = j+d) { int r = 0, g = 0, b = 0; for(int k = 0; k < d; k++) for(int l = 0; l < d; l++) r = r + cm.getRed(pix[(i+k)*iw+(j+l)]); for(int k = 0; k < d; k++) for(int l = 0; l < d; l++) g = g + cm.getGreen(pix[(i+k)*iw+(j+l)]); for(int k = 0; k < d; k++) for(int l = 0; l < d; l++) b = b + cm.getBlue(pix[(i+k)*iw+(j+l)]); r = (int)(r/dd); g = (int)(g/dd); b = (int)(b/dd); for(int k = 0; k < d; k++) for(int l = 0; l < d; l++) // pix[(i+k)*iw+(j+l)] = 255<<24|r<<16|g<<8|b; pix[(i+k)*iw+(j+l)] = new Color(r, g, b).getRGB(); } } return pix; } /** * 对图像进行采样 * @param srcPath 原图像文件路径 * @param distPath 目标图像文件路径 * @param grey 采样的间隔 */ public static void sampleImage(String srcPath, String distPath, int grey) { OutputStream out = null; try { BufferedImage img = ImageIO.read(new File(srcPath)); int imgType = img.getType(); int w = img.getWidth(); int h = img.getHeight(); int[] pix = new int[w*h]; pix = img.getRGB(0, 0, w, h, pix, 0, w); int[] newpix = sample(pix, w, h, grey); out = new FileOutputStream(distPath); BufferedImage imgOut = new BufferedImage( w, h, imgType); imgOut.setRGB(0, 0, w, h, newpix, 0, w); ImageIO.write(imgOut, "jpg", out); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { out.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
图像的量化
量化是把像素的灰度(浓淡)变换成离散的整数值的操作。最简单的量化是用黑(0)白(255)两个数值(即2级)来表示,成为二值图像。
量化越细致,灰度级数(浓淡层次)表现越丰富。计算机中一般用8bit(256级)来量化,这意味着像素的灰度(浓淡)是0—255之间的数值。化级数的效果图如下:
a.量化级数2 b.量化级数8 c.量化级数64
图2
算法源代码2(java):
/** * 对图像进行量化 * @param srcPath 原图像文件路径 * @param distPath 目标图像文件路径 * @param grey 量化的级数 */ public static void quantize(String srcPath, String distPath, int grey) { OutputStream out = null; try { BufferedImage img = ImageIO.read(new File(srcPath)); int imgType = img.getType(); int w = img.getWidth(); int h = img.getHeight(); int pix[] = new int[w*h]; img.getRGB(0, 0, w, h, pix, 0, w); int greyScope = 256/grey; int r,g,b,temp; r=b=g=temp=0; ColorModel cm=ColorModel.getRGBdefault(); for(int i=0; i<w*h; i++) { r = cm.getRed(pix[i]); temp = r/greyScope; r = temp*greyScope; g = cm.getGreen(pix[i]); temp = g/greyScope; g = temp*greyScope; b = cm.getBlue(pix[i]); temp = b/greyScope; b = temp*greyScope; pix[i] = new Color(r, g, b).getRGB(); } out = new FileOutputStream(distPath); BufferedImage imgOut = new BufferedImage(w, h, imgType); imgOut.setRGB(0, 0, w, h, pix, 0, w); ImageIO.write(imgOut, "jpg", out); System.out.println("test"); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { out.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
图像直方图
直方图的定义
灰度直方图(histogram)是灰度级分布的函数,它表示图象中具有每种灰度级的象素的个数,反映图象中每种灰度出现的频率。灰度直方图的横坐标是灰度级,纵坐标是该灰度级出现的频率,是图象的最基本的统计特征。
生成图像灰度直方图的一般步骤:
1、统计各个灰度值的像素个数;
2、根据统计表画出直方图
如下图
图3
图4
算法源代码3:见下面算法源代码4中的drawHistogram()方法
灰度直方图的性质
1、只反映该图像中不同灰度值出现的次数(或频率),而不能反映某一灰度值像素所在的位置;
2、任何一张图像能唯一地确定一个与它对应的直方图,而一个直方图可以有多个不同的图像;
3、如果一张图片被剪裁成多张图片,各个子图的直方图之和就是这个全图的直方图。
直方图的用途
直方图有很多的用途,比如阀值分割,图像增强,还常常用于医疗影像。
图像的阀值(二值)处理
阀值处理的定义
图像的阀值处理是将图像的像素灰度值在某个定值(设为t)以上的点赋值为白色(或黑色),在这个定值t以下的点赋值为黑色(或白色)的处理过程。用公式表示成:
由于图像的阀值处理得到的是只有两个灰度值的二值图像,所以也将阀值处理称作二值化处理,得到的图像叫二值图像。如下图
图像阀值处理的步骤
1、画出图像的灰度直方图;
2、根据图像的灰度直方图确定阀值t,如图5的阀值为65;
3、将像素灰度值小于等于t的点赋值为白色(或黑色),大于t的点赋值为黑色(或白色);效果如图6:
图5
图6
算法源代码4(java):
package cn.edu.jxau.luoweifu; import java.awt.BorderLayout; import java.awt.Canvas; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.FileDialog; import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.image.BufferedImage; import java.awt.image.ColorModel; import java.io.File; import java.io.IOException; import java.util.Date; import javax.imageio.ImageIO; import javax.swing.BoxLayout; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JSlider; import javax.swing.border.LineBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; /** * 设置头像 * @author 罗伟富 * */ public class Histogram extends JFrame implements ChangeListener, ActionListener{ /** * 头像界面的宽度 */ public static final int WIDTH = 680; /** * 头像界面的高度 */ public static final int HEIGHT = 400; /** * 显示图片版面的宽度 */ public static final int PWIDTH = 350; /** * 显示图片版面的高度 */ public static final int PHEIGHT = 300; /** * 直方图版面的宽度 */ public static final int H_WIDTH = 350; /** * 直方图片版面的高度 */ public static final int H_HEIGHT = 300; /** * 滑块的最大值 */ public static final int JS_MAXIMUM = 100; public static final String FRAMTITLE = "图像的灰度直方图"; private String imgSrc; Image img; JSlider jsliderH, jsliderV; //水平和垂直滑块 JPanel uP, picP, uplodP, histP; JButton openFile, histogram, threshold; MyCanvas canvas; Canvas histCanvas; int imgW = PWIDTH, imgH = PHEIGHT; int xcentre = PWIDTH/2, ycentre = PHEIGHT/2; private int dx1 = xcentre-imgW/2, dy1 = ycentre-imgH/2, dx2 = xcentre + imgW/2, dy2 = ycentre + imgH/2; private int sx1 = 0, sy1 = 0, sx2, sy2; private float shx = 0, shy = 0; /** * 构造函数 */ public Histogram() { setTitle(FRAMTITLE); launchDialog(); } /** * 返回canvas * @return */ public Canvas getCanvas() { return canvas; } /** * 界面设计 */ private void launchDialog() { //初始化图片对象 imgSrc = "F:\\image processing\\baboom2_gray.jpg"; img = Toolkit.getDefaultToolkit().getImage(imgSrc); //初始化组件 canvas = new MyCanvas(); jsliderH = new JSlider(); jsliderH.setMaximum(JS_MAXIMUM); jsliderH.setValue(JS_MAXIMUM/2); jsliderH.setMinimum(1); jsliderH.setOrientation(JSlider.HORIZONTAL); jsliderH.addChangeListener(this); jsliderV = new JSlider(); jsliderV.setMaximum(JS_MAXIMUM); jsliderV.setValue(JS_MAXIMUM/2); jsliderV.setMinimum(1); jsliderV.setOrientation(JSlider.VERTICAL); jsliderV.addChangeListener(this); picP = new JPanel(); picP.setPreferredSize(new Dimension(PWIDTH, PHEIGHT)); //picP.setBackground(Color.green); uP = new JPanel(); uplodP = new JPanel(); openFile = new JButton("打开图片"); histogram = new JButton("显示直方图"); threshold = new JButton("显示二值图像"); openFile.addActionListener(this); histogram.addActionListener(this); threshold.addActionListener(this); //添加组件 picP.setLayout(new BorderLayout()); picP.add(canvas, BorderLayout.CENTER); uP.setLayout(new BorderLayout()); uP.add(picP, BorderLayout.CENTER); uP.add(jsliderH, BorderLayout.SOUTH); uP.add(jsliderV, BorderLayout.EAST); histCanvas = new Canvas(); histP = new JPanel(new BorderLayout()); histP.add(histCanvas); histP.setPreferredSize(new Dimension(H_WIDTH, H_HEIGHT)); histP.setBorder(new LineBorder(Color.blue)); //System.out.println("w:" + histP.getWidth() + " h:" + histP.getHeight() + " " + histP.HEIGHT); uplodP.setLayout(new FlowLayout()); uplodP.add(openFile); uplodP.add(histogram); uplodP.add(threshold); Container c = getContentPane(); c.setLayout(new BoxLayout(c, BoxLayout.Y_AXIS)); //c.add(uP); JPanel p = new JPanel(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); p.add(uP); p.add(histP); c.add(p); c.add(uplodP); setSize(WIDTH, HEIGHT); setResizable(false); setLocationRelativeTo(null); setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); setVisible(true); } public void drawHistogram() { try { BufferedImage bfImg = ImageIO.read(new File(imgSrc)); int w = bfImg.getWidth(); int h = bfImg.getHeight(); int pix[] = new int[w*h]; int hist[] = new int[256]; /*for(int i=0; i<hist.length; i++) { hist[i] = 0; }*/ int imgType = bfImg.getType(); int temp; bfImg.getRGB(0, 0, w, h, pix, 0, w); ColorModel cm = ColorModel.getRGBdefault(); for(int i=0; i<pix.length; i++) { /*for(int j=0; j<hist.length; j++) { if(j == cm.getRed(pix[i])) { hist[j] ++; } }*/ temp = cm.getRed(pix[i]); hist[temp] ++; } //System.out.println(hist.length); int max = 0; for(int i=0; i<hist.length; i++) { if(hist[i] > max) { max = hist[i]; } } for(int i=0; i<hist.length; i++) { hist[i] = (int)(hist[i]/(float)max * 250); /*System.out.print(hist[i] + "\t"); if(i%10 == 0) { System.out.println(); }*/ } //histCanvas.setHistPix(hist); //histCanvas.repaint(); Graphics g = histCanvas.getGraphics(); Color c = g.getColor(); g.setColor(Color.red); g.drawLine(10, H_HEIGHT-10, H_WIDTH-30, H_HEIGHT-10); g.drawLine(H_WIDTH-35, H_HEIGHT-15, H_WIDTH-30, H_HEIGHT-10); g.drawLine(H_WIDTH-35, H_HEIGHT-5, H_WIDTH-30, H_HEIGHT-10); g.drawString("灰度级", H_WIDTH-80, H_HEIGHT); g.drawLine(10, H_HEIGHT-10, 10, 10); g.drawLine(5, 15, 10, 10); g.drawLine(15, 15, 10, 10); g.drawString("像素个数", 15, 15); g.setColor(Color.black); for(int i=0; i<hist.length; i++) { g.drawLine(10+i, H_HEIGHT-10, 10+i, H_HEIGHT-10-hist[i]); if(i%30 == 0) { g.drawString(i+"", 10+i, H_HEIGHT); } } g.setColor(c); } catch (IOException e) { e.printStackTrace(); } } public void threshold(int threshold) { try { BufferedImage bfImg = ImageIO.read(new File(imgSrc)); int w = bfImg.getWidth(); int h = bfImg.getHeight(); int pix[] = new int[w*h]; int imgType = bfImg.getType(); bfImg.getRGB(0, 0, w, h, pix, 0, w); int max = 0; ColorModel cm = ColorModel.getRGBdefault(); for(int i=0; i<pix.length; i++) { if(cm.getRed(pix[i]) <= threshold) { pix[i] = new Color(255,255,255).getRGB(); } else { pix[i] = new Color(0, 0, 0).getRGB(); } } bfImg.setRGB(0, 0, w, h, pix, 0, w); //histCanvas.setHistPix(hist); //histCanvas.repaint(); Graphics g = histCanvas.getGraphics(); g.clearRect(0, 0, H_WIDTH, H_HEIGHT); Color c = g.getColor(); g.drawImage(bfImg, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, this); g.setColor(c); } catch (IOException e) { e.printStackTrace(); } } /** * 事件监听响应 */ public void actionPerformed(ActionEvent e) { if(e.getSource() == openFile) { FileDialog openFileDialog = new FileDialog(this, "打开图片"); openFileDialog.setMode(FileDialog.LOAD); //设置此对话框为从文件加载内容 openFileDialog.setFile("*.jpg;*.jpeg;*.gif;*.png;*.bmp;*.tif;"); //设置可打开文件的类型为:.txt,.java openFileDialog.setVisible(true); String fileName = openFileDialog.getFile(); String directory = openFileDialog.getDirectory(); if(null != fileName) { imgSrc = directory + fileName; img = Toolkit.getDefaultToolkit().getImage(imgSrc); histCanvas.repaint(); } else { JOptionPane.showMessageDialog(this, "您已经取消选择了,请重新选择!"); } } else if(e.getSource() == histogram) { System.out.println(new Date()); drawHistogram(); System.out.println(new Date()); } else if(e.getSource() == threshold) { threshold(65); } } /** * 滑动条滑动响应事件 */ public void stateChanged(ChangeEvent e) { if(e.getSource() == jsliderH) { float valueH = jsliderH.getValue(); imgW = (int)(2*PWIDTH*(valueH/JS_MAXIMUM)); if(imgW < PWIDTH/4) { imgW = PWIDTH/4; } dx1 = xcentre-imgW/2; dy1 = ycentre-imgH/2; dx2 = xcentre + imgW/2; dy2 = ycentre + imgH/2; canvas.repaint(); } else if(e.getSource() == jsliderV) { float valueV = jsliderV.getValue(); imgH = (int)(2*PHEIGHT*(valueV/JS_MAXIMUM)); if(imgH < PHEIGHT/4) { imgH = PHEIGHT/4; } dx1 = xcentre-imgW/2; dy1 = ycentre-imgH/2; dx2 = xcentre + imgW/2; dy2 = ycentre + imgH/2; canvas.repaint(); } } public static void main(String[] args) { new Histogram(); } /** * 用于画图像的Canvas */ class MyCanvas extends Canvas { public MyCanvas() { } public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; //g.drawImage(img, xcentre-imgW/2, ycentre-imgH/2, imgW, imgH, this); sx2 = img.getWidth(this); sy2 = img.getHeight(this); g2.shear(shx, shy); g2.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, this);//Color.green, } } } /*class HistCanvas extends Canvas { int histPix[] = new int[0]; public void setHistPix(int[] pix) { histPix = pix; } public void paint(Graphics g) { Color c = g.getColor(); g.setColor(Color.red); g.drawLine(10, H_HEIGHT-10, H_WIDTH-30, H_HEIGHT-10); g.drawLine(H_WIDTH-35, H_HEIGHT-15, H_WIDTH-30, H_HEIGHT-10); g.drawLine(H_WIDTH-35, H_HEIGHT-5, H_WIDTH-30, H_HEIGHT-10); g.drawString("灰度级", H_WIDTH-80, H_HEIGHT); g.drawLine(10, H_HEIGHT-10, 10, 10); g.drawLine(5, 15, 10, 10); g.drawLine(15, 15, 10, 10); g.drawString("像素个数", 15, 15); g.setColor(Color.black); for(int i=0; i<histPix.length; i++) { g.drawLine(10+i, H_HEIGHT-10, 10+i, H_HEIGHT-10-histPix[i]); if(i%30 == 0) { g.drawString(i+"", 10+i, H_HEIGHT); } } g.setColor(c); } }*/
相关推荐
C++、MFC制作的图像处理工具,包括图像灰度、采样、量化、灰度直方图、灰度线性变化、灰度非线性变化、阈值化、均衡化处理等。_2025
四.MFC对话框绘制灰度直方图,博客地址http://blog.csdn.net/eastmount/article/details/46237463 讲述VC++ 6.0关于数字图像处理的灰度直方图(中值灰度、平均灰度)、灰度、采样、量化处理,处理的是BMP图片,详细...
4. **量化和采样**:灰度直方图可用于确定图像的量化级别,以便进行灰度级的压缩或扩展。 在实验过程中,针对不同类型的图像,如RGB图像和索引图像,处理步骤有所不同。对于RGB图像,首先使用`rgb2gray`函数将其...
3. **直方图分析**:通过比较量化前后图像的灰度直方图来评估图像的细节保留程度。 #### 五、总结 本案例通过Matlab程序实现了对图像量化效果的直观判断。通过对原始图像和量化后图像的直方图进行比较,可以初步...
这种方法称为直方图均衡化的灰度转换,可以增强图像的对比度。 2. **采样**: 采样是数字图像处理的基础,根据奈奎斯特定理,采样频率至少应为原始信号最高频率的两倍,以避免失真。在图像处理中,采样通常涉及到...
该ppt 讲了数字图像处理中的数字化采样及量化,一级灰度直方图的绘制.
总的来说,本教程将引导读者深入了解图像处理的基本原理,包括数字图像的表示、采样、量化以及灰度直方图的计算和应用。通过学习这些基础知识,读者将具备处理和分析数字图像的能力,为进一步探索图像处理的高级技术...
13. 灰度直方图与图像面积:直方图按横轴积分可得图像的像素总数,而非面积。 14. 灰度直方图双峰性:双峰可能对应前景和背景,但最优二值化不一定位于两个峰值之间。 15. 图像二值化:将图像转换为只有两种灰阶的...
综上所述,数字图像处理技术的核心是将连续的图像转换为数字形式,这涉及到图像的分类、数字化过程(采样和量化)以及对图像特征的统计分析(如直方图)。这些概念和技术广泛应用于图像压缩、图像分析、机器学习和...
在数字图像处理实验中,我们可以使用MATLAB来实现各种图像处理算法,例如灰度退、均衡化、边缘检测、灰度直方图、图像增强、伪彩色、DCT变换等。 1. 灰度退 灰度退是指将彩色图像转换为灰度图像的过程。灰度值即...
灰度直方图的性质包括不表示图像的空间信息、任一特定图像都有唯一直方图、归一化灰度直方图和面积函数可得到图像的概率密度函数PDF和累积分布函数CDF、直方图的可相加性等。 点运算是指对一幅输入图像,将产生一幅...
本资源总结了数字图像处理的基础知识点,涵盖了图像的定义、分类、处理三个层次、五个模块、数字图像的表示、采样、量化、灰度直方图、图像处理的基本功能形式、邻域、图像处理算法、图像的数据结构与特征、图像特征...
总的来说,这一章深入浅出地阐述了数字图像处理的基础,包括信号的采样和量化原理,以及如何通过灰度直方图分析图像的特性。这些知识是理解和应用数字图像处理技术的关键,对于学习者来说是不可或缺的基础。
灰度直方图的性质包括不表示图像的空间信息、任一特定图像都有唯一直方图、归一化灰度直方图和面积函数可得到图像的概率密度函数PDF和累积分布函数CDF等。 四、点运算 点运算是指对于一幅输入图像,将产生一幅输出...
《贾永红-数字图像处理--chap2》的讲解涵盖了图像处理的重要概念和技术,主要分为四个部分:图像数字化、图像灰度直方图、数字图像处理算法与数据结构以及图像文件格式。这些知识点在信息技术领域,尤其是图像处理和...
* 灰度直方图的性质包括不表示图像的空间信息、任一特定图像都有唯一直方图、归一化灰度直方图和面积函数可得到图像的概率密度函数 PDF 和累积分布函数 CDF 等。 四、点运算 * 点运算是指对于一幅输入图像,将产生...
* 灰度直方图可以用于判断图像量化是否恰当、确定图像二值化的阈值、计算图像中物体的面积和计算图像信息量等。 十、图像处理的基本功能形式 * 单幅图像→单幅图像 * 多幅图像→单幅图像 * 单(或多)幅图像→数字...
数字图像处理(MATLAB) ...图像的灰度变换与直方图修正 二、实验目的 1.熟悉MATLAB软件的使用。 2.掌握灰度变换、直方图修正的原理及数学运算。 3.于MATLAB环境下编程实现对图片的灰度变换和直方图修正。 三、实验