画像のサンプリングと量子化と階調ヒストグラム
10785 ワード
画像のサンプリング
サンプリングは、空域または時間領域に連続した画像(アナログ画像)を離散サンプリングポイント(画素)集合(デジタル画像)に変換する動作である.
サンプリングが細ければ細いほど、画素が小さくなり、画像を細かく表現することができます.異なるサンプリング間隔の効果は次のとおりです.
a.サンプリング間隔16 b.サンプリング間隔32 c.サンプリング間隔64
図1
アルゴリズムソース1(java):
画像の量子化
量子化は画素の階調(濃淡)を離散した整数値に変換する操作であり、最も簡単な量子化は黒(0)白(255)の2つの数値(すなわち2段)で表され、2値画像となる.
量子化が細かいほど階調数(濃淡階層)が豊富に表現される.コンピュータでは一般的に8 bit(256段)で量子化されるが、これは画素の階調(濃淡)が0~255の間の数値であることを意味する.化級数の効果図は以下の通りである.
a.量子化段数2 b.量子化段数8 c.量子化段数64
図2
アルゴリズムソース2(java):
イメージヒストグラム
ヒストグラムの定義
階調ヒストグラム(histogram)は、階調分布の関数であり、画像に各階調レベルの画素を有する個数を表し、画像における各階調が現れる周波数を反映する.階調ヒストグラムの横座標は階調レベルであり、縦座標はこの階調レベルが現れる周波数であり、画像の最も基本的な統計的特徴である.
画像の階調ヒストグラムを生成する一般的な手順は、次のとおりです.
1、各階調値の画素数を統計する.
2、統計表に基づいてヒストグラムを描く
以下の図
図3
図4
アルゴリズムソース3:次のアルゴリズムソース4のdrawHistogram()メソッドを参照
グレースケールヒストグラムの性質
1、当該画像における異なる階調値の出現回数(又は周波数)のみを反映し、ある階調値画素が存在する位置を反映することができない.
2、いずれの画像も、それに対応する1つのヒストグラムを一意に決定することができ、1つのヒストグラムは複数の異なる画像を有することができる.
3、1枚の画像が複数の画像にカットされると、各サブマップのヒストグラムの和がこの全図のヒストグラムとなる.
ヒストグラムの用途
ヒストグラムには,バルブ値分割,画像増強,医療画像にも多くの用途がある.
画像のバルブ値(二値)処理
バルブ値処理の定義
画像の閾値処理は、画像の画素階調値をある一定値(tとする)以上の点に白(または黒)を付与し、この一定値t以下の点に黒(または白)を付与する処理である.
画像の閾値処理は、2つの階調値のみの2値画像を得るため、閾値処理を2値化処理と呼び、得られた画像を2値画像と呼ぶ.以下の図
イメージバルブ値処理の手順
1、画像の階調ヒストグラムを描く.
2、画像の階調ヒストグラムからバルブ値tを決定し、例えば図5のバルブ値が65である.
3、画素階調値がt以下の点を白(または黒)に、tより大きい点を黒(または白)に、図6のように効果を与える.
図5
図6
アルゴリズムソース4(java):
サンプリングは、空域または時間領域に連続した画像(アナログ画像)を離散サンプリングポイント(画素)集合(デジタル画像)に変換する動作である.
サンプリングが細ければ細いほど、画素が小さくなり、画像を細かく表現することができます.異なるサンプリング間隔の効果は次のとおりです.
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つの数値(すなわち2段)で表され、2値画像となる.
量子化が細かいほど階調数(濃淡階層)が豊富に表現される.コンピュータでは一般的に8 bit(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
イメージヒストグラム
ヒストグラムの定義
階調ヒストグラム(histogram)は、階調分布の関数であり、画像に各階調レベルの画素を有する個数を表し、画像における各階調が現れる周波数を反映する.階調ヒストグラムの横座標は階調レベルであり、縦座標はこの階調レベルが現れる周波数であり、画像の最も基本的な統計的特徴である.
画像の階調ヒストグラムを生成する一般的な手順は、次のとおりです.
1、各階調値の画素数を統計する.
2、統計表に基づいてヒストグラムを描く
以下の図
図3
図4
アルゴリズムソース3:次のアルゴリズムソース4のdrawHistogram()メソッドを参照
グレースケールヒストグラムの性質
1、当該画像における異なる階調値の出現回数(又は周波数)のみを反映し、ある階調値画素が存在する位置を反映することができない.
2、いずれの画像も、それに対応する1つのヒストグラムを一意に決定することができ、1つのヒストグラムは複数の異なる画像を有することができる.
3、1枚の画像が複数の画像にカットされると、各サブマップのヒストグラムの和がこの全図のヒストグラムとなる.
ヒストグラムの用途
ヒストグラムには,バルブ値分割,画像増強,医療画像にも多くの用途がある.
画像のバルブ値(二値)処理
バルブ値処理の定義
画像の閾値処理は、画像の画素階調値をある一定値(tとする)以上の点に白(または黒)を付与し、この一定値t以下の点に黒(または白)を付与する処理である.
画像の閾値処理は、2つの階調値のみの2値画像を得るため、閾値処理を2値化処理と呼び、得られた画像を2値画像と呼ぶ.以下の図
イメージバルブ値処理の手順
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 max) {
max = hist[i];
}
}
for(int i=0; i