前言
仅仅是记录与分享自己在学习过程中遇到的问题与解决办法,可能有一些错误的观点或理解等,如果有说错的地方麻烦请大家指正,谢谢。该代码仅仅是从rgb角度进行操作,没有使用opencv等第三方库。
我个人的使用经验来说,增强对比度呢一般是用于灰度处理后的图片的。这样可以将灰度后的图片像素值层次给拉开,更方便进行一些和阈值相关的处理。
增强对比度
首先,我们要知道增强对比度的思路和用处。灰度处理后,图片的像素值差距一般会减小,所以,我们利用增强对比度的方法把像素值的差距放大,对于阈值的处理将会更加容易。因此,我们的思路就定为:
1.将灰度处理后的图片P1的最小像素值设为Min,最大像素值设为Max,并且分为3段。即0~Min+20,Min+20~Max-20,Max-20~255,这个20是个人比较习惯使用的阈值,可以进行适当调整。
2.将0~Min+20部分的像素值定为0,把Max-20部分的像素值定为255。那么中间的部分在新的数轴上进行放缩。
3.将放缩后的值重新赋予给图像像素值,我们就能得到一幅加强对比度之后的图片了。
下面开始实践:
①.我们要先获得图片的像素值,为了统计出最值,我们先遍历一遍图片吧。
public void Traverse()
{
ArrayList<Integer> list = new ArrayList<>();
for(int y = 0;y < height;y++)
{
for(int x = 0;x < width;x++)
{
accountPixel(list,x,y);
}
}
}
public void accountPixel(ArrayList<Integer> list,int x,int y)
{
Color color = new Color(bufferedImage.getRGB(x,y));
list.add(color.getRed());
}
我们可以用arraylist来记录图片的像素点,这样在后续需要图片像素值时就不需要再次遍历了。
②.接下来我们去比较得最值
public void Intensify(ArrayList<Integer> list)
{
int max = 0;
int min = 255;
double avg = 0;
for(int i : list)
{
avg += i;
if(i > max)
max = i;
if(i < min)
min = i;
}
avg = avg/list.size();
for(int y = 0;y < height;y++)
{
for(int x = 0;x < width;x++)
{
setRGB(x,y,max,min,avg);
}
}
}
求出平均值用于下面的对比度拉伸并且可以用获得的max,min值去调用setRGB方法去完成新的赋值。
③.以前是用数轴上的等比例放缩计算进行赋值的,大致思路说一下就是根据最值,平均值以及0和255之间的关系分成6段数轴然后进行放缩,后来发现只需要简单的放缩效果也还行。
这样我们就能得到放缩后的像素值啦。
public void setRGB(int x,int y,int max,int min,double avg)
{
Color color = new Color(bufferedImage.getRGB(x,y));
if(color.getRed() >= max - 20)
{
Color white = new Color(255,255,255);
bufferedImage.setRGB(x,y,white.getRGB());
}
else if(color.getRed() <= min + 20)
{
Color black = new Color(0,0,0);
bufferedImage.setRGB(x,y,black.getRGB());
}
else
{
int pixel = (int)(Math.pow(color.getRed(),2)/avg);
if(pixel > max)
pixel = 255;
color = new Color(pixel,pixel,pixel);
bufferedImage.setRGB(x,y,color.getRGB());
}
}
好,我们来看一下效果如何。毛衣的图整体颜色相近,增加对比度可能不太明显,我们换张图片来体现一下效果。左侧是进行灰度处理后的菊花图,右侧是增强对比度后的效果。
接下来我们来看下全部的代码
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.util.ArrayList;
public class IntensifyContrast
{
BufferedImage bufferedImage;
int height;
int width;
public IntensifyContrast(String path)
{
try
{
bufferedImage = ImageIO.read(new File(path));
}
catch (IOException e)
{
e.printStackTrace();
}
height = bufferedImage.getHeight();
width = bufferedImage.getWidth();
}
public void Traverse()
{
ArrayList<Integer> list = new ArrayList<>();
for(int y = 0;y < height;y++)
{
for(int x = 0;x < width;x++)
{
accountPixel(list,x,y);
}
}
Intensify(list);
}
public void accountPixel(ArrayList<Integer> list,int x,int y)
{
Color color = new Color(bufferedImage.getRGB(x,y));
list.add(color.getRed());
}
public void Intensify(ArrayList<Integer> list)
{
int max = 0;
int min = 255;
double avg = 0;
for(int i : list)
{
avg += i;
if(i > max)
max = i;
if(i < min)
min = i;
}
avg = avg/list.size();
for(int y = 0;y < height;y++)
{
for(int x = 0;x < width;x++)
{
setRGB(x,y,max,min,avg);
}
}
}
public void setRGB(int x,int y,int max,int min,double avg)
{
Color color = new Color(bufferedImage.getRGB(x,y));
if(color.getRed() >= max - 20)
{
Color white = new Color(255,255,255);
bufferedImage.setRGB(x,y,white.getRGB());
}
else if(color.getRed() <= min + 20)
{
Color black = new Color(0,0,0);
bufferedImage.setRGB(x,y,black.getRGB());
}
else
{
int pixel = (int)(Math.pow(color.getRed(),2)/avg);
if(pixel > max)
pixel = 255;
color = new Color(pixel,pixel,pixel);
bufferedImage.setRGB(x,y,color.getRGB());
}
}
public void outPicture(String path)
{
try
{
ImageIO.write(bufferedImage,"png",new File(path));
}
catch (IOException e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
IntensifyContrast ic = new IntensifyContrast("图片/3gray.png");
ic.Traverse();
ic.outPicture("图片/ic3gray.png");
}
}
谢谢大家,有能优化的地方欢迎大家提出!