直方图均衡化 java_直方图均衡化的java代码

本文介绍了一种使用Java实现直方图均衡化的代码示例。直方图均衡化可使图像暗部变亮,亮部变暗,但并非所有图像都适用,可能会影响图像原本的视觉效果。文章通过具体代码展示了如何进行图像加载、灰度化、直方图显示和均衡化操作,并给出了直方图均衡化前后的图像效果对比。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

自我感觉直方图均衡化作用并不是很大,有的时候甚至会适得其反。它的核心思想就是让图像暗的地方变亮,亮的地方变暗。问题是,如果图像原本的亮暗程度就非常符合人眼的观察结果,那么直方图均衡化之后的图像就变的很糟。所以该方法要依据图像数据的特点而定。先看一下效果比较好的案例:

彩色的lena图像:lena_color.jpg

1149f0c80c31ce1e182fe138aa64fffd.png

将彩色lena变为灰度lena:

7ff6b57d87137a022f2f7a9c5fda8812.png

c02c83d1f1b8bf3c4f0be9fb6f4f4282.png

对灰度lena进行直方图均衡化,结果如下,可以看出,图像整体变亮,暗处的细节得到了突出:

d95825103d91f359d83a059ed7933ccd.png

0c7d561447db8a82bc23011304402938.png

但是对于某些图像,尤其是亮背景的图像,本来前景和背景有很好的区分,但是直方图均衡化之后,亮的背景变暗,图像灰度成平稳过渡状态,反而不利于图像信息的展示,如下图:girl.jpg:

133e024284226c11f152562619c5f616.png

ece3d8e6cbf9630ed98bdd86adfa4a1a.png

直方图均衡化后,结果如下,可以看到,结果并不理想:

d349eb496685ef48e78514c3543889ea.png

582884c640ab4417e6f1a82041dd2053.png

package p01;

import java.awt.*;

import java.awt.event.*;

import java.awt.image.*;

import java.io.File;

import java.io.IOException;

import javax.imageio.ImageIO;

import javax.swing.*;

public class hist extends Frame{

Image im, tmp;

int iw, ih;

int[] pixels;

boolean flag_load = false;

boolean flag_grey = false;

//hist的构造方法

public hist(){

this.setTitle("直方图均衡化");

Panel pdown;

Button load, grey, hist, run, save, quit;

//添加窗口监听事件

addWindowListener(new WindowAdapter(){

public void windowClosing(WindowEvent e){

System.exit(0);

}

}

);

pdown = new Panel();

pdown.setBackground(Color.LIGHT_GRAY);

//按钮名称

load = new Button("装载图像");

grey = new Button("灰度图像");

hist = new Button("直方图");

run = new Button("均衡化");

save = new Button("保存");

quit = new Button("退出");

this.add(pdown, BorderLayout.SOUTH);

//增加按钮

pdown.add(load);

pdown.add(grey);

pdown.add(hist);

pdown.add(run);

pdown.add(save);

pdown.add(quit);

//按钮的动作程序 装载图像

load.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

try {

jLoad_ActionPerformed(e);

} catch (IOException e1) {

e1.printStackTrace();

}

}

});

//按钮的动作程序 灰度化

grey.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

try {

jGrey_ActionPerformed(e);

} catch (IOException e1) {

e1.printStackTrace();

}

}

});

//按钮的动作程序 直方图

hist.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

jHist_ActionPerformed(e);

}

});

//按钮的动作程序 直方图均衡化

run.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

jRun_ActionPerformed(e);

}

});

//按钮的动作程序 保存

save.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

try {

jSave_ActionPerformed(e);

} catch (IOException e1) {

e1.printStackTrace();

}

}

});

//按钮的动作程序 退出

quit.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

jQuit_ActionPerformed(e);

}

});

}

//按钮动作的实现 加载图像

public void jLoad_ActionPerformed(ActionEvent e) throws IOException{

File inputFile = new File("E:\\f2\\sc\\source.jpg");

BufferedImage input = ImageIO.read(inputFile);

im = input;

tmp = input;

flag_load = true;

repaint();

}

//按钮动作的实现 灰度化

public void jGrey_ActionPerformed(ActionEvent e) throws IOException{

if(flag_load){

File inputFile = new File("E:\\f2\\sc\\source.jpg");

BufferedImage input = ImageIO.read(inputFile);

iw = input.getWidth(this);

ih = input.getHeight(this);

pixels = new int[iw*ih];

BufferedImage grayImage = new BufferedImage(iw, ih,

BufferedImage.TYPE_BYTE_GRAY);

for(int i=0; i

for(int j=0; j

int rgb = input.getRGB(i, j);

int grey = (int) (0.3*((rgb&0xff0000 )>>16)+0.59*((rgb&0xff00 )>>8)+0.11*((rgb&0xff)));

rgb = 255<<24|grey<<16|grey<<8|grey;

grayImage.setRGB(i, j, rgb);

}

}

tmp = grayImage;

try{

PixelGrabber pg = new PixelGrabber(tmp,0,0,iw,ih,pixels,0,iw);

pg.grabPixels();

}catch(InterruptedException e3){

e3.printStackTrace();

}

flag_grey = true;

repaint();

} else{

JOptionPane.showMessageDialog(null, "先点击“装载图像”,3Q!","提示:",

JOptionPane.WARNING_MESSAGE);

}

}

//按钮动作的实现 直方图显示 调用histshow这个类进行操作

public void jHist_ActionPerformed(ActionEvent e){

histshow h = new histshow();

h.getData(pixels, iw, ih);

h.setSize(480,350);

h.setVisible(true);

}

//按钮动作的实现 直方图均衡化

