- Java 数字图像处理
- DIP - 首页
- DIP - 简介
- DIP - Java BufferedImage 类
- DIP - 图像下载与上传
- DIP - 图像像素
- DIP - 灰度转换
- DIP - 增强图像对比度
- DIP - 增强图像亮度
- DIP - 增强图像锐度
- DIP - 图像压缩技术
- DIP - 添加图像边框
- DIP - 图像金字塔
- DIP - 基本阈值化
- DIP - 图像形状转换
- DIP - 高斯滤波器
- DIP - 盒式滤波器
- DIP - 腐蚀与膨胀
- DIP - 水印
- DIP - 理解卷积
- DIP - Prewitt算子
- DIP - Sobel算子
- DIP - Kirsch算子
- DIP - Robinson算子
- DIP - Laplacian算子
- DIP - 加权平均滤波器
- DIP - 创建缩放效果
- DIP - 开源库
- DIP - OpenCV 简介
- DIP - OpenCV 灰度转换
- DIP - 色彩空间转换
- DIP 有用资源
- DIP - 快速指南
- DIP - 有用资源
- DIP - 讨论
Java 数字图像处理 - 快速指南
Java DIP - 简介
数字图像处理 (DIP) 使用数字计算机处理数字图像。它是信号与系统的一个子领域,但特别关注图像。DIP 专注于开发能够对图像进行处理的计算机系统。此类系统的输入是数字图像。系统使用高效算法处理图像,并输出图像。
Java 是一种高级编程语言,在现代世界中被广泛使用。它可以使用各种函数有效地支持和处理数字图像处理。
Java BufferedImage 类
Java 的 BufferedImage
类是 Image 类的子类。它用于处理和操作图像数据。BufferedImage
由图像数据的 ColorModel 组成。所有 BufferedImage
对象的左上角坐标均为 (0, 0)。
构造函数
此类支持三种类型的构造函数。
第一个构造函数使用指定的 ColorModel 和 Raster 构造一个新的 BufferedImage
。
BufferedImage(ColorModel cm, WritableRaster raster, boolean isRasterPremultiplied, Hashtable<?,?> properties)
第二个构造函数构造一个预定义图像类型之一的 BufferedImage
。
BufferedImage(int width, int height, int imageType)
第三个构造函数构造一个预定义图像类型之一的 BufferedImage
:TYPE_BYTE_BINARY 或 TYPE_BYTE_INDEXED。
BufferedImage(int width, int height, int imageType, IndexColorModel cm)
序号 | 方法及描述 |
---|---|
1 |
copyData(WritableRaster outRaster) 它计算 |
2 |
getColorModel() 它返回图像的 ColorModel 类的对象。 |
3 |
getData() 它将图像作为单个大图块返回。 |
4 |
getData(Rectangle rect) 它计算并返回 |
5 |
getGraphics() 此方法返回 Graphics2D,保留向后兼容性。 |
6 |
getHeight() 它返回 |
7 |
getMinX() 它返回此 |
8 |
getMinY() 它返回此 |
9 |
getRGB(int x, int y) 它以默认 RGB 颜色模型 (TYPE_INT_ARGB) 和默认 sRGB 颜色空间返回一个整数像素。 |
10 |
getType() 它返回图像类型。 |
示例
以下示例演示了 java BufferedImage
类的用法,该类使用 Graphics 对象在屏幕上绘制一些文本:
import java.awt.Graphics; import java.awt.Image; import java.awt.image.BufferedImage; import javax.swing.JFrame; import javax.swing.JPanel; public class Test extends JPanel { public void paint(Graphics g) { Image img = createImageWithText(); g.drawImage(img, 20,20,this); } private Image createImageWithText() { BufferedImage bufferedImage = new BufferedImage(200,200,BufferedImage.TYPE_INT_RGB); Graphics g = bufferedImage.getGraphics(); g.drawString("www.tutorialspoint.com", 20,20); g.drawString("www.tutorialspoint.com", 20,40); g.drawString("www.tutorialspoint.com", 20,60); g.drawString("www.tutorialspoint.com", 20,80); g.drawString("www.tutorialspoint.com", 20,100); return bufferedImage; } public static void main(String[] args) { JFrame frame = new JFrame(); frame.getContentPane().add(new Test()); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(200, 200); frame.setVisible(true); } }
输出
执行给定代码时,将看到以下输出:
下载与上传图像
在本章中,我们将了解如何从互联网下载图像,对图像执行一些图像处理技术,然后再次将处理后的图像上传到服务器。
下载图像
为了从网站下载图像,我们使用名为 URL 的 java 类,该类可以在 java.net 包中找到。其语法如下:
String website = "https://tutorialspoint.com"; URL url = new URL(website);
除了上述方法外,URL 类中还提供了其他方法,简要描述如下:
序号 | 方法及描述 |
---|---|
1 |
public String getPath() 它返回 URL 的路径。 |
2 |
public String getQuery() 它返回 URL 的查询部分。 |
3 |
public String getAuthority() 它返回 URL 的权限。 |
4 |
public int getPort() 它返回 URL 的端口。 |
5 |
public int getDefaultPort() 它返回 URL 协议的默认端口。 |
6 |
public String getProtocol() 它返回 URL 的协议。 |
7 |
public String getHost() 它返回 URL 的主机。 |
示例
以下示例演示了如何使用 java URL 类从互联网下载图像:
import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; public class Download { public static void main(String[] args) throws Exception { try{ String fileName = "digital_image_processing.jpg"; String website = "https://tutorialspoint.com/java_dip/images/"+fileName; System.out.println("Downloading File From: " + website); URL url = new URL(website); InputStream inputStream = url.openStream(); OutputStream outputStream = new FileOutputStream(fileName); byte[] buffer = new byte[2048]; int length = 0; while ((length = inputStream.read(buffer)) != -1) { System.out.println("Buffer Read of length: " + length); outputStream.write(buffer, 0, length); } inputStream.close(); outputStream.close(); } catch(Exception e) { System.out.println("Exception: " + e.getMessage()); } } }
输出
执行上述操作时,将看到以下输出。
它将从服务器下载以下图像。
上传图像
让我们看看如何将图像上传到 Web 服务器。我们将 BufferedImage 转换为字节数组以将其发送到服务器。
我们使用 Java 类 ByteArrayOutputStream,该类可以在 java.io 包中找到。其语法如下:
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(image, "jpg", baos);
为了将图像转换为字节数组,我们使用 ByteArrayOutputStream 类的 toByteArray() 方法。其语法如下:
byte[] bytes = baos.toByteArray();
除了上述方法外,ByteArrayOutputStream 类中还提供了其他方法,简要描述如下:
序号 | 方法及描述 |
---|---|
1 |
public void reset() 此方法将字节数组输出流的有效字节数重置为零,以便丢弃流中累积的所有输出。 |
2 |
public byte[] toByteArray() 此方法创建一个新分配的字节数组。其大小将是输出流的当前大小,缓冲区的内容将复制到其中。它返回输出流的当前内容作为字节数组。 |
3 |
public String toString() 将缓冲区内容转换为字符串。翻译将根据默认字符编码进行。它返回从缓冲区内容翻译而来的字符串。 |
4 |
public void write(int w) 它将指定的数组写入输出流。 |
5 |
public void write(byte []b, int of, int len) 它将从偏移量 off 开始的 len 个字节写入流。 |
6 |
public void writeTo(OutputStream outSt) 它将此流的全部内容写入指定的流参数。 |
示例
以下示例演示了如何使用 ByteArrayOutputStream 将图像上传到服务器:
客户端代码
import javax.swing.*; import java.net.*; import java.awt.image.*; import javax.imageio.*; import java.io.*; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; public class Client{ public static void main(String args[]) throws Exception{ Socket soc; BufferedImage img = null; soc=new Socket("localhost",4000); System.out.println("Client is running. "); try { System.out.println("Reading image from disk. "); img = ImageIO.read(new File("digital_image_processing.jpg")); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ImageIO.write(img, "jpg", baos); baos.flush(); byte[] bytes = baos.toByteArray(); baos.close(); System.out.println("Sending image to server. "); OutputStream out = soc.getOutputStream(); DataOutputStream dos = new DataOutputStream(out); dos.writeInt(bytes.length); dos.write(bytes, 0, bytes.length); System.out.println("Image sent to server. "); dos.close(); out.close(); } catch (Exception e) { System.out.println("Exception: " + e.getMessage()); soc.close(); } soc.close(); } }
服务器代码
import java.net.*; import java.io.*; import java.awt.image.*; import javax.imageio.*; import javax.swing.*; class Server { public static void main(String args[]) throws Exception{ ServerSocket server=null; Socket socket; server = new ServerSocket(4000); System.out.println("Server Waiting for image"); socket = server.accept(); System.out.println("Client connected."); InputStream in = socket.getInputStream(); DataInputStream dis = new DataInputStream(in); int len = dis.readInt(); System.out.println("Image Size: " + len/1024 + "KB"); byte[] data = new byte[len]; dis.readFully(data); dis.close(); in.close(); InputStream ian = new ByteArrayInputStream(data); BufferedImage bImage = ImageIO.read(ian); JFrame f = new JFrame("Server"); ImageIcon icon = new ImageIcon(bImage); JLabel l = new JLabel(); l.setIcon(icon); f.add(l); f.pack(); f.setVisible(true); } }
输出
客户端输出
执行客户端代码时,客户端上会出现以下输出:
服务器端输出
执行服务器代码时,服务器端会出现以下输出:
收到图像后,服务器显示图像如下:
Java DIP - 图像像素
图像包含一个二维像素数组。实际上,正是这些像素的值构成了图像。通常,图像可以是彩色或灰度的。
在 Java 中,BufferedImage 类用于处理图像。您需要调用 BufferedImage 类的 getRGB() 方法来获取像素的值。
获取像素值
可以使用以下语法接收像素值:
Color c = new Color(image.getRGB(j, i));
获取 RGB 值
getRGB() 方法以行和列索引作为参数,并返回相应的像素。对于彩色图像,它返回三个值,即 (红色、绿色、蓝色)。可以按如下方式获取它们:
c.getRed(); c.getGreen(); c.getBlue();
获取图像的宽度和高度
可以通过调用 BufferedImage 类的 getWidth() 和 getHeight() 方法来获取图像的高度和宽度。其语法如下:
int width = image.getWidth(); int height = image.getHeight();
除了这些方法外,BufferedImage 类还支持其他方法。它们简要描述如下:
序号 | 方法及描述 |
---|---|
1 |
copyData(WritableRaster outRaster) 它计算 BufferedImage 的任意矩形区域,并将其复制到指定的 WritableRaster 中。 |
2 |
getColorModel() 它返回图像的 ColorModel。 |
3 |
getData() 它将图像作为单个大图块返回。 |
4 |
getData(Rectangle rect) 它计算并返回 BufferedImage 的任意区域。 |
5 |
getGraphics() 此方法返回 Graphics2D,但此处是为了向后兼容性。 |
6 |
getHeight() 它返回 BufferedImage 的高度。 |
7 |
getMinX() 它返回此 BufferedImage 的最小 x 坐标。 |
8 |
getMinY() 它返回此 BufferedImage 的最小 y 坐标。 |
9 |
getRGB(int x, int y) 它以默认 RGB 颜色模型 (TYPE_INT_ARGB) 和默认 sRGB 颜色空间返回一个整数像素。 |
10 |
getType() 它返回图像类型。 |
示例
以下示例演示了如何使用 java BufferedImage 类显示大小为 (100 x 100) 的图像的像素:
import java.awt.*; import java.awt.image.BufferedImage; import java.io.*; import javax.imageio.ImageIO; import javax.swing.JFrame; class Pixel { BufferedImage image; int width; int height; public Pixel() { try { File input = new File("blackandwhite.jpg"); image = ImageIO.read(input); width = image.getWidth(); height = image.getHeight(); int count = 0; for(int i=0; i<height; i++) { for(int j=0; j<width; j++) { count++; Color c = new Color(image.getRGB(j, i)); System.out.println("S.No: " + count + " Red: " + c.getRed() +" Green: " + c.getGreen() + " Blue: " + c.getBlue()); } } } catch (Exception e) {} } static public void main(String args[]) throws Exception { Pixel obj = new Pixel(); } }
输出
执行上述示例时,它将打印以下图像的像素:
原始图像
像素输出
如果向下滚动输出,将看到以下模式:
Java DIP - 灰度转换
为了将彩色图像转换为灰度图像,您需要使用 File 和 ImageIO 对象读取图像的像素或数据,并将图像存储在 BufferedImage 对象中。其语法如下:
File input = new File("digital_image_processing.jpg"); BufferedImage image = ImageIO.read(input);
此外,使用 getRGB() 方法获取像素值,并对其执行 GrayScale() 方法。getRGB() 方法以行和列索引作为参数。
Color c = new Color(image.getRGB(j, i)); int red = (c.getRed() * 0.299); int green =(c.getGreen() * 0.587); int blue = (c.getBlue() *0.114);
除了这三种方法外,Color 类中还提供了其他方法,简要描述如下:
序号 | 方法及描述 |
---|---|
1 |
brighter() 它创建一个新的 Color,它是此 Color 的更亮版本。 |
2 |
darker() 它创建一个新的 Color,它是此 Color 的更暗版本。 |
3 |
getAlpha() 它返回 0-255 范围内的 alpha 分量。 |
4 |
getHSBColor(float h, float s, float b) 它根据 HSB 颜色模型的指定值创建一个 Color 对象。 |
5 |
HSBtoRGB(float hue, float saturation, float brightness) 它将 HSB 模型指定的颜色的分量转换为默认 RGB 模型的等效值集。 |
6 |
toString() 它返回此 Color 的字符串表示形式。 |
最后一步是将这三个值全部加起来,并将其重新设置为相应的像素值。其语法如下:
int sum = red+green+blue; Color newColor = new Color(sum,sum,sum); image.setRGB(j,i,newColor.getRGB());
示例
以下示例演示了如何使用 Java BufferedImage 类将图像转换为灰度:
import java.awt.*; import java.awt.image.BufferedImage; import java.io.*; import javax.imageio.ImageIO; import javax.swing.JFrame; public class GrayScale { BufferedImage image; int width; int height; public GrayScale() { try { File input = new File("digital_image_processing.jpg"); image = ImageIO.read(input); width = image.getWidth(); height = image.getHeight(); for(int i=0; i<height; i++) { for(int j=0; j<width; j++) { Color c = new Color(image.getRGB(j, i)); int red = (int)(c.getRed() * 0.299); int green = (int)(c.getGreen() * 0.587); int blue = (int)(c.getBlue() *0.114); Color newColor = new Color(red+green+blue, red+green+blue,red+green+blue); image.setRGB(j,i,newColor.getRGB()); } } File ouptut = new File("grayscale.jpg"); ImageIO.write(image, "jpg", ouptut); } catch (Exception e) {} } static public void main(String args[]) throws Exception { GrayScale obj = new GrayScale(); } }
输出
执行给定示例时,它会将图像 digital_image_processing.jpg 转换为等效的灰度图像,并将其写入硬盘,文件名 grayscale.jpg。
原始图像
灰度图像
Java DIP - 增强图像对比度
在本章中,我们将学习如何使用直方图均衡来增强图像的对比度。
我们使用 OpenCV 函数 equalizeHist() 方法。它可以在 Imgproc 包中找到。其语法如下:
Imgproc.equalizeHist(source, destination);
参数描述如下:
序号 | 参数及描述 |
---|---|
1 |
源 它是 8 位单通道源图像。 |
2 |
目标 它是目标图像。 |
除了 equalizeHist() 方法外,Imgproc 类还提供了其他方法。它们简要描述如下:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int ddepth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类增强图像的对比度:
import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class Main { static int width; static int height; static double alpha = 2; static double beta = 50; public static void main( String[] args ) { try { System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("grayscale.jpg", Highgui.CV_LOAD_IMAGE_GRAYSCALE); Mat destination = new Mat(source.rows(),source.cols(),source.type()); Imgproc.equalizeHist(source, destination); Highgui.imwrite("contrast.jpg", destination); } catch (Exception e) { System.out.println("error: " + e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
增强对比度图像
Java DIP - 增强图像亮度
本章中,我们将通过将图像的每个像素乘以一个 alpha 值并加上另一个 beta 值来增强图像的亮度。
我们使用OpenCV函数convertTo来自动执行上述操作。它可以在Mat包中找到。其语法如下所示:
int alpha = 2; int beta = 50; sourceImage.convertTo(destination, rtype , alpha, beta);
参数描述如下:
序号 | 参数及描述 |
---|---|
1 |
目标图像 它是目标图像。 |
2 |
输出数据类型 它是所需的输出矩阵类型,或者更确切地说是深度,因为通道数与输入相同。如果 rtype 为负,则输出矩阵将与输入具有相同的类型。 |
3 |
alpha 它是可选的缩放因子。 |
4 |
beta 它是添加到缩放值中的可选增量。 |
除了 convertTo 方法外,Mat 类还提供了其他方法。下面简要介绍一下:
序号 | 方法及描述 |
---|---|
1 |
adjustROI(int dtop, int dbottom, int dleft, int dright) 它调整子矩阵在父矩阵中的大小和位置。 |
2 |
copyTo(Mat m) 它将矩阵复制到另一个矩阵。 |
3 |
diag() 它从矩阵中提取对角线,或创建一个对角矩阵。 |
4 |
dot(Mat m) 它计算两个向量的点积。 |
5 |
reshape(int cn) 它更改 2D 矩阵的形状和/或通道数,而无需复制数据。 |
6 |
submat(Range rowRange, Range colRange) 它提取一个矩形子矩阵。 |
示例
以下示例演示了如何使用 Mat 类来增强图像的亮度:
import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; public class Main { static int width; static int height; static double alpha = 2; static double beta = 50; public static void main( String[] args ) { try{ System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("digital_image_processing.jpg",Highgui.CV_LOAD_IMAGE_COLOR); Mat destination = new Mat(source.rows(),source.cols(), source.type()); source.convertTo(destination, -1, alpha, beta); Highgui.imwrite("brightWithAlpha2Beta50.jpg", destination); } catch (Exception e) { System.out.println("error:" + e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
增强亮度图像 (Alpha=1 & Beta=50)
增强亮度图像 (Alpha=2 & Beta=50)
Java 数字图像处理 - 增强图像锐度
本章中,我们将学习如何使用高斯滤波器来提高图像的锐度。
首先,我们使用OpenCV函数GaussianBlur。它可以在Imgproc包中找到。其语法如下所示:
Imgproc.GaussianBlur(source, destination, new Size(0,0), sigmaX);
参数如下所示:
序号 | 参数及描述 |
---|---|
1 |
源图像 它是源图像。 |
2 |
目标图像 它是目标图像。 |
3 |
尺寸 它是高斯核的大小。 |
4 |
sigmaX 它是高斯核在 X 方向上的标准差。 |
此外,我们使用OpenCV函数addWeighted将图像水印应用于图像。它可以在Core包中找到。其语法如下所示:
Core.addWeighted(InputArray src1, alpha, src2, beta, gamma, OutputArray dst);
该函数的参数如下所示:
序号 | 参数及描述 |
---|---|
1 |
src1 它是第一个输入数组。 |
2 |
alpha 它是第一个数组元素的权重。 |
3 |
src2 它是第二个输入数组,其大小和通道数与 src1 相同。 |
4 |
Beta 它是第二个数组元素的权重。 |
5 |
gamma 它是添加到每个和中的标量。 |
6 |
dst 它是输出数组,其大小和通道数与输入数组相同。 |
除了 GaussianBlur 方法外,Imgproc 类还提供了其他方法。下面简要介绍一下:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int depth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 和 Core 类来对图像进行锐化:
import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.Size; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class Main { public static void main( String[] args ) { try{ System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("digital_image_processing.jpg", Highgui.CV_LOAD_IMAGE_COLOR); Mat destination = new Mat(source.rows(),source.cols(),source.type()); Imgproc.GaussianBlur(source, destination, new Size(0,0), 10); Core.addWeighted(source, 1.5, destination, -0.5, 0, destination); Highgui.imwrite("sharp.jpg", destination); } catch (Exception e) { } } }
输出
执行给定代码时,将看到以下输出:
原始图像
锐化图像
Java 数字图像处理 - 图像压缩技术
图像可以通过 Java 轻松压缩和存储。图像压缩涉及将图像转换为 jpg 并存储。
为了压缩图像,我们读取图像并将其转换为 BufferedImage 对象。
此外,我们从 ImageIO 类中找到的getImageWritersByFormatName()方法获取一个 ImageWriter。从这个 ImageWriter 中,创建一个ImageWriteParam对象。其语法如下所示:
Iterator<ImageWriter> list = ImageIO.getImageWritersByFormatName("jpg"); ImageWriteParam obj = writer_From_List.getDefaultWriteParam();
从这个 ImageWriteParam 对象中,您可以通过调用这两个方法来设置压缩,这两个方法是setCompressionMode()和setCompressionQuality()。它们的语法如下所示:
obj.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); obj.setCompressionQuality(0.05f);
setCompressionMode()方法将 Mode_EXPLICIT 作为参数。下面简要介绍其他一些模式:
序号 | 模式 |
---|---|
1 |
MODE_DEFAULT 它是一个常数值,可以传递给方法以启用该功能以供将来写入。 |
2 |
MODE_DISABLED 它是一个常数值,可以传递给方法以禁用该功能以供将来写入。 |
3 |
MODE_EXPLICIT 它是一个常数值,可以传递给方法以启用该功能以供将来写入。 |
除了压缩方法外,ImageWriteParam 类还提供了其他方法。下面简要介绍一下:
序号 | 方法及描述 |
---|---|
1 |
canOffsetTiles() 如果写入器可以在写入时执行具有非零网格偏移量的平铺,则返回 true。 |
2 |
getBitRate(float quality) 它返回一个浮点数,表示在给定质量级别下每个输入图像数据位输出数据位的估计数。 |
3 |
getLocale() 它返回当前设置的区域设置,如果仅支持默认区域设置,则返回 null。 |
4 |
isCompressionLossless() 如果当前压缩类型提供无损压缩,则返回 true。 |
5 |
unsetCompression() 它删除任何以前的压缩类型和质量设置。 |
6 |
unsetTiling() 它删除通过调用 setTiling 指定的任何以前的图块网格参数。 |
示例
以下示例演示了如何使用 ImageWriteParam 类来压缩图像:
import java.io.*; import java.util.*; import java.awt.image.*; import javax.imageio.*; import javax.imageio.stream.ImageOutputStream; class Compression { public static void main(String[] args) throws IOException { File input = new File("digital_image_processing.jpg"); BufferedImage image = ImageIO.read(input); File compressedImageFile = new File("compress.jpg"); OutputStream os =new FileOutputStream(compressedImageFile); Iterator<ImageWriter>writers = ImageIO.getImageWritersByFormatName("jpg"); ImageWriter writer = (ImageWriter) writers.next(); ImageOutputStream ios = ImageIO.createImageOutputStream(os); writer.setOutput(ios); ImageWriteParam param = writer.getDefaultWriteParam(); param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); param.setCompressionQuality(0.05f); writer.write(null, new IIOImage(image, null, null), param); os.close(); ios.close(); writer.dispose(); } }
输出
当您执行给定的代码时,它会将图像digital_image_processing.jpg压缩到其等效的压缩图像,并将其写入硬盘,文件名compress.jpg。
原始图像
压缩图像 - 质量因子 - 0.05
压缩图像 - 质量因子 - 0.5
Java 数字图像处理 - 添加边框
本章中,我们将学习如何向图像添加不同类型的边框。
我们使用OpenCV函数copyMakeBorder。它可以在Imgproc包中找到。其语法如下所示:
Imgproc.copyMakeBorder(source,destination,top,bottom,left,right,borderType);
参数描述如下:
序号 | 参数及描述 |
---|---|
1 |
源图像 它是源图像。 |
2 |
目标图像 它是目标图像。 |
3 |
顶部 它是图像顶部边框的像素长度。 |
4 |
底部 它是图像底部边框的像素长度。 |
5 |
左边 它是图像左边边框的像素长度。 |
6 |
右边 它是图像右边边框的像素长度。 |
7 |
边框类型 它定义边框的类型。可能的边框有 BORDER_REPLICATE、BORDER_REFLECT、BORDER_WRAP、BORDER_CONSTANT 等。 |
除了 copyMakeBorder() 方法外,Imgproc 类还提供了其他方法。下面简要介绍一下:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int depth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类向图像添加边框:
import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class main { public static void main( String[] args ) { try { System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("digital_image_processing.jpg", Highgui.CV_LOAD_IMAGE_COLOR); Mat destination = new Mat(source.rows(),source.cols(),source.type()); int top, bottom, left, right; int borderType; /// Initialize arguments for the filter top = (int) (0.05*source.rows()); bottom = (int) (0.05*source.rows()); left = (int) (0.05*source.cols()); right = (int) (0.05*source.cols()); destination = source; Imgproc.copyMakeBorder(source, destination, top, bottom, left, right, Imgproc.BORDER_WRAP); Highgui.imwrite("borderWrap.jpg", destination); } catch (Exception e) { System.out.println("error: " + e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
孤立边框图像
环绕边框图像
反射边框图像
Java 数字图像处理 - 图像金字塔
图像金字塔不过是一种显示多分辨率图像的方法。最下面一层是图像的最高分辨率版本,最上面一层是图像的最低分辨率版本。图像金字塔用于处理不同尺度的图像。
本章中,我们将对图像进行一些下采样和上采样操作。
我们使用OpenCV函数pyrUp和pyrDown。它们可以在Imgproc包中找到。其语法如下所示:
Imgproc.pyrUp(source, destination, destinationSize); Imgproc.pyrDown(source, destination,destinationSize);
参数描述如下:
序号 | 参数及描述 |
---|---|
1 |
源图像 它是源图像。 |
2 |
目标图像 它是目标图像。 |
3 |
目标尺寸 它是输出图像的大小。默认情况下,它计算为 Size((src.cols*2), (src.rows*2))。 |
除了 pyrUp 和 pyrDown 方法外,Imgproc 类还提供了其他方法。下面简要介绍一下:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int depth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类对图像进行上采样和下采样操作。
import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.Size; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class main { public static void main( String[] args ) { try{ System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("digital_image_processing.jpg", Highgui.CV_LOAD_IMAGE_COLOR); Mat destination1 = new Mat(source.rows()*2, source.cols()*2,source.type()); destination1 = source; Imgproc.pyrUp(source, destination1, new Size(source.cols()*2 source.rows()*2)); Highgui.imwrite("pyrUp.jpg", destination1); source = Highgui.imread("digital_image_processing.jpg", Highgui.CV_LOAD_IMAGE_COLOR); Mat destination = new Mat(source.rows()/2,source.cols()/2, source.type()); destination = source; Imgproc.pyrDown(source, destination, new Size(source.cols()/2, source.rows()/2)); Highgui.imwrite("pyrDown.jpg", destination); } catch (Exception e) { System.out.println("error: " + e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
在原始图像上,执行了 pyrUp(上采样)和 pyrDown(下采样)。采样后的输出如下所示:
PyrUP 图像
pyrDown 图像
Java 数字图像处理 - 基本阈值化
阈值化能够以最简单的方式实现图像分割。图像分割是指将完整图像划分为一组像素,以便每个集合中的像素具有一些共同的特征。图像分割在定义对象及其边界方面非常有用。
本章中,我们将对图像执行一些基本的阈值化操作。
我们使用OpenCV函数threshold。它可以在Imgproc包中找到。其语法如下所示:
Imgproc.threshold(source, destination, thresh , maxval , type);
参数描述如下:
序号 | 参数及描述 |
---|---|
1 |
源图像 它是源图像。 |
2 |
目标图像 它是目标图像。 |
3 |
阈值 它是阈值。 |
4 |
最大值 它是将与 THRESH_BINARY 和 THRESH_BINARY_INV 阈值类型一起使用的最大值。 |
5 |
类型 可能的类型有 THRESH_BINARY、THRESH_BINARY_INV、THRESH_TRUNC 和 THRESH_TOZERO。 |
除了这些阈值化方法外,Imgproc 类还提供了其他方法。下面简要介绍一下:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int ddepth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类对图像执行阈值化操作:
import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class main { public static void main( String[] args ) { try{ System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("digital_image_processing.jpg", Highgui.CV_LOAD_IMAGE_COLOR); Mat destination = new Mat(source.rows(),source.cols(),source.type()); destination = source; Imgproc.threshold(source,destination,127,255,Imgproc.THRESH_TOZERO); Highgui.imwrite("ThreshZero.jpg", destination); } catch (Exception e) { System.out.println("error: " + e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
在上面的原始图像上,执行了一些阈值化操作,输出结果如下所示:
二值阈值
反二值阈值
零阈值
Java 数字图像处理 - 图像形状转换
可以使用 OpenCV 轻松更改图像的形状。图像可以翻转、缩放或沿四个方向中的任何一个旋转。
为了更改图像的形状,我们读取图像并将其转换为 Mat 对象。其语法如下所示:
File input = new File("digital_image_processing.jpg"); BufferedImage image = ImageIO.read(input); //convert Buffered Image to Mat.
翻转图像
OpenCV 允许三种类型的翻转代码,如下所示:
序号 | 翻转代码和描述 |
---|---|
1 |
0 0 表示,围绕 x 轴翻转。 |
2 |
1 1 表示,围绕 y 轴翻转。 |
3 |
-1 -1 表示,围绕 x 和 y 轴都翻转。 |
我们将适当的翻转代码传递给Core类中的flip()方法。其语法如下所示:
Core.flip(source mat, destination mat1, flip_code);
flip()方法接受三个参数:源图像矩阵、目标图像矩阵和翻转代码。
除了 flip 方法外,Core 类还提供了其他方法。下面简要介绍一下:
序号 | 方法及描述 |
---|---|
1 |
add(Mat src1, Mat src2, Mat dst) 它计算两个数组或数组和标量的逐元素和。 |
2 |
bitwise_and(Mat src1, Mat src2, Mat dst) 它计算两个数组或数组和标量的逐元素按位与运算。 |
3 |
bitwise_not(Mat src, Mat dst) 它反转数组的每一位。 |
4 |
circle(Mat img, Point center, int radius, Scalar color) 它绘制一个圆。 |
5 |
sumElems(Mat src) 它使用高斯滤波器模糊图像。 |
6 |
subtract(Mat src1, Scalar src2, Mat dst, Mat mask) 它计算两个数组或数组和标量之间的逐元素差。 |
示例
以下示例演示了如何使用 Core 类来翻转图像:
import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; import java.io.File; import javax.imageio.ImageIO; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.imgproc.Imgproc; public class Main { public static void main( String[] args ) { try { System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); File input = new File("digital_image_processing.jpg"); BufferedImage image = ImageIO.read(input); byte[] data = ((DataBufferByte) image.getRaster(). getDataBuffer()).getData(); Mat mat = new Mat(image.getHeight(),image.getWidth(),CvType.CV_8UC3); mat.put(0, 0, data); Mat mat1 = new Mat(image.getHeight(),image.getWidth(),CvType.CV_8UC3); Core.flip(mat, mat1, -1); byte[] data1 = new byte[mat1.rows()*mat1.cols()*(int)(mat1.elemSize())]; mat1.get(0, 0, data1); BufferedImage image1 = new BufferedImage(mat1.cols(), mat1.rows(), 5); image1.getRaster().setDataElements(0,0,mat1.cols(),mat1.rows(),data1); File ouptut = new File("hsv.jpg"); ImageIO.write(image1, "jpg", ouptut); } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } } }
输出
运行以上示例时,它会将名为digital_image_processing.jpg的图像翻转到其等效的 HSV 颜色空间图像,并将其写入硬盘,文件名flip.jpg。
原始图像
翻转后的图像
Java 数字图像处理 - 应用高斯滤波器
本章中,我们将对图像应用高斯滤波器,该滤波器可以模糊图像。我们将使用 OpenCV 函数 GaussianBlur 对图像应用高斯滤波器。它可以在 Imgproc 包中找到。其语法如下所示:
Imgproc.GaussianBlur(source, destination,Size,SigmaX);
函数参数如下所示:
序号 | 参数和描述 |
---|---|
1 |
源图像 它是源图像。 |
2 |
目标图像 它是目标图像。 |
3 |
尺寸 它是高斯核的大小。 |
4 |
SigmaX 它是高斯核在 X 方向上的标准差。 |
除了 GaussianBlur 方法外,Imgproc 类还提供了其他方法。下面简要介绍一下:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int depth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类对图像应用高斯滤波器。
import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.core.Size; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class Main { public static void main( String[] args ) { try { System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("digital_image_processing.jpg", Highgui.CV_LOAD_IMAGE_COLOR); Mat destination = new Mat(source.rows(),source.cols(),source.type()); Imgproc.GaussianBlur(source, destination,new Size(45,45), 0); Highgui.imwrite("Gaussian45.jpg", destination); } catch (Exception e) { System.out.println("Error:" + e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
当原始图像与大小为 11 和 45 的高斯滤波器进行卷积时,会看到以下输出。
大小为 11 的高斯滤波器
大小为 45 的高斯滤波器
Java 数字图像处理 - 应用方框滤波器
我们应用方框滤波器来模糊图像。方框滤波器可以是 3x3、5x5、9x9 等尺寸。
我们使用OpenCV函数filter2D对图像应用方框滤波器。它可以在Imgproc包中找到。其语法如下所示:
filter2D(src, dst, depth , kernel, anchor, delta, BORDER_DEFAULT );
函数参数如下所示:
序号 | 参数和描述 |
---|---|
1 |
源图像 它是源图像。 |
2 |
dst 它是目标图像。 |
3 |
深度 它是 dst 的深度。负值(例如 -1)表示深度与源相同。 |
4 |
内核 它是将扫描图像的内核。 |
5 |
锚点 它是锚点相对于其内核的位置。位置 Point (-1, -1) 默认表示中心。 |
6 |
增量 它是在卷积过程中添加到每个像素的值。默认值为 0。 |
7 |
BORDER_DEFAULT 我们默认使用此值。 |
除了 filter2D() 方法外,Imgproc 类还提供了其他方法。它们简要描述如下:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int depth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类将 Box 滤波器应用于灰度图像。
import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class convolution { public static void main( String[] args ) { try { int kernelSize = 9; System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("grayscale.jpg", Highgui.CV_LOAD_IMAGE_GRAYSCALE); Mat destination = new Mat(source.rows(),source.cols(),source.type()); Mat kernel = Mat.ones(kernelSize,kernelSize, CvType.CV_32F); for(int i=0; i<kernel.rows(); i++) { for(int j=0; j<kernel.cols(); j++) { double[] m = kernel.get(i, j); for(int k =0; k<m.length; k++) { m[k] = m[k]/(kernelSize * kernelSize); } kernel.put(i,j, m); } } Imgproc.filter2D(source, destination, -1, kernel); Highgui.imwrite("output.jpg", destination); } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
在这个例子中,我们用以下滤波器(内核)对我们的图像进行卷积。随着滤波器尺寸的增加,此滤波器会导致图像模糊。
此原始图像已使用大小为 5 的 Box 滤波器进行卷积,如下所示:
大小为 5 的 Box 滤波器
1/25 | 1/25 | 1/25 | 1/25 | 1/25 |
1/25 | 1/25 | 1/25 | 1/25 | 1/25 |
1/25 | 1/25 | 1/25 | 1/25 | 1/25 |
1/25 | 1/25 | 1/25 | 1/25 | 1/25 |
1/25 | 1/25 | 1/25 | 1/25 | 1/25 |
卷积后的图像(使用大小为 5 的 Box 滤波器)
卷积后的图像(使用大小为 9 的 Box 滤波器)
Java 数字图像处理 - 腐蚀和膨胀
在本章中,我们将学习应用两种非常常见的形态学运算符:膨胀和腐蚀。
我们使用 **OpenCV** 函数 **erode** 和 **dilate**。它们可以在 **Imgproc** 包中找到。其语法如下所示:
Imgproc.erode(source, destination, element); Imgproc.dilate(source, destination, element);
参数描述如下:
序号 | 参数及描述 |
---|---|
1 |
源图像 它是源图像。 |
2 |
目标图像 它是目标图像。 |
3 |
element 它是用于腐蚀和膨胀的结构元素,如果 element=Mat(),则使用 3 x 3 的矩形结构元素。 |
除了 erode() 和 dilate() 方法外,Imgproc 类还提供了其他方法。它们简要描述如下:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int depth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类对图像执行腐蚀和膨胀操作。
import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class main { public static void main( String[] args ) { try{ System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("digital_image_processing.jpg", Highgui.CV_LOAD_IMAGE_COLOR); Mat destination = new Mat(source.rows(),source.cols(),source.type()); destination = source; int erosion_size = 5; int dilation_size = 5; Mat element = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2*erosion_size + 1, 2*erosion_size+1)); Imgproc.erode(source, destination, element); Highgui.imwrite("erosion.jpg", destination); source = Highgui.imread("digital_image_processing.jpg", Highgui.CV_LOAD_IMAGE_COLOR); destination = source; Mat element1 = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(2*dilation_size + 1, 2*dilation_size+1)); Imgproc.dilate(source, destination, element1); Highgui.imwrite("dilation.jpg", destination); } catch (Exception e) { System.out.println("error:" + e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
在上面的原始图像上,执行了一些腐蚀和膨胀操作,输出结果如下所示:
腐蚀
膨胀
Java 数字图像处理 - 应用水印
在本章中,我们将学习两种在图像上应用水印的方法。这些方法是:
- 应用文本水印
- 应用图像水印
应用文本水印
我们使用 **OpenCV** 函数 **putText** 将文本水印应用于图像。它可以在 **Core** 包中找到。其语法如下所示:
Core.putText(source, Text, Point, fontFace ,fontScale , color);
该函数的参数如下所示:
序号 | 参数及描述 |
---|---|
1 |
源 它是源图像。 |
2 |
Text 它是将显示在图像上的字符串文本。 |
3 |
Point 它是文本在图像上显示的位置。 |
4 |
fontFace 字体类型。例如:FONT_HERSHEY_SIMPLEX、FONT_HERSHEY_PLAIN、FONT_HERSHEY_COMPLEX 等。 |
5 |
fontScale 它是字体缩放因子,乘以特定字体的基本大小。 |
6 |
color 它是文本颜色。 |
除了 putText 方法外,Core 类还提供了其他方法。它们简要描述如下:
序号 | 方法及描述 |
---|---|
1 |
normalize(Mat src, Mat dst, double alpha, double beta, int norm_type) 它规范化数组的范数或值范围。 |
2 |
perspectiveTransform(Mat src, Mat dst, Mat m) 它执行向量的透视矩阵变换。 |
3 |
phase(Mat x, Mat y, Mat angle) 它计算二维向量的旋转角度。 |
4 |
rectangle(Mat img, Point pt1, Point pt2, Scalar color) 它绘制一个简单的、粗的或填充的向右矩形。 |
5 |
reduce(Mat src, Mat dst, int dim, int rtype, int dtype) 它将矩阵简化为向量。 |
6 |
transform(Mat src, Mat dst, Mat m) 它执行每个数组元素的矩阵变换。 |
示例
以下示例演示了如何使用 Core 类将文本水印应用于图像。
import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class Main { public static void main( String[] args ) { try{ System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("digital_image_processing.jpg", Highgui.CV_LOAD_IMAGE_COLOR); Mat destination = new Mat(source.rows(),source.cols(), source.type()); Core.putText(source, "Tutorialspoint.com", new Point (source.rows()/2,source.cols()/2), Core.FONT_ITALIC,new Double(1),new Scalar(255)); Highgui.imwrite("watermarked.jpg", source); } catch (Exception e) { System.out.println("Error: "+e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
带文本水印的图像
在图像上应用图像水印
我们将使用 **OpenCV** 函数 **addWeighted** 将图像水印应用于图像。它可以在 **Core** 包中找到。其语法如下所示:
Core.addWeighted(InputArray src1, alpha, src2 (Watermark image), beta, gamma, OutputArray dst);
该函数的参数如下所示:
序号 | 参数及描述 |
---|---|
1 |
src1 它是第一个输入数组。 |
2 |
alpha 它是第一个数组元素的权重。 |
3 |
src2 它是第二个输入数组,其大小和通道数与 src1 相同。 |
4 |
beta 它是第二个数组元素的权重。 |
5 |
gamma 它是添加到每个总和的标量。 |
6 |
dst 它是输出数组,其大小和通道数与输入数组相同。 |
示例
以下示例演示了如何使用 Core 类将图像水印应用于图像。
import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class Main { public static void main( String[] args ) { try{ System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("digital_image_processing.jpg", Highgui.CV_LOAD_IMAGE_COLOR); Mat waterMark = Highgui.imread("watermark.png", Highgui.CV_LOAD_IMAGE_COLOR); Rect ROI = new Rect(waterMark.rows() * 4,waterMark.cols(), waterMark.cols(),waterMark.rows()); Core.addWeighted(source.submat(ROI), 0.8, waterMark, 0.2, 1, source.submat(ROI)); Highgui.imwrite("watermarkedImage.jpg", source); } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
水印图像
带水印的图像
Java 数字图像处理 - 理解卷积
卷积是对两个函数 f 和 g 的数学运算。在这种情况下,函数 f 和 g 是图像,因为图像也是一个二维函数。
执行卷积
为了对图像执行卷积,需要执行以下步骤:
- 仅翻转一次掩码(水平和垂直)。
- 将掩码滑动到图像上。
- 将对应的元素相乘,然后相加。
- 重复此过程,直到计算出图像的所有值。
我们使用 **OpenCV** 函数 **filter2D** 将卷积应用于图像。它可以在 **Imgproc** 包中找到。其语法如下所示:
filter2D(src, dst, depth , kernel, anchor, delta, BORDER_DEFAULT );
函数参数如下所示:
序号 | 参数和描述 |
---|---|
1 |
源图像 它是源图像。 |
2 |
dst 它是目标图像。 |
3 |
深度 它是 dst 的深度。负值(例如 -1)表示深度与源相同。 |
4 |
内核 它是将扫描图像的内核。 |
5 |
锚点 它是锚点相对于其内核的位置。位置 Point (-1, -1) 默认表示中心。 |
6 |
增量 它是在卷积过程中添加到每个像素的值。默认值为 0。 |
7 |
BORDER_DEFAULT 我们默认使用此值。 |
示例
以下示例演示了如何使用 Imgproc 类对灰度图像执行卷积操作。
import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class convolution { public static void main( String[] args ) { try { int kernelSize = 3; System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("grayscale.jpg", Highgui.CV_LOAD_IMAGE_GRAYSCALE); Mat destination = new Mat(source.rows(),source.cols(),source.type()); Mat kernel = new Mat(kernelSize,kernelSize, CvType.CV_32F) { { put(0,0,0); put(0,1,0); put(0,2,0); put(1,0,0); put(1,1,1); put(1,2,0); put(2,0,0); put(2,1,0); put(2,2,0); } }; Imgproc.filter2D(source, destination, -1, kernel); Highgui.imwrite("original.jpg", destination); } catch (Exception e) { System.out.println("Error:" + e.getMessage()); } } }
输出
在这个例子中,我们用以下滤波器(内核)对我们的图像进行卷积。此滤波器会导致生成原始图像本身:
0 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
原始图像
卷积后的图像
Java 数字图像处理 - Prewitt 算子
Prewitt 算子用于图像边缘检测。它检测两种类型的边缘:垂直边缘和水平边缘。
我们使用 **OpenCV** 函数 **filter2D** 将 Prewitt 算子应用于图像。它可以在 **Imgproc** 包中找到。其语法如下所示:
filter2D(src, dst, depth , kernel, anchor, delta, BORDER_DEFAULT );
函数参数如下所示:
序号 | 参数和描述 |
---|---|
1 |
源图像 它是源图像。 |
2 |
dst 它是目标图像。 |
3 |
深度 它是 dst 的深度。负值(例如 -1)表示深度与源相同。 |
4 |
内核 它是将扫描图像的内核。 |
5 |
锚点 它是锚点相对于其内核的位置。位置 Point (-1, -1) 默认表示中心。 |
6 |
增量 它是在卷积过程中添加到每个像素的值。默认值为 0。 |
7 |
BORDER_DEFAULT 我们默认使用此值。 |
除了 filter2D 方法外,Imgproc 类还提供了其他方法。它们简要描述如下:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int depth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类将 Prewitt 算子应用于灰度图像。
import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class convolution { public static void main( String[] args ) { try { int kernelSize = 9; System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("grayscale.jpg", Highgui.CV_LOAD_IMAGE_GRAYSCALE); Mat destination = new Mat(source.rows(),source.cols(),source.type()); Mat kernel = new Mat(kernelSize,kernelSize, CvType.CV_32F) { { put(0,0,-1); put(0,1,0); put(0,2,1); put(1,0-1); put(1,1,0); put(1,2,1); put(2,0,-1); put(2,1,0); put(2,2,1); } }; Imgproc.filter2D(source, destination, -1, kernel); Highgui.imwrite("output.jpg", destination); } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
此原始图像已使用如下所示的垂直边缘 Prewitt 算子进行卷积:
垂直方向
-1 | 0 | 1 |
-1 | 0 | 1 |
-1 | 0 | 1 |
卷积后的图像(垂直方向)
此原始图像也已使用如下所示的水平边缘 Prewitt 算子进行卷积:
水平方向
-1 | -1 | -1 |
0 | 0 | 0 |
1 | 1 | 1 |
卷积后的图像(水平方向)
Java 数字图像处理 - Sobel 算子
Sobel 算子与 Prewitt 算子非常相似。它也是一个导数掩码,用于边缘检测。Sobel 算子用于检测图像中的两种边缘:垂直方向边缘和水平方向边缘。
我们将使用 **OpenCV** 函数 **filter2D** 将 Sobel 算子应用于图像。它可以在 **Imgproc** 包中找到。其语法如下所示:
filter2D(src, dst, depth , kernel, anchor, delta, BORDER_DEFAULT );
函数参数如下所示:
序号 | Argument |
---|---|
1 |
源图像 它是源图像。 |
2 |
dst 它是目标图像。 |
3 |
深度 它是 dst 的深度。负值(例如 -1)表示深度与源相同。 |
4 |
内核 它是将扫描图像的内核。 |
5 |
锚点 它是锚点相对于其内核的位置。位置 Point (-1, -1) 默认表示中心。 |
6 |
增量 它是在卷积过程中添加到每个像素的值。默认值为 0。 |
7 |
BORDER_DEFAULT 我们默认使用此值。 |
除了 filter2D 方法外,Imgproc 类还提供了其他方法。它们简要描述如下:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int depth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类将 Sobel 算子应用于灰度图像。
import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class convolution { public static void main( String[] args ) { try { int kernelSize = 9; System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("grayscale.jpg", Highgui.CV_LOAD_IMAGE_GRAYSCALE); Mat destination = new Mat(source.rows(),source.cols(),source.type()); Mat kernel = new Mat(kernelSize,kernelSize, CvType.CV_32F) { { put(0,0,-1); put(0,1,0); put(0,2,1); put(1,0-2); put(1,1,0); put(1,2,2); put(2,0,-1); put(2,1,0); put(2,2,1); } }; Imgproc.filter2D(source, destination, -1, kernel); Highgui.imwrite("output.jpg", destination); } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
此原始图像已使用如下所示的垂直边缘 Sobel 算子进行卷积:
垂直方向
-1 | 0 | 1 |
-2 | 0 | 2 |
-1 | 0 | 1 |
卷积后的图像(垂直方向)
此原始图像已使用如下所示的水平边缘 Sobel 算子进行卷积:
水平方向
-1 | -2 | -1 |
0 | 0 | 0 |
1 | 2 | 1 |
卷积后的图像(水平方向)
Java 数字图像处理 - Kirsch 算子
Kirsch 指南针掩码是另一种类型的导数掩码,用于边缘检测。此运算符也称为方向掩码。在此运算符中,我们取一个掩码并将其旋转到所有八个指南针方向以获取八个方向的边缘。
我们将使用 **OpenCV** 函数 **filter2D** 将 Kirsch 算子应用于图像。它可以在 **Imgproc** 包中找到。其语法如下所示:
filter2D(src, dst, depth , kernel, anchor, delta, BORDER_DEFAULT );
函数参数如下所示:
序号 | Argument |
---|---|
1 |
源图像 它是源图像。 |
2 |
dst 它是目标图像。 |
3 |
深度 它是 dst 的深度。负值(例如 -1)表示深度与源相同。 |
4 |
内核 它是将扫描图像的内核。 |
5 |
锚点 它是锚点相对于其内核的位置。位置 Point (-1, -1) 默认表示中心。 |
6 |
增量 它是在卷积过程中添加到每个像素的值。默认值为 0。 |
7 |
BORDER_DEFAULT 我们默认使用此值。 |
除了 filter2D() 方法外,Imgproc 类还提供了其他方法。它们简要描述如下:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int depth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类将 Kirsch 算子应用于灰度图像。
import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class convolution { public static void main( String[] args ) { try { int kernelSize = 9; System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("grayscale.jpg", Highgui.CV_LOAD_IMAGE_GRAYSCALE); Mat destination = new Mat(source.rows(),source.cols(),source.type()); Mat kernel = new Mat(kernelSize,kernelSize, CvType.CV_32F) { { put(0,0,-3); put(0,1,-3); put(0,2,-3); put(1,0-3); put(1,1,0); put(1,2,-3); put(2,0,5); put(2,1,5); put(2,2,5); } }; Imgproc.filter2D(source, destination, -1, kernel); Highgui.imwrite("output.jpg", destination); } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
此原始图像已使用如下所示的东边缘 Kirsch 算子进行卷积:
Kirsch 东
-3 | -3 | -3 |
-3 | 0 | -3 |
5 | 5 | 5 |
卷积后的图像(Kirsch 东)
此原始图像已使用如下所示的西南边缘 Kirsch 算子进行卷积:
Kirsch 西南
5 | 5 | -3 |
5 | 0 | -3 |
-3 | -3 | -3 |
卷积后的图像(Kirsch 西南)
Java 数字图像处理 - Robinson 算子
Robinson 指南针掩码是另一种类型的导数掩码,用于边缘检测。此运算符也称为方向掩码。在此运算符中,我们取一个掩码并将其旋转到所有八个主要方向以获取八个方向的边缘。
我们将使用 **OpenCV** 函数 **filter2D** 将 Robinson 算子应用于图像。它可以在 **Imgproc** 包中找到。其语法如下所示:
filter2D(src, dst, depth , kernel, anchor, delta, BORDER_DEFAULT );
函数参数如下所示:
序号 | 参数和描述 |
---|---|
1 |
源图像 它是源图像。 |
2 |
dst 它是目标图像。 |
3 |
深度 它是 dst 的深度。负值(例如 -1)表示深度与源相同。 |
4 |
内核 它是将扫描图像的内核。 |
5 |
锚点 它是锚点相对于其内核的位置。默认情况下,位置 Point(-1, -1) 表示中心。 |
6 |
增量 它是在卷积过程中添加到每个像素的值。默认值为 0。 |
7 |
BORDER_DEFAULT 我们默认使用此值。 |
除了 filter2D 方法外,Imgproc 类还提供了其他方法。它们简要描述如下:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int depth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类将 Robinson 算子应用于灰度图像。
import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class convolution { public static void main( String[] args ) { try { int kernelSize = 9; System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("grayscale.jpg", Highgui.CV_LOAD_IMAGE_GRAYSCALE); Mat destination = new Mat(source.rows(),source.cols(),source.type()); Mat kernel = new Mat(kernelSize,kernelSize, CvType.CV_32F) { { put(0,0,-1); put(0,1,0); put(0,2,1); put(1,0-2); put(1,1,0); put(1,2,2); put(2,0,-1); put(2,1,0); put(2,2,1); } }; Imgproc.filter2D(source, destination, -1, kernel); Highgui.imwrite("output.jpg", destination); } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
此原始图像已使用如下所示的北边缘 Robinson 算子进行卷积:
北方向掩码
-1 | 0 | 1 |
-2 | 0 | 2 |
-1 | 0 | 1 |
卷积后的图像(Robinson 北)
此原始图像也已使用如下所示的东边缘 Robinson 算子进行卷积:
东方向掩码
-1 | -2 | -1 |
0 | 0 | 0 |
1 | 2 | 1 |
卷积后的图像(Robinson 东)
Java 数字图像处理 - Laplacian 算子
Laplacian 算子也是一个导数运算符,用于查找图像中的边缘。Laplacian 与其他运算符(如 Prewitt、Sobel、Robinson 和 Kirsch)的主要区别在于,这些运算符都是一阶导数掩码,而 Laplacian 是二阶导数掩码。
我们使用 **OpenCV** 函数 **filter2D** 将 Laplacian 算子应用于图像。它可以在 **Imgproc** 包中找到。其语法如下所示:
filter2D(src, dst, depth , kernel, anchor, delta, BORDER_DEFAULT );
函数参数如下所示:
序号 | Arguments |
---|---|
1 |
源图像 它是源图像。 |
2 |
dst 它是目标图像。 |
3 |
深度 它是 dst 的深度。负值(例如 -1)表示深度与源相同。 |
4 |
内核 它是将扫描图像的内核。 |
5 |
锚点 它是锚点相对于其内核的位置。位置 Point (-1, -1) 默认表示中心。 |
6 |
增量 它是在卷积过程中添加到每个像素的值。默认值为 0。 |
7 |
BORDER_DEFAULT 我们默认使用此值。 |
除了 filter2D() 方法外,Imgproc 类还提供了其他方法。它们简要描述如下:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int depth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类将 Laplacian 算子应用于灰度图像。
import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class convolution { public static void main( String[] args ) { try { int kernelSize = 9; System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("grayscale.jpg", Highgui.CV_LOAD_IMAGE_GRAYSCALE); Mat destination = new Mat(source.rows(),source.cols(),source.type()); Mat kernel = new Mat(kernelSize,kernelSize, CvType.CV_32F) { { put(0,0,0); put(0,1,-1) put(0,2,0); put(1,0-1); put(1,1,4); put(1,2,-1); put(2,0,0); put(2,1,-1); put(2,2,0); } }; Imgproc.filter2D(source, destination, -1, kernel); Highgui.imwrite("output.jpg", destination); } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
此原始图像已使用如下所示的 Laplacian 负算子进行卷积:
Laplacian 负
0 | -1 | 0 |
-1 | 4 | -1 |
0 | -1 | 0 |
卷积后的图像(Laplacian 负)
此原始图像已使用如下所示的 Laplacian 正算子进行卷积:
Laplacian 正
0 | 1 | 0 |
1 | -4 | 1 |
0 | 1 | 0 |
卷积后的图像(Laplacian 正)
Java 数字图像处理 - 加权平均滤波器
在加权平均滤波器中,我们赋予中心值更大的权重,因此中心值的贡献大于其余值。通过加权平均滤波,我们可以控制图像的模糊程度。
我们使用 **OpenCV** 函数 **filter2D** 将加权平均滤波器应用于图像。它可以在 **Imgproc** 包中找到。其语法如下所示:
filter2D(src, dst, depth , kernel, anchor, delta, BORDER_DEFAULT );
函数参数如下所示:
序号 | 参数和描述 |
---|---|
1 |
源图像 它是源图像。 |
2 |
dst 它是目标图像。 |
3 |
ddepth 它是 dst 的深度。负值(例如 -1)表示深度与源相同。 |
4 |
内核 它是将扫描图像的内核。 |
5 |
锚点 它是锚点相对于其内核的位置。默认情况下,位置 Point(-1, -1) 表示中心。 |
6 |
增量 它是在卷积过程中添加到每个像素的值。默认值为 0。 |
7 |
BORDER_DEFAULT 我们默认使用此值。 |
除了 filter2D() 方法外,Imgproc 类还提供了其他方法。它们简要描述如下:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int depth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类将加权平均滤波器应用于灰度图像。
import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class convolution { public static void main( String[] args ) { try { int kernelSize = 9; System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("grayscale.jpg", Highgui.CV_LOAD_IMAGE_GRAYSCALE); Mat destination = new Mat(source.rows(),source.cols(),source.type()); Mat kernel = Mat.ones(kernelSize,kernelSize, CvType.CV_32F) { for(int i=0; i<kernel.rows(); i++) { for(int j=0; j<kernel.cols(); j++) { double[] m = kernel.get(i, j); for(int k =0; k<m.length; k++) { if(i==1 && j==1) { m[k] = 10/18; } else{ m[k] = m[k]/(18); } } kernel.put(i,j, m); } } }; Imgproc.filter2D(source, destination, -1, kernel); Highgui.imwrite("output.jpg", destination); } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
此原始图像已使用如下所示的加权平均滤波器进行卷积:
加权平均滤波器
1 | 1 | 1 |
1 | 10 | 1 |
1 | 1 | 1 |
卷积后的图像
Java 数字图像处理 - 创建缩放效果
缩放是放大图像的过程,以便图像中的细节变得更加清晰和突出。
我们使用 **OpenCV** 函数 **resize** 将缩放应用于图像。它可以在 **Imgproc** 包中找到。其语法如下所示:
Imgproc.resize(source,destination, destination.size(),zoomFactor,zoomFactor,Interpolation);
在 resize 函数中,我们传递源图像、目标图像及其大小、缩放因子和要使用的插值方法。
可用的插值方法如下所述:
序号 | 插值方法和说明 |
---|---|
1 |
INTER_NEAREST 它是最近邻插值。 |
2 |
INTER_LINEAR 它是双线性插值(默认使用)。 |
3 |
INTER_AREA 它是使用像素面积关系进行重采样。它可能是图像抽取的首选方法,因为它提供更无损的结果。 |
4 |
INTER_CUBIC 它是在 4x4 像素邻域上进行的双三次插值。 |
5 |
INTER_LANCZOS4 这是一个基于 8x8 像素邻域的 Lanczos 插值。 |
除了调整大小方法外,Imgproc 类还提供了其他方法。下面简要描述了它们:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int ddepth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类将图像进行缩放。
import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.highgui.Highgui; import org.opencv.imgproc.Imgproc; public class Main { public static void main( String[] args ) { try { int zoomingFactor = 2; System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); Mat source = Highgui.imread("image.jpg", Highgui.CV_LOAD_IMAGE_GRAYSCALE); Mat destination = new Mat(source.rows() * zoomingFactor, source.cols()* zoomingFactor,source.type()); Imgproc.resize(source, destination, destination.size(), zoomingFactor,zoomingFactor,Imgproc.INTER_NEAREST); Highgui.imwrite("zoomed.jpg", destination); } catch (Exception e) { System.out.println("Error: "+e.getMessage()); } } }
输出
执行给定代码时,将看到以下输出:
原始图像
缩放后的图像(缩放因子 - 2)
Java 图像处理 - 开源库
在本章中,我们将探讨一些广泛使用的免费图像处理库,这些库可以轻松地集成到项目中。这些库包括:
- ImageJ
- Fiji
- Commons Imaging
- ImageMagick
- Endrov
- LeadTools
- OpenCv
ImageJ
ImageJ 是一款公共领域的 Java 图像处理程序,其灵感来自 Macintosh 上的 NIH Image。它可以显示、编辑、分析、处理、保存和打印 8 位、16 位和 32 位图像。
下面描述了 ImageJ 的一些基本功能:
序号 | 功能与描述 |
---|---|
1 |
随处运行 ImageJ 使用 Java 编写,这使得它可以在 Linux、Mac OS X 和 Windows 上运行,并且支持 32 位和 64 位模式。 |
2 |
开源 ImageJ 及其 Java 源代码可免费获取,并且属于公共领域。 |
3 |
工具包 将 ImageJ 作为图像处理工具包(类库)来开发小程序、servlet 或应用程序。 |
4 |
数据类型 8 位灰度或索引颜色、16 位无符号整数、32 位浮点数和 RGB 颜色。 |
5 |
文件格式 打开和保存 GIF、JPEG、BMP、PNG、PGM、FITS 和 ASCII。打开 DICOM。使用 URL 打开 TIFF、GIF、JPEG、DICOM 和原始数据。 |
6 |
选择 创建矩形、椭圆或不规则区域选择。创建线条和点选择。 |
7 |
图像增强 支持对 8 位灰度和 RGB 彩色图像进行平滑、锐化、边缘检测、中值滤波和阈值处理。 |
8 |
颜色处理 将 32 位彩色图像分割成 RGB 或 HSV 分量。将 8 位分量合并成彩色图像。 |
Fiji
Fiji 是一款图像处理软件包。可以将其描述为 ImageJ(和 ImageJ2)以及 Java、Java3D 和大量插件的组合,这些插件被组织成一个连贯的菜单结构。Fiji 与 ImageJ 的关系就像 Ubuntu 与 Linux 的关系。
除了 ImageJ 的基本功能外,下面还描述了 Fiji 的一些高级功能:
序号 | 功能与描述 |
---|---|
1 |
配准 3D 图像 这涉及弹性对齐和蒙太奇、特征提取、图像稳定器等。 |
2 |
分割图像 它提供了超过 35 种类型的分割方法。 |
3 |
有用的键盘快捷键 Fiji 有很多键盘快捷键。 |
4 |
脚本编写 允许使用宏、JavaScript、JRuby、Jython、Clojure 和 Beanshell 进行脚本编写。 |
5 |
开发插件 使用脚本编辑器开始开发插件,然后运行插件。 |
6 |
ImageJ 技巧 ImageJ 易于使用,但有时您希望有一些实际上已实现的功能,但您不知道如何触发。 |
Commons Imaging
Apache Commons Imaging,以前称为 Apache Commons Sanselan,是一个库,可以读取和写入各种图像格式,包括快速解析图像信息(例如大小、颜色、空间、ICC 配置文件等)和元数据。
下面描述了 ImageJ 的一些基本功能:
序号 | 功能与描述 |
---|---|
1 |
Java Apache Commons Imaging 使用 100% 纯 Java 编写。它可以在任何 JVM 和任何平台上执行,无需修改。 |
2 |
图像格式 它读取和写入各种图像格式,并支持所有或大多数其他库遗漏的一些变体和编码。 |
3 |
元数据支持 它支持以结构化的方式读取和写入各种元数据,包括 EXIF 元数据。 |
4 |
网络友好 它是网络友好的。Commons Imaging 只读取它需要的数据,并缓存读取的数据,以便它不会对网络造成过大的负担。 |
5 |
易于使用 它设计得非常易于使用。它具有简单、干净的界面。大多数操作都是单个 Imaging 方法调用。 |
6 |
透明 Commons Imaging 旨在保持透明。没有隐藏的缓冲区需要释放,没有本机内存需要释放,也没有后台线程。 |
7 |
开源 它是免费软件/开源软件。它在 Apache 软件许可证下可用。 |
8 |
颜色转换 ColorConversions 类提供方法在以下颜色空间之间进行转换:CIE-L*CH、CIE-L*ab、CIE-L*uv、CMY、CMYK、HSL、HSV、Hunter-Lab、RGB、XYZ 和 YXY。 |
ImageMagick
ImageMagick 是一款用于创建、编辑、合成或转换位图图像的软件套件。它可以读取和写入超过 100 种格式的图像,包括 DPX、EXR、GIF、JPEG、JPEG-2000、PDF、PNG、Postscript、SVG 和 TIFF。使用 ImageMagick 可以调整图像大小、翻转、镜像、旋转、扭曲、剪切和变换图像,调整图像颜色,应用各种特殊效果,或绘制文本、线条、多边形、椭圆和贝塞尔曲线。
下面描述了 ImageMagick 的一些基本功能:
序号 | 功能与描述 |
---|---|
1 |
格式转换 它将图像从一种格式转换为另一种格式(例如,PNG 到 JPEG)。 |
2 |
变换 它可以调整图像大小、旋转、裁剪、翻转或修剪图像。 |
3 |
透明度 它使图像的某些部分不可见。 |
4 |
绘制 它向图像添加形状或文本。 |
5 |
装饰 它向图像添加边框或框架。 |
6 |
特殊效果 它可以模糊、锐化、阈值或色调图像。 |
7 |
动画 它可以从一组图像创建 GIF 动画序列。 |
8 |
合成 它可以将一个图像叠加在另一个图像上。 |
9 |
形状形态 它提取特征、描述形状并在图像中识别模式。 |
10 |
加密或解密图像 它将普通图像转换为难以理解的乱码并恢复。 |
Endrov
Endrov 是一款多功能图像分析程序。它是独立编写的,旨在解决其他免费软件和许多商业软件包的许多缺点。
下面描述了 Endrov 的一些基本功能:
序号 | 功能与描述 |
---|---|
1 |
查看数据 它以 2D 和 3D 方式查看数据。旨在处理复杂的 4D 数据方案和无限数量的通道,其中每个通道可以具有自己的 X、Y 和 Z 分辨率。 |
2 |
注释图像 它自动或手动注释图像,以理解图像并获取统计信息。 |
3 |
撤消和重做 它可以撤消和重做所有操作。 |
4 |
惰性求值 它从一开始就设计用于处理大型图像集。Endrov 使用惰性求值,这主要在研究型编程语言中可用。 |
5 |
脚本语言 它支持图形化脚本语言以及传统脚本。 |
6 |
Java 使用 Java 编写。插件架构允许使用新的 Java 插件轻松扩展。它可以与 Matlab 交互。 |
7 |
格式 它使用 Bio-formats 访问几乎所有商业和开放文件格式。 |
8 |
显微镜处理 它可以使用一个程序控制所有显微镜,并进行即时图像分析。 |
LEADTOOLS
LEADTOOLS 在多个类别中提供了 200 多个图像处理功能,包括文档清理、医学图像增强、颜色转换和校正、降噪、边缘检测等等。
下面描述了 LEADTOOLS 的一些基本功能:
序号 | 功能与描述 |
---|---|
1 |
扫描文档图像处理 这套强大的功能可以读取扫描文档中的伪影和瑕疵,例如打孔、倾斜角度、边框、灰尘斑点等等。 |
2 |
医学图像处理 通过平移、选择、减法和去除背景来增强图像或突出细节,以获得更好的视觉效果。 |
3 |
几何变换 这些功能可用于清理、对齐、校正图像或应用艺术性的 3D 效果。 |
4 |
亮度和对比度 这些功能可用于增强图像、应用艺术效果或辅助医学图像的诊断评估。 |
5 |
颜色空间转换 它们可以为单线程和多线程应用程序(包括 IIS 和 Windows WF 托管应用程序)添加图像颜色空间功能。 |
6 |
颜色校正 这些功能用于校正颜色通道交换、平衡颜色强度或执行各种图像分析任务的图像。 |
7 |
图像增强 这些功能用于校正摄影中常见的错误,例如红眼和颜色不平衡,以及辅助医学图像的诊断评估。 |
8 |
感兴趣区域 这些功能用于在图像中创建和修改感兴趣区域,以便对图像的特定部分执行图像处理功能,节省条形码和 OCR 识别的时间,或执行各种图像分析任务。 |
OpenCV
OpenCV 在 BSD 许可证下发布,因此它可免费用于学术和商业用途。它具有 C++、C、Python 和 Java 接口,并且支持 Windows、Linux、Mac OS、iOS 和 Android。OpenCV 专为计算效率而设计,并专注于实时应用。该库使用优化的 C/C++ 编写,可以利用多核处理。
下面简要描述了 OpenCV 的一些基本功能:
序号 | 功能与描述 |
---|---|
1 |
平滑图像 这涉及应用 Blur、GaussianBlur、medianBlur 和 bilateral Filter。 |
2 |
腐蚀和膨胀 它可以应用两个非常常见的形态学算子:膨胀和腐蚀。 |
3 |
形态学变换 OpenCV 函数 morphologyEx 用于应用形态学变换,例如开运算、闭运算、TopHat 和 BlackHat 等。 |
4 |
图像金字塔 OpenCV 函数 pyrUp 和 pyrDown 用于对给定图像进行下采样或上采样。 |
4 |
基本的阈值操作 使用 OpenCV 函数 threshold 执行基本的阈值操作。 |
5 |
向图像添加边框 OpenCV 函数 copyMakeBorder 用于设置边框(图像的额外填充)。 |
7 |
重新映射 在 OpenCV 中,函数 remap 提供了一个简单的重新映射实现。 |
8 |
直方图计算 对于简单目的,OpenCV 实现函数 calcHist,该函数计算一组数组(通常是图像或图像平面)的直方图。它可以操作多达 32 个维度。 |
Java 图像处理 - OpenCV 简介
OpenCV 在 BSD 许可证下发布,因此它可免费用于学术和商业用途。它具有 C++、C、Python 和 Java 接口,并且支持 Windows、Linux、Mac OS、iOS 和 Android。
OpenCV 专为计算效率而设计,并专注于实时应用。该库使用优化的 C/C++ 编写,可以利用多核处理。
下面描述了 OpenCV 的一些基本功能:
序号 | 功能与描述 |
---|---|
1 |
平滑图像 这涉及应用 Blur、GaussianBlur、medianBlur 和 bilateral Filter。 |
2 |
腐蚀和膨胀 它可以应用两个非常常见的形态学算子:膨胀和腐蚀。 |
3 |
形态学变换 OpenCV 函数 morphologyEx 用于应用形态学变换,例如开运算、闭运算、TopHat 和 BlackHat 等。 |
4 |
图像金字塔 OpenCV 函数 pyrUp 和 pyrDown 用于对给定图像进行下采样或上采样。 |
4 |
基本的阈值操作 它可以使用 OpenCV 函数 threshold 执行基本的阈值操作。 |
5 |
向图像添加边框 OpenCV 函数 copyMakeBorder 用于设置边框(图像的额外填充)。 |
7 |
重新映射 在 OpenCV 中,函数 remap 提供了一个简单的重新映射实现。 |
8 |
直方图计算 对于简单目的,OpenCV 实现函数 calcHist,该函数计算一组数组(通常是图像或图像平面)的直方图。它可以操作多达 32 个维度。 |
集成 OpenCV
以下步骤说明了如何将 OpenCV 集成到您的应用程序中。
下载 OpenCV
您可以从其官方网站 此处 下载 OpenCV。
创建用户库
此外,我们创建了 OpenCV 的用户库,以便我们可以在未来的项目中使用它。
启动 Eclipse
从菜单中选择 Window -> Preferences。
导航到 Java -> Build Path -> User Libraries 并单击 New。
现在输入库的名称。例如,OpenCV-2.4.6。
之后,选择您的新用户库(即 OpenCV-2.4.6)并单击 Add External JARs。
浏览到 C:\OpenCV-2.4.6\build\java\ 并选择 opencv-246.jar。添加 jar 后,展开 opencv-246.jar 并选择 Native library location,然后按 Edit。
选择 External Folder... 并浏览以选择文件夹 C:\OpenCV-2.4.6\build\java\x64。如果您拥有 32 位系统,则需要选择 x86 文件夹而不是 x64。
按 Ok,您就完成了。
现在您的用户库已创建。现在您可以在任何项目中重用此配置。
创建 OpenCV 项目
在 Eclipse 中创建一个新的 Java 项目。
在 Java Settings 步骤的 Libraries 选项卡下,选择 Add Library... 并选择 OpenCV-2.4.6,然后单击 Finish。
单击 Finish,您就完成了。
Java 图像处理 - OpenCV 灰度转换
为了使用 OpenCV 将彩色图像转换为灰度图像,我们先将图像读入 **BufferedImage** 并将其转换为 **Mat** 对象。其语法如下所示:
File input = new File("digital_image_processing.jpg"); BufferedImage image = ImageIO.read(input); //convert Buffered Image to Mat.
然后,您可以使用 **Imgproc** 类中的 **cvtColor()** 方法将图像从 RGB 格式转换为灰度格式。其语法如下所示:
Imgproc.cvtColor(source mat, destination mat1, Imgproc.COLOR_RGB2GRAY);
**cvtColor()** 方法接受三个参数,分别是源图像矩阵、目标图像矩阵和颜色转换类型。
除了 cvtColor 方法外,Imgproc 类还提供了其他方法。它们列在下面:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int depth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类将图像转换为灰度图像:
import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; import java.io.File; import javax.imageio.ImageIO; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.imgproc.Imgproc; public class Main { public static void main( String[] args ) { try { System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); File input = new File("digital_image_processing.jpg"); BufferedImage image = ImageIO.read(input); byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3); mat.put(0, 0, data); Mat mat1 = new Mat(image.getHeight(),image.getWidth(),CvType.CV_8UC1); Imgproc.cvtColor(mat, mat1, Imgproc.COLOR_RGB2GRAY); byte[] data1 = new byte[mat1.rows() * mat1.cols() * (int)(mat1.elemSize())]; mat1.get(0, 0, data1); BufferedImage image1 = new BufferedImage(mat1.cols(),mat1.rows(), BufferedImage.TYPE_BYTE_GRAY); image1.getRaster().setDataElements(0, 0, mat1.cols(), mat1.rows(), data1); File ouptut = new File("grayscale.jpg"); ImageIO.write(image1, "jpg", ouptut); } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } } }
输出
执行此示例时,它会将名为 **digital_image_processing.jpg** 的图像转换为等效的灰度图像,并将其写入硬盘,文件名命名为 **grayscale.jpg**。
原始图像
灰度图像
Java 数字图像处理 - OpenCV 颜色空间转换
为了使用 OpenCV 将一个图像的颜色空间更改为另一个颜色空间,我们先将图像读入 **BufferedImage** 并将其转换为 **Mat** 对象。其语法如下所示:
File input = new File("digital_image_processing.jpg"); BufferedImage image = ImageIO.read(input); //convert Buffered Image to Mat.
OpenCv 允许许多颜色转换类型,所有这些类型都可以在 Imgproc 类中找到。其中一些类型简要描述如下:
序号 | 颜色转换类型 |
---|---|
1 | COLOR_RGB2BGR |
2 | COLOR_RGB2BGRA |
3 | COLOR_RGB2GRAY |
4 | COLOR_RGB2HLS |
5 | COLOR_RGB2HSV |
6 | COLOR_RGB2Luv |
7 | COLOR_RGB2YUV |
8 | COLOR_RGB2Lab |
对于任何颜色转换类型,只需将相应的类型传递给 **Imgproc** 类中的 **cvtColor()** 方法即可。其语法如下所示:
Imgproc.cvtColor(source mat, destination mat1, Color_Conversion_Code);
**cvtColor()** 方法接受三个参数,分别是源图像矩阵、目标图像矩阵和颜色转换类型。
除了 cvtColor() 方法外,Imgproc 类还提供了其他方法。它们简要描述如下:
序号 | 方法及描述 |
---|---|
1 |
cvtColor(Mat src, Mat dst, int code, int dstCn) 它将图像从一个颜色空间转换为另一个颜色空间。 |
2 |
dilate(Mat src, Mat dst, Mat kernel) 它使用特定的结构元素膨胀图像。 |
3 |
equalizeHist(Mat src, Mat dst) 它均衡灰度图像的直方图。 |
4 |
filter2D(Mat src, Mat dst, int ddepth, Mat kernel, Point anchor, double delta) 它将图像与内核进行卷积。 |
5 |
GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) 它使用高斯滤波器模糊图像。 |
6 |
integral(Mat src, Mat sum) 它计算图像的积分。 |
示例
以下示例演示了如何使用 Imgproc 类将图像从一个颜色空间转换为另一个颜色空间。
import java.awt.image.BufferedImage; import java.awt.image.DataBufferByte; import java.io.File; import javax.imageio.ImageIO; import org.opencv.core.Core; import org.opencv.core.CvType; import org.opencv.core.Mat; import org.opencv.imgproc.Imgproc; public class Main { public static void main( String[] args ) { try { System.loadLibrary( Core.NATIVE_LIBRARY_NAME ); File input = new File("digital_image_processing.jpg"); BufferedImage image = ImageIO.read(input); byte[] data = ((DataBufferByte) image.getRaster().getDataBuffer()).getData(); Mat mat = new Mat(image.getHeight(),image.getWidth(), CvType.CV_8UC3); mat.put(0, 0, data); Mat mat1 = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3); Imgproc.cvtColor(mat, mat1, Imgproc.COLOR_RGB2HSV); byte[] data1 = new byte[mat1.rows()*mat1.cols()*(int)(mat1.elemSize())]; mat1.get(0, 0, data1); BufferedImage image1 = new BufferedImage(mat1.cols(), mat1.rows(), 5); image1.getRaster().setDataElements(0, 0, mat1.cols(), mat1.rows(), data1); File ouptut = new File("hsv.jpg"); ImageIO.write(image1, "jpg", ouptut); } catch (Exception e) { System.out.println("Error: " + e.getMessage()); } } }
输出
执行此示例时,它会将名为 **digital_image_processing.jpg** 的图像转换为等效的 HSV 颜色空间图像,并将其写入硬盘,文件名命名为 **hsv.jpg**。