目录

一.图像处理的原理

二.图像处理的方法

(1)将图片转换成二维数组

(2)绘制原图

(3)绘制灰度图像

(4)绘制马赛克图像

(5)绘制珠纹化图像

​(6)绘制融合图像

​(7)绘制轮廓图像

(8)绘制黑白版画

(9)绘制锐化图像

(10)绘制高斯模糊图像

三.锐化、均值模糊、浮雕



一.图像处理的原理

  • 每个图片都可以看做一个保存了每个像素点RGB值的二维数组,我们操作的对象则是RGB值。
  • 每个R、G、B值用1个byte来表示,范围在0~255之间。
  • //rgb数字构成颜色,范围0~255
    Color c1 = new Color(123456789);
    //int数字构成颜色,int范围即可
    Cplor c2 = new Color(111, 222, 111);
  • 每个RGB值都用1个int类型的变量来存储,1个int由4个byte组成,,Color对象由3个byte组成,所以其间可以相互转换。
  • (0,0,0)是黑色,(255,255,255)是白色,(255,0,0)是红色;

二.图像处理的方法

(1)将图片转换成二维数组

图像处理的本质即为对代表图像的二维数组中的数值按照一定的算法进行重新计算。所以我们首先需要把图片转换成二维数组。

    /**** @param path 图片路径* @return imgArr 保存图片像素的二维数组*/public int[][] imageFileToArr(String path) {File file = new File(path);//将图片保存到图像缓冲区BufferedImage buffimg = null;try {buffimg = ImageIO.read(file);} catch (Exception e) {e.printStackTrace();}int w = buffimg.getWidth();int h = buffimg.getHeight();//存储像素点的二维数组int[][] imgArr = new int[w][h];for(int i = 0; i < w; i++) {for(int j = 0; j < h; j++) {imgArr[i][j] = buffimg.getRGB(i, j);}}return imgArr;}

(2)绘制原图

将图片通过图像缓冲区存储到二维数组以后,我们可以通过遍历,将每个像素点打印出来,从而实现绘制原图的功能。

     //绘制原图public void drawImage(int[][] imgArr) {for(int i = 0; i < imgArr.length; i++) {for(int j = 0; j < imgArr[0].length; j++) {int rgb = imgArr[i][j];Color color = new Color(rgb);gr.setColor(color);gr.fillRect(i,j,1,1);}}

实现了绘制原图功能的hxd会发现,图像在窗体的打印十分缓慢,这是因为IO与底层GPU速度不匹配造成的,此时我们进行的是一个一个像素的数据传输,导致图片加载缓慢,关于解决方法我会在后面介绍(在计算时将所有的像素点存入BufferedImage对象,进行全内存操作,然后再绘制)。

(3)绘制灰度图像

实现灰度很简单,三原色R、G、B取相同的值即可以实现灰度,我们一般取平均值。

//绘制灰度图像public void drawGrayImage(int[][] imgArr) {for(int i = 0; i < imgArr.length; i++) {for(int j = 0; j < imgArr[0].length; j++) {int rgb = imgArr[i][j];int red = (rgb >> 16) & 0xFF;int green = (rgb >> 8) & 0xFF;int blue = (rgb >> 0) & 0xFF;int gray = (red + green + blue) / 3;Color color = new Color(gray, gray, gray);gr.setColor(color);gr.drawLine(i, j, i, j);}}}

也可以通过如下代码来获取R、G、B的值:

Color c = new Color(rgb);
int r = c.getRed();
int g = c.getGreen();
int b = c.getBlue();

(4)绘制马赛克图像

马赛克图像的实现则是通过扩大像素点-->画方格,来实现的。

    //绘制马赛克图像public void drawMosaicImage(int[][] imgArr) {for(int i = 0; i < imgArr.length; i+=16) {for(int j = 0; j < imgArr[0].length; j+=16) {Color c2 = new Color(imgArr[i][j]);//画方格子,实现方格状马赛克gr.setColor(c2);gr.fillRect(i, j, 16, 16);}}}

(5)绘制珠纹化图像

珠纹化则是将绘制方格改成了绘制圆;

//绘制珠纹化图像public void drawPearlImage(int[][] imgArr) {for(int i = 0; i < imgArr.length; i+=10) {for(int j = 0; j < imgArr[0].length; j+=10) {int rgb = imgArr[i][j];int red = (rgb >> 16) & 0xFF;int green = (rgb >> 8) & 0xFF;int blue = (rgb >> 0) & 0xFF;Color color = new Color(red, green, blue);gr.setColor(color);gr.fillOval(i, j, 8, 8);}}}

(6)绘制融合图像

将两个图像融合就是将两个图像的RBG值按照一定的比例组成一个新的RGB的值;

    //绘制融合图像   public void drawMixImage(int[][] imgArr, int[][] imgArr2) {int w = Math.min(imgArr.length, imgArr2.length);int h = Math.min(imgArr[0].length, imgArr2[0].length);double pro_1 = 0.4;double pro_2 = 0.6;for(int i = 0; i < w; i++) {for(int j = 0; j < h; j++) {int rgb = imgArr[i][j];int red = (rgb >> 16) & 0xFF;int green = (rgb >> 8) & 0xFF;int blue = (rgb >> 0) & 0xFF;int rgb2 = imgArr2[i][j];int red2 = (rgb2 >> 16) & 0xFF;int green2 = (rgb2 >> 8) & 0xFF;int blue2 = (rgb2 >> 0) & 0xFF;int newRed = (int)(pro_1*red + pro_2*red2);int newGreen = (int)(pro_1*green + pro_2*green2);int newBlue = (int)(pro_1*blue + pro_2*blue2);Color color = new Color(newRed, newGreen, newBlue);gr.setColor(color);gr.fillRect(i, j, 1, 1);}}       }

(7)绘制轮廓图像

 //绘制轮廓图像public void drawOutlinesImage(int[][] imgArr) {//-3防止越界for(int i = 0; i < imgArr.length-3; i++) {for(int j = 0; j < imgArr[0].length-3; j++) {int rgb = imgArr[i][j];int red = (rgb >> 16) & 0xFF;int green = (rgb >> 8) & 0xFF;int blue = (rgb >> 0) & 0xFF;int gray = (red + green + blue) / 3;// 获取三个单通道的RGB值int rgb2 = imgArr[i+3][j+3];int red2 = (rgb2 >> 16) & 0xFF;int green2 = (rgb2 >> 8) & 0xFF;int blue2 = (rgb2 >> 0) & 0xFF;int gray2 = (red2 + green2 + blue2) / 3;//边缘检测if(Math.abs(gray-gray2) > 5) {gr.setColor(Color.WHITE);} else {gr.setColor(Color.BLACK);}gr.drawLine(i, j, i, j);}}}

(8)绘制黑白版画

rgb值大于某值画黑,小于某值画白;

public void drawBlackWhiteImage(int[][] imgArr) {for(int i = 0; i < imgArr.length; i++) {for(int j = 0; j < imgArr[0].length; j++) {int rgb = imgArr[i][j];int red = (rgb >> 16) & 0xFF;int green = (rgb >> 8) & 0xFF;int blue = (rgb >> 0) & 0xFF;int gray = (red + green + blue) / 3;if(gray > 100) {gr.setColor(Color.WHITE);} else {gr.setColor(Color.BLACK);}gr.drawLine(i, j, i, j);}}}

(9)绘制锐化图像

高斯模糊与图像卷积滤波,这个博客对于图像卷积相关知识讲得还不错,hxdm可以看看;卷积算法就是通过不同的卷积核来处理图像二维数组,从而获取不同的特征图像;

public void drawSharpenImage(int[][] imgArr) {//锐化卷积核float[][] kArr = {{-1, -1, -1},{-1, 9, -1},{-1, -1, -1}};//开始卷积计算//tem保存单次卷积核数组乘积的值int[][] tem = new int[kArr.length][kArr[0].length];//valid为卷积后得到的特征图像的保存数组int validWidth = imgArr[0].length - kArr[0].length + 1;int validHeihgt = imgArr.length - kArr.length + 1;int[][] valid = new int[validHeihgt][validWidth];//卷积for(int i = 0; i < validHeihgt; i++) {for(int j = 0; j < validWidth; j++) {for(int y = 0; y < kArr.length; y++) {for(int z = 0; z < kArr[0].length; z++) {tem[y][z] = (int)(imgArr[i+y][j+z] * kArr[y][z]);}}int k = 0;for(int y = 0; y < kArr.length; y++) {for(int z = 0; z < kArr[0].length; z++) {k += tem[y][z];}}if(k < 0) {k = 0;}else if(k > 255){k = 255;}valid[i][j] = (byte)k;}}//打印卷积后的图像for(int i = 0; i < valid.length; i++) {for(int j = 0; j < valid[0].length; j++) {Color c = new Color(valid[i][j]);gr.setColor(c);gr.drawLine(i, j, i, j);}}}

此代码我们卷积的对象是保存整个rgb值的二维数组,可以发现,锐化的效果并不理想,作为改进,我们可以把R、G、B三个通道分别卷积然后合成新的图像,效果会更好,后文会讲解。

(10)绘制高斯模糊图像

关于高斯模糊,我们则是通过高斯函数来计算权重矩阵,从而计算模糊值,然后进行高斯模糊。特别要注意边界值的处理,详细情况可以参考(9)中所附链接。

三.锐化、均值模糊、浮雕

这三种图像处理的方式都是通过不同的卷积核对图像进行卷积。(R、G、B三个通道分别卷积然后合成新的图像)。

如下是他们的卷积核,可以按照需求修改,不同的卷积核会有不同特征,更大的卷积核效果会更明显。

//卷积核//1.锐化卷积核float[][] kArr_1 = {{-1, -1, -1},{-1, 9, -1},{-1, -1, -1}};//2.浮雕卷积核float[][] kArr_2 = {{-1, -1, 0},{-1, 0, 1},{0, 1, 1}};//3.均值模糊卷积核float[][] kArr_3 = {{0, 0.2f, 0},{0.2f, 0, 0.2f},{0, 0.2f, 0}};

RGB三通道分别卷积的代码如下:

    /**** @param imgArr 存储图像的二维数组* @param kArr 卷积核二维数组* @return buffimg 卷积后的BufferedImage类型图像*/public BufferedImage drawConvolutionImage(int[][] imgArr, float[][] kArr) {BufferedImage buffimg = new BufferedImage(imgArr.length, imgArr[0].length, BufferedImage.TYPE_INT_ARGB);Graphics bfg = buffimg.getGraphics();//三个tem分别保存RGB单次卷积核数组乘积的值int[][] temRed = new int[kArr.length][kArr[0].length];int[][] temGreen = new int[kArr.length][kArr[0].length];int[][] temBlue = new int[kArr.length][kArr[0].length];//三个二维数组分别保存三原色的像素int[][] redArr = new int[imgArr.length][imgArr[0].length];int[][] greenArr = new int[imgArr.length][imgArr[0].length];int[][] blueArr = new int[imgArr.length][imgArr[0].length];for(int i = 0; i < imgArr.length; i++) {for(int j = 0; j < imgArr[0].length; j++) {int rgb = imgArr[i][j];redArr[i][j] = (rgb >> 16) & 0xFF;greenArr[i][j] = (rgb >> 8) & 0xFF;blueArr[i][j] = (rgb >> 0) & 0xFF;}}//三个valid二维数组分别保存卷积后特征图像的rgb值int validWidth = imgArr[0].length - kArr[0].length + 1;int validHeihgt = imgArr.length - kArr.length + 1;int[][] validRed = new int[validHeihgt][validWidth];int[][] validGreen = new int[validHeihgt][validWidth];int[][] validBlue = new int[validHeihgt][validWidth];//卷积for(int i = 0; i < validHeihgt; i++) {for(int j = 0; j < validWidth; j++) {for(int y = 0; y < kArr.length; y++) {for(int z = 0; z <kArr[0].length; z++) {temRed[y][z] = (int)(redArr[i+y][j+z] * kArr[y][z]);temGreen[y][z] = (int)(greenArr[i+y][j+z] * kArr[y][z]);temBlue[y][z] = (int)(blueArr[i+y][j+z] * kArr[y][z]);}}int kRed = 0;int kGreen = 0;int kBlue = 0;for(int y = 0; y < kArr.length; y++) {for(int z = 0; z < kArr[0].length; z++) {kRed += temRed[y][z];kGreen += temGreen[y][z];kBlue += temBlue[y][z];}}if(kRed < 0) {kRed = 0;}else if(kRed > 255){kRed = 255;}if(kGreen < 0) {kGreen = 0;}else if(kGreen > 255){kGreen = 255;}if(kBlue < 0) {kBlue = 0;}else if(kBlue > 255){kBlue = 255;}validRed[i][j] = kRed;validGreen[i][j] = kGreen;validBlue[i][j] = kBlue;}}//打印卷积后的图像for(int i = 0; i < validHeihgt; i++) {for(int j = 0; j < validWidth; j++) {Color c = new Color(validRed[i][j], validGreen[i][j], validBlue[i][j]);bfg.setColor(c);bfg.drawLine(i, j, i, j);}}//窗体上绘制gr.drawImage(buffimg, 0, 0, null);return buffimg;}

图像处理Image Processing(一)相关推荐

  1. 图像处理(Image Processing) ---------- 直方图均衡化 (Equalization)(C#实现)

    说到直方图均衡化,首先提一提概率论的知识. 概率论: 离散型随机变量:能用日常使用的量词度量的随机变量. 概率函数:形如  P(x = 1) = 1/6; 概率分布: 概率分布函数: . (累积概率函 ...

  2. 图像处理(Image Processing) ---------- 灰阶位图分割 (bit-plane slicing)(浮水印)(C#实现)

    灰阶图像,通常每个Pixel是由8个bit构成,即有256种变化.然而每个Pixel的8个bit,从最高位到最低位携带的信息量是逐渐递减的.可以看下面几幅图:  右边是原图,下面就是将灰阶图每一个pi ...

  3. 图像处理(Image Processing) ---------- 对比拉伸 (Contrast Stretching)(C#实现)

    对比拉伸也就是灰度拉伸,主要是通过改善图像灰度级的动态范围,來改善的图像品质. 如下图:将原灰度集中拉升到均匀提升图像品质. 对比拉伸的本质是使用分段函数进行的线性变换,如下图:输出图像通过牺牲 0 ...

  4. CxImage图像处理类库

    转自:http://blog.csdn.net/byxdaz/archive/2009/04/10/4061324.aspx CxImage是一个可以用于MFC 的C++图像处理类库类,它可以打开,保 ...

  5. 图像处理分类、一般流程与算法

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达本文转自|新机器视觉 常用的图像处理算法:数字图像处理基础.遥感数字 ...

  6. 图像处理技术(二)滤波去噪

    在图像处理领域中,在真正的应用过程前,通常需要对图像进行预先处理,达到去除干扰项的目的.滤波去噪就是其中的一项图像预处理工作. 在.NET下常用OpenCV进行图像处理工作,常用的.NET下的Open ...

  7. 数字图像与数字图像处理

    数字图像与数字图像处理 1.基本概念 (1)图:是物体反射或者透射电磁波的分布. (2)像:是人的视觉系统对接收的图信息在大脑 中形成的印象. (3)图像(image):是"图"和 ...

  8. image pil 图像保存_如何利用python中的PIL库做图像处理?

    自从这个世界上出现了Python编程,一切都好像有了新的思路与进展,比如人工智能,还有我们常用的PS,你可知道Python也可以做图像处理,用的就是PIL库,还没有用过的,还没有发现的,还没有实现过的 ...

  9. Java图像处理方面的工具库和开发包

    Java图像处理类库Java Image Filters Java Image Filters 是由 Jhlabs 开发的一组用来处理 Java 图像的类库,提供各种常用的图像处理效果,例如反转色.扭 ...

最新文章

  1. Linux系统Logrotate服务介绍
  2. Zuul路由的strip-prefix与order
  3. Java购物车前端代码_JavaWeb后台购物车类实现代码详解
  4. 微信小程序+java后台
  5. Tableau 自定义调色板及应用全流程讲解【保姆级】
  6. 计算机控制液压同步顶升系统,BOLTING博霆1600吨PLC控制全自动同步顶升系统(数控智能油缸同步控制系统)技术特点...
  7. VMware ESXI7.0的安装与配置(全过程超详细含中英文对照,附应知必会的理论基础和常见故障解决方案)
  8. python你好代码-AI人工智能Python实现简单人机对话:你好,人类
  9. 重置kubernetes集群
  10. USACO--3.2Feed Ratios
  11. win32 打印机任务管理的 node 模块 (3)详解Win32 Spooler API 获取打印机列表及状态
  12. pandas_数据处理分析基本
  13. 拉马车 的游戏 c语言编程,蓝桥杯-拉马车(C语言)
  14. 开区网站打开自动播放音乐的添加跟修改教程
  15. 数据结构一线性表 (顺序表、单链表、双链表)
  16. 将VMware 虚拟磁盘文件vmdk直接挂到win系统下的方法
  17. 6_计算机网络_应用层-HTTP-DNS-跳板机
  18. ORACLE日期函数大全!
  19. ionic环境配置,生成apk
  20. 虚拟资源小程序变现/知识付费小程序变现源码

热门文章

  1. 有没有一个桌面日历点击某天就可以直接填写便签内容
  2. 淘宝乐视奥比中光深度摄像头不显示RGB图像终极解决办法
  3. 清华大学java_清华大学出版社-图书详情-《Java语言程序设计(第3版)》
  4. mysql gbk编码 字节数,mysql中utf-8编码数据库转换成GBK编码的问题
  5. flash春雷闪电效果
  6. WM6 Rapi 开发(一) 准备工作
  7. 用心制作之Google Nexus最详细刷机方法——小白也能看得懂的刷机教程
  8. reportviewer控件mysql_ReportViewer不连接数据库,自定义DataSet导出到报表
  9. DUBBO本地搭建及小案例
  10. Oracle Drop误删表、Delete误删表数据后恢复方法