public void jRun_ActionPerformed(ActionEvent e){

if(flag_load&&flag_grey){

try{

PixelGrabber pg = new PixelGrabber(tmp,0,0,iw,ih,pixels,0,iw);

pg.grabPixels();

}catch(InterruptedException e3){

e3.printStackTrace();

}

BufferedImage greyImage = new BufferedImage(iw, ih,

BufferedImage.TYPE_BYTE_GRAY);

//获取图像的直方图

int[] histogram = new int[256];

for(int i=0; i

for(int j=0; j

int grey = pixels[i*iw+j]&0xff;

histogram[grey]++;

}

}

//直方图均衡化

double a = (double)255/(iw*ih);

double[] c = new double [256];

c[0] = (a*histogram[0]);

for(int i=1; i<256; i++){

c[i] = c[i-1]+(int)(a*histogram[i]);

}

for(int i=0; i

for(int j=0; j

int grey = pixels[i*iw+j]&0x0000ff;

int hist = (int)(c[grey]);

pixels[i*iw+j] = 255<<24|hist<<16|hist<<8|hist;

greyImage.setRGB(j, i, pixels[i*iw+j]);

}

}

tmp = greyImage;

flag_load = true;

repaint();

}else{

JOptionPane.showMessageDialog(null, "先点击“装载图像”,3Q!","提示:",

JOptionPane.WARNING_MESSAGE);

}

}

//按钮动作的实现保存

public void jSave_ActionPerformed(ActionEvent e) throws IOException{

if(flag_load){

BufferedImage bi = new BufferedImage(tmp.getWidth(null),tmp.getHeight(null),

BufferedImage.TYPE_INT_RGB);

Graphics g = bi.getGraphics();

g.drawImage(tmp,0, 0,null);

g.dispose();

File save_path=new File("E:\\f2\\sc\\save_t01.jpg");

ImageIO.write(bi, "JPG", save_path);

}else{

JOptionPane.showMessageDialog(null, "先点击“装载图像”,3Q!","提示:",

JOptionPane.WARNING_MESSAGE);

}

}

//按钮动作的实现 退出

public void jQuit_ActionPerformed(ActionEvent e){

System.exit(0);

}

//绘图函数

public void paint(Graphics g){

//if(flag_Load){

g.drawImage(tmp,50,50,this);

//}else{}

}

public static void main(String[] args) {

hist ti = new hist();

ti.setSize(900,860);

ti.setVisible(true);

}

}

//上面的代码应用到了histshow类,如下:

package p01;

import java.awt.*;

import java.awt.event.*;

import java.awt.Window;

public class histshow extends Frame{

int data[];

int histogram[] = new int[256];

public histshow(){

this.setTitle("图像的灰度直方图");

Panel pdown;

Button quit;

pdown = new Panel();

quit = new Button("关闭窗口");

this.add(pdown, BorderLayout.SOUTH);

pdown.add(quit);

quit.addActionListener(new ActionListener(){

public void actionPerformed(ActionEvent e){

jQuit_ActionPerformed(e);

}

});

// 添加窗口监听事件

addWindowListener(new WindowAdapter(){

public void windowClosing(WindowEvent e){

histshow.this.dispose();

}

});

}

public void jQuit_ActionPerformed(ActionEvent e){

this.setVisible(false);

}

public void getData(int[] data, int iw, int ih){

this.data = data;

for (int i = 0; i < iw * ih; i++){

int grey = data[i] & 0xff;

histogram[grey]++;

}

// 找出最大的数,进行标准化.

int temp = histogram[0];

for (int i = 0; i < 256; i++){

if (temp <= histogram[i]){

temp = histogram[i];

//System.out.println(temp);

}

}

for (int i = 0; i < 256; i++){

histogram[i] = histogram[i] * 200 / temp;

//System.out.println(temp);

}

}

//画出直方图

public void paint(Graphics g){

// 画出水平和垂直的轴

g.drawLine(100, 250, 356, 250);

g.drawLine(100, 50, 100, 250);

// 画出横轴坐标

g.drawString("0", 98, 263);

g.drawString("50", 145, 263);

g.drawString("100", 193, 263);

g.drawString("150", 243, 263);

g.drawString("200", 293, 263);

g.drawString("250", 343, 263);

// 画出纵轴坐标

g.drawString("0.5", 83, 145);

g.drawString("1", 90, 60);

// 画出图像的直方图

for (int i = 0; i < 256; i++){

g.drawLine(100 + i, 250, 100 + i, 250 - histogram[i]);

}

g.drawString("该图像的灰度直方图如上所示.", 160, 280);

}

}

29e1695446b4697b5c7f3099fc848d90.png

大小: 11.1 KB

b8135549d12c8993d4be374b6265b0c4.png

大小: 13.9 KB

b5e9e5bc0128aef58031237e28bf507b.png

大小: 30.6 KB

89a036c78309c0e627095c075b829af5.png

大小: 19.9 KB

4df791c0de2ca5d1965eb549e08be92b.png

大小: 22.9 KB

502b8fcf5aeee870a608eab4552837e7.png

大小: 20.5 KB

960188ea4d7dd872c30495a055c77a5b.png

大小: 20.3 KB

992c36660b6b1869163cc4030c20c351.png

大小: 21.1 KB

74de0ec2ae977be91551a68939853872.png

大小: 17.3 KB

分享到:

18e900b8666ce6f233d25ec02f95ee59.png

72dd548719f0ace4d5f9bca64e1d7715.png

2012-11-05 23:50

浏览 7969

评论

1 楼

探花郎

2013-07-22

最近在做数字图像处理的大作业,需要做出直方图的均衡化和规定化。在你程序的基础上怎么做菜能实现直方图的规定化。望您不吝赐教。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值