1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 人工智能应用实例:图片降噪

人工智能应用实例:图片降噪

时间:2024-06-26 03:11:01

相关推荐

人工智能应用实例:图片降噪

人工智能应用实例:图片降噪

场景设置

对白色背景、黑色前景的黑白图片进行降噪处理,可以假定背景部分多于前景。

图1 从左往右:原图、噪声图、降噪图

降噪模型

我们可以对图片建立这样一个两层的二维模型,底层表示原图,顶层表示任意的噪声图,xi为原图第i个像素,yi为噪声图第i个像素,xi、yi的取值只有1和-1,1表示白色,-1表示黑色。

图2 图片模型

显然,我们对噪声图任取的一个像素yi可以有以下3个推测:

1、这个像素更加可能是白色,因为白色背景多于黑色前景。

2、这个像素应该和它周围的几个像素颜色一致。

3、如果不能确定这个像素在原图到底是白色还是黑色,那么更有可能原图就是现在噪声图的这个颜色,因为毕竟噪声像素是少量的,大部分像素维持了原图的颜色。

基于此,可以对噪声图定义一个能量公式:

注意:这里的xi、yi颠倒过来了,xi为噪声图,yi为原图。

公式中三个参数都是正实数,第一项表示对噪声图每个像素的值求和,第二项表示对噪声图每个像素与之周围像素差异的求和,第三项表示噪声图像素与原图像素的差异求和。显然基于我们以上的3点推测,越接近原图,噪声图的能量值应该越低。

降噪过程

有了这样一个图片模型和噪声图能量公式,我们就可以对图片降噪了。图片降噪基于一个很简单的想法,我们对整个噪声图的每个像素扫描一次(也可以扫描多遍),看看每次改变该像素点的颜色能否使整个噪声图的能量值降低,如果能量值降低了,我们就接受这一次改动,否则,该像素颜色保持不变。

不过,这里还存在一个问题,我们不可能取得能量公式中原图每个像素yi的值!其实这也无妨,可以简单地用每次降噪处理(一次只处理一个像素)得到的新的降噪图去逼近原图,而一开始采用的就是噪声图。因此,每次降噪处理都要计算两个能量值,一个是当前已经得到的降噪图(被用来逼近原图,即xi、yi都是自身)的能量值,另一个是改变一个像素颜色得到的图片(xi为自身,yi为前面得到的降噪图)的能量值。

Java代码实现

由于某些限制,代码实现中图片读写使用了十分复杂的手段,实际上可以通过Java的imageio包进行简化。

另外,图片能量公式的3个参数这里采用了手动指定的方式:fa=0.0,fb=1.0,fc=2.1,还可以通过更加智能的算法自动学习得到,比如爬山算法、模拟退火算法、遗传算法。

// ImageIOer.java/*** > ImageIOer* * ImageIOer is a class to read and save images,* and it implements IImageIO.* * @author RuanShiHai*/import java.awt.*;import java.awt.image.*;import java.io.*;import javax.imageio.*;public class ImageIOer {/*** Read a bmp image* @param filePath - the image file to read* @return an Image object of the image*/public Image myRead(String filePath) {try {// the length of BMP file headerint bfLen = 14;// the length of BMP information headerint biLen = 40;FileInputStream fs = new FileInputStream(filePath);byte[] bf = new byte[bfLen];byte[] bi = new byte[biLen];// read BMP file headerfs.read(bf, 0, bfLen);// read BMP information headerfs.read(bi, 0, biLen);// pixels value of widthint biWidth = ((((int) bi[7] & 0xff) << 24) |(((int) bi[6] & 0xff) << 16) | (((int) bi[5] & 0xff) << 8) |((int) bi[4] & 0xff));// pixels value of heightint biHeight = (((int) bi[11] & 0xff) << 24) |(((int) bi[10] & 0xff) << 16) | (((int) bi[9] & 0xff) << 8) |((int) bi[8] & 0xff);// the number of bits of each pixelint biBitCount = ((((int) bi[15] & 0xff) << 8) |((int) bi[14] & 0xff));// the size of bytes of the imageint biSizeImage = ((((int) bi[23] & 0xff) << 24) |(((int) bi[22] & 0xff) << 16) | (((int) bi[21] & 0xff) << 8) |((int) bi[20] & 0xff));// only processes 24bits bmp imageif (biBitCount != 24) {fs.close();return null;}// the number of bytes to be padded after each rowint nPad = (biSizeImage / biHeight) - (biWidth * 3);// read pixels data from image into a byte arraybyte[] bRGB = new byte[biSizeImage];fs.read(bRGB, 0, biSizeImage);fs.close();int index = 0;int[] data = new int[biWidth * biHeight];// store pixels in an array of int typefor (int i = biHeight - 1; i >= 0; i--) {for (int j = 0; j < biWidth; j++) {data[(i * biWidth) + j] = (((int) 255 << 24) |(((int) bRGB[index + 2] & 0xff) << 16) |(((int) bRGB[index + 1] & 0xff) << 8) |((int) bRGB[index] & 0xff));index += 3;}index += nPad;}// create an Image objectToolkit kit = Toolkit.getDefaultToolkit();Image image = kit.createImage(new MemoryImageSource(biWidth,biHeight, data, 0, biWidth));return image;} catch (Exception e) {e.printStackTrace();System.out.println("Caught exception in loadbitmap!");}return null;}/*** Store an Image as a bmp image file* @param image - Image object to be saved as a bmp image file* @param filePath - the name of the bmp image file* @return the Image object*/public Image myWrite(Image image, String filePath) {try {File imgFile = new File(filePath + ".bmp");BufferedImage bi = new BufferedImage(image.getWidth(null),image.getHeight(null), BufferedImage.TYPE_INT_RGB);Graphics2D biContext = bi.createGraphics();// get a BufferedImage object from an Image objectbiContext.drawImage(image, 0, 0, null);biContext.dispose();ImageIO.write(bi, "bmp", imgFile);return image;} catch (Exception e) {e.printStackTrace(System.out);}return null;}}

