数图的量化:灰度处理

前言:灰度处理相较于双线性内插值法要容易理解很多。

1. 灰度处理

介绍:

一幅具有256个灰度级([0,255])的图像,如果量化2level则保留像素值0和255,即整张数图的像素值只能取0和255这两个值其中之一,并且离哪个值比较近,就取哪个。比如你原来的像素是90,我们已知0和255的中间值是128,那么90应该改为0。根据这种思路,遍历所有像素,一一将其改成最贴近的像素即可。

思路:

怎么具体改成最贴近的像素呢,这其实是一道算法题,比如2level是保留像素值0和255,4level是0,85,170和255,可以发现每个level的间隔区间都是255/(level-1)取整。比如level4的间隔255/(4-1)=85,所以第0层是85*0,第1层是85*1,第2层是85*2,第3层是85*3。我们要实现一种算法使得某个0-255的值能找到其所归属的层,然后改为该层对应的像素。比如我们的像素是90,那么很容易想到要先算出90该去第几层,可以用90/间隔85得到1.06多的一个浮点数,如果是0-0.5则去第0层,0.5-1.5则去第1层,1.5-2.5则去第2层,2.5-3.5则去第三层,注意:这里为什么要有到3.5呢?按道理来说最高像素值是255,255/85不可能超过3,但是还是有特殊情况的,比如当level为8时,间隔为36,那么255/36为7.083,所以超过了7,至于有没有可能超过7.5我没去试过,但是没所谓的,我们给所求的像素值加个255的上限即可。根据这个规律,我们得出具体操作步骤。

操作:

先用(像素值/间隔)得出浮点数,⌊ 像素值/间隔 ⌋得出浮点数的整数部分,再用该浮点数-浮点数的整数部分得出浮点数的小数部分,将小数部分与0.5比较,如果超过了则整数部分+1,没超过则不变,最后整数部分乘以间隔即为所求像素值

2. 代码

java实现

import java.awt.*;
import java.awt.Graphics2D;
import java.awt.image.ColorModel;
import java.awt.image.BufferedImage;

import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class ImageReader {

    //原图、宽、高、RGB矩阵、图片路径
    private BufferedImage bufferedImage = null;
    private int width;
    private int height;
    private double[][][] sourceRGB;
    private String filePath = "./hw1_input/20.png";
    ColorModel cm = ColorModel.getRGBdefault();

    ImageReader() {
        //读取图片
        try {
            bufferedImage = ImageIO.read(new File(filePath));
        } catch (IOException e) {
            e.printStackTrace();
        }

        width = bufferedImage.getWidth();
        height = bufferedImage.getHeight();

        //量化
        quantize(128);
        quantize(32);
        quantize(8);
        quantize(4);
        quantize(2);
    }

    //量化
    public void quantize(int level) {
        BufferedImage buffImage =  new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
        //注意,读进来彩色图像用TYPE_INT_ARGB(三通道),灰度图用TYPE_BYTE_GRAY(单通道),灰度图用TYPE_INT_ARGB会变亮

        // 将图像画到buffImage中
        Graphics2D bGr = buffImage.createGraphics();
        bGr.drawImage(bufferedImage, 0, 0, width, height, null);
        bGr.dispose();

        //设置每个区间段
        int gap = (int) (256 / (level-1));
        //存储量化后的RGB值
        int pix[] = new int[width * height];

        bufferedImage.getRGB(0, 0, width, height, pix, 0, width);
        int r, g, b, temp;
        double doutemp;
        for(int i = 0; i < width * height; i++) {
            r = cm.getRed(pix[i]);
            temp = r / gap;
            doutemp = (double)r/gap - temp;
            if (doutemp - 0.5 > 0) {
                temp++;
            }
            r = temp*gap > 255 ? 255 : temp*gap;

            g = cm.getGreen(pix[i]);
            temp = g / gap;
            doutemp = (double)g/gap - temp;
            if (doutemp - 0.5 > 0) {
                temp++;
            }
            g = temp*gap > 255 ? 255 : temp*gap;

            b = cm.getBlue(pix[i]);
            temp = b / gap;
            doutemp = (double)b/gap - temp;
            if (doutemp - 0.5 > 0) {
                temp++;
            }
            b = temp*gap > 255 ? 255 : temp*gap;

            pix[i] = new Color(r, g, b).getRGB();
        }

        //把图像设置为新的RGB值
        buffImage.setRGB(0, 0, width, height, pix, 0, width);
        //将图片输出为png格式
        File output= new File("./targetImg/level_" + Integer.toString(level) + ".png");
        try {
            ImageIO.write(buffImage, "png", output);
        } catch(IOException e) {
            return;
        }

    }

}

运行:再随便写一个类,main函数中new一下ImageReader即可。

女票的matlab实现

function output_img = quantize(input_img, level)
%Input - input_img is a two-dimensional matrices storing image
% - level is an integer in [1; 256] defining the number of gray levels of output
%Output - output_img is the same as input_img

imshow(input_img); %显示原图
img = imread(input_img); %读取输入图片的数据
[h,w] = size(img); %获取行和列,即原图的高度和宽度

output_img = zeros(h, w); %初始化

d = 255 / (level - 1)

for i = 1 : h
    for j = 1 : w
        output_img(i, j) = round(round(img(i, j) / d) * d);
    end
end

imwrite(uint8(output_img), 'output_img.png');
figure,imshow(uint8(output_img));
end

运行:quantize(‘C:\Users\Administrator\Desktop\20.png’, 128);

3.示例

原图

数图的量化:灰度处理_第1张图片

level128

数图的量化:灰度处理_第2张图片

level32

数图的量化:灰度处理_第3张图片

level8

数图的量化:灰度处理_第4张图片

level4

数图的量化:灰度处理_第5张图片

level2

数图的量化:灰度处理_第6张图片

你可能感兴趣的:(数字图像处理)