人工智能应用实例:图片降噪
场景设置
对白色背景、黑色前景的黑白图片进行降噪处理,可以假定背景部分多于前景。
图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 header int bfLen = 14; // the length of BMP information header int biLen = 40; FileInputStream fs = new FileInputStream(filePath); byte[] bf = new byte[bfLen]; byte[] bi = new byte[biLen]; // read BMP file header fs.read(bf, 0, bfLen); // read BMP information header fs.read(bi, 0, biLen); // pixels value of width int biWidth = ((((int) bi[7] & 0xff) << 24) | (((int) bi[6] & 0xff) << 16) | (((int) bi[5] & 0xff) << 8) | ((int) bi[4] & 0xff)); // pixels value of height int 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 pixel int biBitCount = ((((int) bi[15] & 0xff) << 8) | ((int) bi[14] & 0xff)); // the size of bytes of the image int biSizeImage = ((((int) bi[23] & 0xff) << 24) | (((int) bi[22] & 0xff) << 16) | (((int) bi[21] & 0xff) << 8) | ((int) bi[20] & 0xff)); // only processes 24bits bmp image if (biBitCount != 24) { fs.close(); return null; } // the number of bytes to be padded after each row int nPad = (biSizeImage / biHeight) - (biWidth * 3); // read pixels data from image into a byte array byte[] 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 type for (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 object Toolkit 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 object biContext.drawImage(image, 0, 0, null); biContext.dispose(); ImageIO.write(bi, "bmp", imgFile); return image; } catch (Exception e) { e.printStackTrace(System.out); } return null; } }
// PictureNoise.java import 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); // 获取Graphics2D Graphics2D 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 noise public 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 object biContext.drawImage(sourceImage, 0, 0, null); biContext.dispose(); // create an array of int type to store rgb values of each pixel int[] 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 object Toolkit 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 object biContext.drawImage(sourceImage, 0, 0, null); biContext.dispose(); // create an array of int type to store rgb values of each pixel int[] 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; else d2 += 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 object Toolkit 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"); } }
相关推荐
在Python编程领域,图片识别是一项重要的技术,广泛应用于图像处理、机器学习以及人工智能等领域。本实例将探讨如何使用Python进行图片识别,通过实际操作来帮助理解相关知识点。 首先,我们需要了解图片识别的基本...
此外,随着物联网和人工智能的兴起,DSP也越来越多地应用于传感器数据处理和机器学习算法的实现。 通过学习这个课件,读者不仅可以掌握DSP的基本原理,还能了解到不同领域如何利用DSP实现复杂功能,进一步提升对...
### 人工智能在相机成像中的应用 #### 一、智能降噪与图像增强 **智能降噪** 1. **降噪算法优化**:利用深度学习技术优化降噪模型,能够根据不同的噪声类型和图像特征进行调整,从而显著提高图像的信噪比和视觉...
在人工智能领域,神经网络是模仿人脑神经元工作原理的一种算法模型,通过大量数据的训练来学习复杂的关系和模式。Matlab神经网络工具箱使得非专业AI背景的用户也能方便地进行神经网络研究和应用开发。 **神经网络的...
在本项目中,“基于matlab的数字信号降噪系统以及GUI界面.zip”是一个结合了MATLAB编程和人工智能技术的应用实例,主要用于数字信号处理中的噪声消除。MATLAB是一种强大的数学计算和数据分析环境,特别适合进行信号...
试题中涉及到人工智能在日常生活中的应用,如手机的智能化功能,如自动亮屏、语音识别等,这些都是人工智能技术在客户端(C端)的应用实例。 【课件】该文档可能以课件的形式呈现,便于教师讲解和学生复习,通过...
在IT领域,语音信号处理是一项重要的技术,广泛应用于通信、语音识别、听力辅助设备和人工智能等领域。本资源“语音信号处理实验教程(MATLAB源代码)语音降噪.rar”提供了一个学习和实践这一技术的平台,特别关注的...
在IT领域,图像处理是一项重要的技术,广泛应用于各种软件开发,包括摄影后期、医疗成像、人工智能、视频编辑等。本篇文章将详细探讨基于C语言的图像处理程序设计实例,结合C++编程语言,帮助读者深入理解图像处理的...
5. **源码解析**:提供的源码可能包含多个实例,如彩色图像转换为灰度图像、图像降噪、图像增强等,读者可以通过阅读和分析这些代码,深入理解FPGA在图像处理中的应用。 6. **实际应用案例**:除了理论知识,书中的...
【智能运维】:智能运维是利用人工智能和大数据技术,实现主动、快速和精准的运维策略。通过基站异常检测,网络运维部门可以提前发现问题,针对性地进行巡检,减少故障发生,提高网络运维效率。 【实际应用】:提出...
首先,语音识别是将人类语音转化为文本的过程,它在人工智能领域有着广泛的应用,如智能家居、智能助手、语音搜索等。在Python中,有许多库可以帮助我们实现这一功能,比如`SpeechRecognition`库。这个库允许我们与...
这一领域的研究对图像处理、人工智能、机器学习等多个领域都有深远影响。 首先,我们需要了解模式识别的基本步骤:数据获取、预处理、特征提取、模式分类和后处理。在这个过程中,结构模式识别强调了特征的选取和...
7. **应用实例**:书中会提供一些实际案例,比如语音识别系统、语音增强或降噪算法的实现,以帮助读者将理论知识应用到实践中。 尽管书中可能并未包含代码,但作者指出,相关的MATLAB代码可以通过网络获取。读者...
12. **最新技术趋势**:第3版可能会涵盖最新的DSP芯片技术,如多核DSP、SoC(System on Chip)集成、低功耗设计以及在物联网、人工智能等新兴领域的应用。 通过阅读这本书,读者不仅可以了解DSP芯片的基本原理,还...
waifu2x-caffe 的核心是深度学习算法,这是一种人工智能技术,通过大量的训练数据学习到图像特征,并能应用这些特征来预测新图像的高质量版本。在这个特定的工具中,它可能包含预训练的模型,用户可以直接使用,无需...
在IT领域,数字图像处理是一项基础且重要的技术,广泛应用于摄影、医学成像、安全监控、人工智能等多个领域。本主题“简单的数字图像处理应用”涵盖了基础的图像操作和滤波技术,下面将对这些知识点进行详细阐述。 ...
5. 应用实例: - 无线通信中的信道模型:多径衰落、瑞利衰落和莱斯衰落等随机过程。 - 信号检测与估计理论:噪声中的信号检测,如匹配滤波器的应用。 - 时间序列分析:ARIMA模型在时间序列预测中的应用。 - 信号...
OpenCV(开源计算机视觉库)是一个强大的跨平台库,它包含了大量的...同时,这个过程也会涉及到机器学习和人工智能的概念,因为特征检测和匹配是许多机器视觉任务的基础,而拼接工具则是一个实际的计算机视觉应用实例。
GFPGAN是AI技术在图像恢复领域的应用实例。 3. **图像处理**:GFPGAN涉及多种图像处理技术,包括图像增强、降噪、超分辨率等,这些技术都是为了提高修复后照片的质量和真实感。 在实际操作中,GFPGAN的流程可能...
《精品完整数字图像处理课件》是一套全面深入讲解数字图像处理的教育资源,适用于...通过深入学习和实践,你不仅可以提升专业能力,还可以为未来在人工智能、机器视觉、图像分析等相关领域的研究和发展奠定坚实的基础。