package com.opencv;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Size;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
public class OpenCVDemo {
public static void main(String[] args) {
/* 1.加载本地动态链接库
* 加载动态链接库有很多种方法,也可以写成static静态代码块。
*/
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
/* 2 读取测试图片
* imread:输入图片所在地址,返回Mat矩阵对象。
* Mat对象中保存着加载图片的大小、通道、像素数据等等与图片有关的数据
*/
Mat image = Imgcodecs.imread("c:\\123.jpg");
// 3. 设置图片的大小,让图片显示的时候小一点
Imgproc.resize(image, image, new Size(image.cols()/2,image.rows()/2));
HighGui.imshow("原图", image);
HighGui.waitKey();
// 使用了4种不同新建Mat对象的方式 还有 Mat::create()方法
blur(image); //Mat image = src.clone();
gausssianBlur(image); //Mat image = Mat.eye(src.size(),src.type());
mediaBlur(image); // Mat image = Mat.zeros(src.size(),src.type());
bilateralFilter(image);//Mat image = Mat.ones(src.size(),src.type());
}
/**
* 均值模糊(降噪) 支持就地过滤(可以操作对象本身)
* 使用标准的过滤器模糊图像。该函数使用一个内核(奇数的矩阵)来平滑模糊图像:
* 调用blur(src,dst,ksize,anchor,borderType等效于boxFilter(src,dst,src.type(),anchor,true,borderType。
* @param src输入图像; 它可以具有任意数量的通道,这些通道可以独立处理,但深度应为CV_8U,CV_16U,CV_16S,CV_32F或CV_64F。
* @param dst输出图像的大小和类型与src相同。
* @param ksize模糊内核大小。
* @param锚点; 默认值Point(-1,-1)表示锚点位于内核中心。
*/
public static void blur(Mat src) {
//克隆,数据,大小,类型等同于输入图像
Mat image = src.clone();
Imgproc.blur(src, image, new Size(3,3),new Point(-1,-1));
HighGui.imshow("均值模糊(降噪)", image);
HighGui.waitKey();
}
/**
* 高斯滤波(降噪) 支持就地过滤(可以操作对象本身)。
* 使用高斯滤波器对图像进行模糊处理。该函数将源图像与指定的高斯内核进行卷积。
* @param src输入图像;图像可以具有任意数量的通道,这些通道可以独立处理,但深度应为CV_8U,CV_16U,CV_16S,CV_32F或CV_64F。
* @param dst输出图像的大小和类型与src相同。
* @param ksize高斯内核大小。 ksize.width和ksize.height可以不同,但它们都必须为正数和奇数。或者,它们可以为零,然后根据sigma计算得出。
* @param sigmaX X方向上的高斯核标准偏差。
* @param sigmaY Y方向上的高斯核标准差;如果sigmaY为零,则将其设置为等于sigmaX;如果两个sigmas为零,
* 则分别从ksize.width和ksize.height计算得出;为了完全控制结果,
* 而不管将来可能对所有这些语义进行的修改,建议指定所有ksize,sigmaX和sigmaY。
*/
public static void gausssianBlur(Mat src) {
//返回一个恒等指定大小和类型矩阵,数据全部有0填充。
Mat image = Mat.eye(src.size(),src.type());
Imgproc.GaussianBlur(src, image, new Size(11,11), 7,7);
HighGui.imshow("高斯滤波(降噪)", image);
HighGui.waitKey();
}
/**
* 中值滤波(降噪) 支持就地操作(可以操作对象本身)
* 使用中值滤镜模糊图像。该函数使用中性滤镜使图像平滑({ksize}*{ksize})光圈。 多通道图像的每个通道都是独立处理的。
* 注意:中值过滤器内部使用#BORDER_REPLICATE处理边界像素
* @param src输入1、3或4通道图像; 当ksize为3或5时,图像深度应为CV_8U,CV_16U或CV_32F,对于较大的光圈,只能为CV_8U。
* @param dst目标数组,其大小和类型与src相同。
* @param ksize孔径线性大小; 它必须是奇数且大于1,例如:3、5、7 ...
*/
public static void mediaBlur(Mat src) {
//返回一个恒等指定大小和类型矩阵,数据全部有0填充。
Mat image = Mat.zeros(src.size(),src.type());
Imgproc.medianBlur(src, image, 9);
HighGui.imshow("中值滤波(降噪)", image);
HighGui.waitKey();
}
/**
* 双边滤波(降噪) 此过滤器无法就地工作。(需要新建个Mat对象)
* 将双边过滤器应用于图像。
* 该函数将双边滤波应用于输入图像,bilateralFilter可以很好地减少不需要的噪声,
* 同时保持边缘相当清晰。但是,与大多数过滤器相比,它非常慢。
* _Sigma values_:为简单起见,您可以将2个sigma值设置为相同。如果它们很小(<10),
* 则滤镜效果不大;而如果它们很大(> 150),则滤镜效果会很强,使图像看起来“卡通化”。
* _Filter size_:大型滤波器(d> 5)非常慢,因此对于实时应用程序建议使用d = 5,
* 对于需要重噪声过滤的离线应用程序建议使用d = 9。
* @param src源8位或浮点,1通道或3通道图像。
* @param dst与src大小和类型相同的目标映像。
* @param d滤波期间使用的每个像素邻域的直径。如果它不是正值,则从sigmaSpace计算得出。
* @param sigmaColor在色彩空间中过滤sigma。参数的较大值表示像素邻域内的其他颜色将混
* 合在一起,从而导致较大区域的半均等颜色。
* @param sigmaSpace在坐标空间中过滤sigma。该参数的值越大,表示越远的像素就会相互影响,
* 只要它们的颜色足够接近即可。当d> 0时,它指定邻域大小,而不考虑sigmaSpace。否则,d与sigmaSpace成比例。
*/
public static void bilateralFilter(Mat src) {
//返回一个恒等指定大小和类型矩阵,数据全部有BGR分别由100填充。
Mat image = Mat.ones(src.size(),src.type());
Imgproc.bilateralFilter(src, image, 2, 200, 5);
HighGui.imshow("双边滤波(降噪)", image);
HighGui.waitKey();
}
}
图像降噪
图像降噪是图像处理中的专业术语.
现实中的数字图像在数字化和传输过程中常受到成像设备与外部环境噪声干扰等影响,称为含噪图像或噪声图像。减少数字图像中噪声的过程称为图像降噪,有时候又称为图像去噪。
噪声的产生及分类
噪声是图像干扰的重要原因。一幅图像在实际应用中可能存在各种各样的噪声,这些噪声可能在传输中产生,也可能在量化等处理中产生。根据噪声和信号的关系可将其分为三种形式:(f(x,y)表示给定原始图像,g(x,y)表示图像信号,n(x,y)表示噪声。)
- 加性噪声,此类噪声与输入图像信号无关,含噪图像可表示为f(x,y)=g(x,y)+n(x,y),信道噪声及光导摄像管的摄像机扫描图像时产生的噪声就属这类噪声;
- 乘性噪声,此类噪声与图像信号有关,含噪图像可表示为f(x,y)=g(x,y)+n(x,y)g(x,y),飞点扫描器扫描图像时的噪声,电视图像中的相干噪声,胶片中的颗粒噪声就属于此类噪声。
- 量化噪声,此类噪声与输入图像信号无关,是量化过程存在量化误差,再反映到接收端而产生。