// PictureNoise.javaimport java.awt.*;import java.awt.image.*;import java.io.*;import java.util.Random;import javax.imageio.*;public class PictureNoise {private static final double rate = 0.1;private static final double fa = 0;private static final double fb = 1.0;private static final double fc = 2.1;public void generateAPicture() {try {int width = 640;int height = 480;// 创建BufferedImage对象Font font = new Font("微软雅黑", Font.BOLD, 160);BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);// 获取Graphics2DGraphics2D g2d = image.createGraphics();// 画图g2d.setBackground(new Color(255, 255, 255));g2d.setPaint(new Color(0, 0, 0));g2d.clearRect(0, 0, width, height);g2d.setFont(font);g2d.drawString("Java", 140, 200);g2d.drawString("Python", 40, 400);// 释放对象g2d.dispose();// 保存文件ImageIO.write(image, "bmp", new File("/home/ln/picture.bmp"));} catch (Exception ex) {ex.printStackTrace();}}// generate a picture with noisepublic Image getNoise(Image sourceImage) {BufferedImage bi = new BufferedImage(sourceImage.getWidth(null),sourceImage.getHeight(null), BufferedImage.TYPE_INT_RGB);Graphics2D biContext = bi.createGraphics();// get a BufferedImage object from an Image objectbiContext.drawImage(sourceImage, 0, 0, null);biContext.dispose();// create an array of int type to store rgb values of each pixelint[] rgbs = new int[bi.getWidth() * bi.getHeight()];bi.getRGB(0, 0, bi.getWidth(), bi.getHeight(), rgbs, 0, bi.getWidth());Random rd = new Random();int index = 0;for (int i = 0; i < bi.getHeight(); i++) {for (int j = 0; j < bi.getWidth(); j++, index++) {if (rd.nextDouble() < rate)rgbs[index] = (rgbs[index] & 0xff000000)| (~rgbs[index] & 0x00ffffff);}}// create a new Image objectToolkit kit = Toolkit.getDefaultToolkit();Image image = kit.createImage(new MemoryImageSource(bi.getWidth(), bi.getHeight(), rgbs, 0, bi.getWidth()));return image;}public Image reduceNoise(Image sourceImage, double fa, double fb, double fc) {BufferedImage bi = new BufferedImage(sourceImage.getWidth(null),sourceImage.getHeight(null), BufferedImage.TYPE_INT_RGB);Graphics2D biContext = bi.createGraphics();// get a BufferedImage object from an Image objectbiContext.drawImage(sourceImage, 0, 0, null);biContext.dispose();// create an array of int type to store rgb values of each pixelint[] rgbs = new int[bi.getWidth() * bi.getHeight()];bi.getRGB(0, 0, bi.getWidth(), bi.getHeight(), rgbs, 0, bi.getWidth());int height = bi.getHeight(), width = bi.getWidth();for (int i = 0; i < height; i++) {for (int j = 0; j < width; j++) {double dd;int d1, d2, d3;d1 = 2;if ((rgbs[i * width + j] & 0x00ffffff) == 0)d1 = -2;d2 = 0;int rc[][] = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } };for (int k = 0; k < 4; k++) {if (isValid(i + rc[k][0], j + rc[k][1], height, width)) {if ((rgbs[(i + rc[k][0]) * width + j + rc[k][1]] & 0x00ffffff) == (rgbs[i* width + j] & 0x00ffffff))d2 += -2;elsed2 += 2;}}d2 *= 2;d3 = -2;dd = fa * d1 - fb * d2 - fc * d3;if (dd < 0)rgbs[i * width + j] = (rgbs[i * width + j] & 0xff000000)| (~rgbs[i * width + j] & 0x00ffffff);}}// create a new Image objectToolkit kit = Toolkit.getDefaultToolkit();Image image = kit.createImage(new MemoryImageSource(bi.getWidth(), bi.getHeight(), rgbs, 0, bi.getWidth()));return image;}private boolean isValid(int row, int col, int height, int width) {return (row >= 0 && row < height && col >= 0 && col < width);}public static void main(String[] args) {PictureNoise pictureNoise = new PictureNoise();ImageIOer imageIOer = new ImageIOer();pictureNoise.generateAPicture();Image sourceImage = imageIOer.myRead("/picture.bmp");Image noiseImage = pictureNoise.getNoise(sourceImage);Image noNoiseImage = pictureNoise.reduceNoise(noiseImage, fa, fb, fc);imageIOer.myWrite(noiseImage, "/picture_with_noise");imageIOer.myWrite(noNoiseImage, "/picture_noise_processed");}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。