2019-11-04 20:34:42 qq_36511401 阅读数 4322
  • OpenCV3.2 Java图像处理视频学习教程

    OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java OpenCV图像处理部分内容,包括Mat对象使用、图像读写、 基于常用核心API讲述基本原理、使用方法、参数、代码演示、图像处理思路与流程讲授。主要内容包括opencv像素操作、滤波、边缘提取、直线与圆检测、形态学操作与分水岭、图像金子塔融合重建、多尺度模板匹配、opencv人脸检测、OpenCV跟Tomcat使用实现服务器端图像处理服务。

    4118 人正在学习 去看看 贾志刚

一、介绍

1、一维高斯滤波。

         \LARGE f(x)=\frac{1}{\sqrt{2\pi }\sigma }e^\frac{-(x-u)^2}{2\sigma^2 }

    a表示得到曲线的高度,u是指曲线在x轴的中心, σ指width(与半峰全宽有关,即平方差)。

2、二维高斯滤波。

        \LARGE f(x,y)=\frac{1}{2\pi \sigma ^2}e^\frac{-(x^2+y^2)}{2\sigma ^2}

二、二维高斯滤波模版

1、生成维高斯滤波模版。

public class MathUtils {
    /**
     * 获取高斯滤波模版的二维数组
     *
     * @param length 模版长度,length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
     * @param sigma  模版标准差,length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
     */
    public static double[][] getGaussTemplate(int length, double sigma) {
        double[][] gaussTemplate = new double[length][length];    // 用于存储结果
        int centerIndex = (length - 1) / 2;//模版的中心点
        double variance = sigma * sigma;//方差
        double sum = 0;
        for (int i = 0; i < length; ++i) {
            for (int j = 0; j < length; ++j) {
                int xLength = j - centerIndex;//x上的距离
                int yLength = i - centerIndex;//y上的距离
                double e = Math.exp(-(xLength * xLength + yLength * yLength) / (2 * variance));
                gaussTemplate[i][j] = e / (2 * Math.PI * variance);
                sum += gaussTemplate[i][j];
            }
        }
        //占得比重
        for (int i = 0; i < length; ++i) {
            for (int j = 0; j < length; ++j) {
                gaussTemplate[i][j] = gaussTemplate[i][j] / sum;
            }
        }
        //打印模版
        System.out.println(String.format("生成大小为%d,标准差为%.3f的二维高斯模版:", length, sigma));
        for (double[] doubles : gaussTemplate) {
            for (int j = 0; j < gaussTemplate.length; j++) {
                System.out.print(String.format("%8.3f", doubles[j]));
            }
            System.out.println();
        }
        return gaussTemplate;
    }
}
public static void main(String[] args) {
        //高斯滤波的模版,length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
        double[][] gaussTemplate1 = FilterUtils.getGaussTemplate(3, 1.5);
        double[][] gaussTemplate2 = FilterUtils.getGaussTemplate(3, 0.75);
        double[][] gaussTemplate3 = FilterUtils.getGaussTemplate(3, 0.5);
        double[][] gaussTemplate4 = FilterUtils.getGaussTemplate(5, 2.5);
        double[][] gaussTemplate5 = FilterUtils.getGaussTemplate(5, 1.25);
        double[][] gaussTemplate6 = FilterUtils.getGaussTemplate(5, 0.833);
        double[][] gaussTemplate7 = FilterUtils.getGaussTemplate(7, 3.5);
        double[][] gaussTemplate8 = FilterUtils.getGaussTemplate(7, 1.75);
        double[][] gaussTemplate9 = FilterUtils.getGaussTemplate(7, 1.167);
    }

2、日志打印的结果。

        生成大小为3,标准差为1.500的二维高斯模版:
           0.095   0.118   0.095
           0.118   0.148   0.118
           0.095   0.118   0.095
        生成大小为3,标准差为0.750的二维高斯模版:
           0.051   0.124   0.051
           0.124   0.301   0.124
           0.051   0.124   0.051
        生成大小为3,标准差为0.500的二维高斯模版:
           0.011   0.084   0.011
           0.084   0.619   0.084
           0.011   0.084   0.011
        生成大小为5,标准差为2.500的二维高斯模版:
           0.029   0.036   0.039   0.036   0.029
           0.036   0.046   0.050   0.046   0.036
           0.039   0.050   0.054   0.050   0.039
           0.036   0.046   0.050   0.046   0.036
           0.029   0.036   0.039   0.036   0.029
        生成大小为5,标准差为1.250的二维高斯模版:
           0.009   0.022   0.031   0.022   0.009
           0.022   0.058   0.080   0.058   0.022
           0.031   0.080   0.110   0.080   0.031
           0.022   0.058   0.080   0.058   0.022
           0.009   0.022   0.031   0.022   0.009
        生成大小为5,标准差为0.833的二维高斯模版:
           0.001   0.006   0.013   0.006   0.001
           0.006   0.054   0.112   0.054   0.006
           0.013   0.112   0.230   0.112   0.013
           0.006   0.054   0.112   0.054   0.006
           0.001   0.006   0.013   0.006   0.001
        生成大小为7,标准差为3.500的二维高斯模版:
           0.013   0.016   0.018   0.019   0.018   0.016   0.013
           0.016   0.020   0.023   0.024   0.023   0.020   0.016
           0.018   0.023   0.026   0.027   0.026   0.023   0.018
           0.019   0.024   0.027   0.028   0.027   0.024   0.019
           0.018   0.023   0.026   0.027   0.026   0.023   0.018
           0.016   0.020   0.023   0.024   0.023   0.020   0.016
           0.013   0.016   0.018   0.019   0.018   0.016   0.013
        生成大小为7,标准差为1.750的二维高斯模版:
           0.003   0.007   0.011   0.013   0.011   0.007   0.003
           0.007   0.015   0.025   0.030   0.025   0.015   0.007
           0.011   0.025   0.041   0.048   0.041   0.025   0.011
           0.013   0.030   0.048   0.057   0.048   0.030   0.013
           0.011   0.025   0.041   0.048   0.041   0.025   0.011
           0.007   0.015   0.025   0.030   0.025   0.015   0.007
           0.003   0.007   0.011   0.013   0.011   0.007   0.003
        生成大小为7,标准差为1.167的二维高斯模版:
           0.000   0.001   0.003   0.004   0.003   0.001   0.000
           0.001   0.006   0.019   0.027   0.019   0.006   0.001
           0.003   0.019   0.056   0.081   0.056   0.019   0.003
           0.004   0.027   0.081   0.117   0.081   0.027   0.004
           0.003   0.019   0.056   0.081   0.056   0.019   0.003
           0.001   0.006   0.019   0.027   0.019   0.006   0.001
           0.000   0.001   0.003   0.004   0.003   0.001   0.000

3、结论。

        方差越大模版大小越大,各点和中心点的差距越大。并且模版长度length和标准差sigma之间的关系:length=6sigma(%99.74)、length=4sigma(%95)、length=2sigma(%68)。其中括号中的百分比指的是高斯模版中的数据占全部数据的百分之多少。

三、高斯滤波(带权值的均值滤波)

1、原图。高斯滤波只是在计算平均值的时候,根据距离的远近,带有权值而已。

2、代码。生成4张图片,高斯模版大小和方差分别是:(3、1)、(3、0.5)、(5、1)、(5、0.5)。

package com.zxj.reptile.test.mnist;

import com.zxj.reptile.utils.image.ImageService;
import com.zxj.reptile.utils.image.ImageUtils;

public class ImgTest {

    private static final String File_Path = "G:\\xiaojie-java-test\\img\\";

    public static void main(String[] args) {
        //高斯过滤
        String gaussSourcePath = File_Path + "滤波\\高斯滤波\\高斯噪声.jpg";
        String gaussTargetPath = File_Path + "滤波\\高斯滤波\\高斯滤波_";
        //高斯过滤 length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
        gaussFilter(sourcePath, targetPath + "3_6sigma.jpg", 3, 1.5);
        gaussFilter(sourcePath, targetPath + "3_4sigma.jpg", 3, 0.75);
        gaussFilter(sourcePath, targetPath + "3_2sigma.jpg", 3, 0.5);
        gaussFilter(sourcePath, targetPath + "5_6sigma.jpg", 5, 2.5);
        gaussFilter(sourcePath, targetPath + "5_4sigma.jpg", 5, 1.25);
        gaussFilter(sourcePath, targetPath + "5_2sigma.jpg", 5, 0.833);
        gaussFilter(sourcePath, targetPath + "7_6sigma.jpg", 7, 3.5);
        gaussFilter(sourcePath, targetPath + "7_4sigma.jpg", 7, 1.75);
        gaussFilter(sourcePath, targetPath + "7_2sigma.jpg", 7, 1.167);
    }
}
package com.zxj.reptile.utils.image;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;

public class ImageService {
    /**
     * 高斯过滤(加权的均值过滤)
     *
     * @param sourcePath 原图像
     * @param targetPath 目标图像
     * @param grayType   灰度化方式
     * @param length     模版长度,length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
     * @param sigma      模版标准差,length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
     */
    public static void gaussFilter(String sourcePath, String targetPath, int grayType, int length, double sigma) {
        try {
            //高斯模版
            double[][] gaussTemplate = ImageUtils.getGaussTemplate(length, sigma);
            //获取原图像对象,并获取原图像的二维数组
            BufferedImage image = ImageIO.read(new File(sourcePath));
            int[][] imgArrays = ImageUtils.getTwoDimension(image);
            //生成新图像的二维数组
            imgArrays = ImageUtils.getGrayImg(imgArrays, grayType);//灰度化
            int[][] newImgArrays = ImageUtils.getGaussFilter(imgArrays, gaussTemplate);//均值过滤
            //生成新图片对象,填充像素
            BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
            ImageUtils.setTwoDimension(newImage, newImgArrays, ImageUtils.Channel_Type_1);
            //生成图片文件
            ImageIO.write(newImage, "JPEG", new File(targetPath + size + "_" + variance + ".jpg"));
            Thread.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.zxj.reptile.utils.image;

import java.awt.image.BufferedImage;

public class ImageUtils {
    /**
     * 获取高斯滤波模版的二维数组
     *
     * @param length 模版长度,length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
     * @param sigma  模版标准差,length=6sigma(%99.74), length=4sigma(95%), length=2sigma(68%)
     */
    public static double[][] getGaussTemplate(int length, double sigma) {
        double[][] gaussTemplate = new double[length][length];    // 用于存储结果
        int centerIndex = (length - 1) / 2;//模版的中心点
        double variance = sigma * sigma;//方差
        double sum = 0;
        for (int i = 0; i < length; ++i) {
            for (int j = 0; j < length; ++j) {
                int xLength = j - centerIndex;//x上的距离
                int yLength = i - centerIndex;//y上的距离
                double e = Math.exp(-(xLength * xLength + yLength * yLength) / (2 * variance));
                gaussTemplate[i][j] = e / (2 * Math.PI * variance);
                sum += gaussTemplate[i][j];
            }
        }
        //占得比重
        for (int i = 0; i < length; ++i) {
            for (int j = 0; j < length; ++j) {
                gaussTemplate[i][j] = gaussTemplate[i][j] / sum;
            }
        }
//        //打印模版
//        System.out.println(String.format("生成大小为%d,标准差为%.3f的二维高斯模版:", length, sigma));
//        for (double[] doubles : gaussTemplate) {
//            for (int j = 0; j < gaussTemplate.length; j++) {
//                System.out.print(String.format("%8.3f", doubles[j]));
//            }
//            System.out.println();
//        }
        return gaussTemplate;
    }

    /**
     * 高斯滤波
     *
     * @param imgArrays     图像二维数组
     * @param gaussTemplate 高斯滤波模版的二维数组
     */
    public static int[][] getGaussFilter(int[][] imgArrays, double[][] gaussTemplate) {
        final int imgHeight = imgArrays.length;
        final int imgWidth = imgArrays[0].length;
        int[][] newImgArrays = new int[imgHeight][imgWidth];
        //模版长度和半径
        final int filterLength = gaussTemplate.length;
        final int filterRadius = (filterLength - 1) / 2;
        //高斯过滤
        for (int h = 0; h < imgHeight; h++) {//图片第几行
            for (int w = 0; w < imgWidth; w++) {//图片第几列
                double weightTotal = 0;
                double sum = 0;
                for (int templateH = -filterRadius; templateH <= filterRadius; templateH++) {//模版第几行
                    int rowIndex = h + templateH;
                    if (rowIndex < 0 || rowIndex > imgHeight - 1) {
                        continue;
                    }
                    for (int templateW = -filterRadius; templateW < filterRadius; templateW++) {//模版第几列
                        int columnIndex = w + templateW;
                        if (columnIndex < 0 || columnIndex > imgWidth - 1) {
                            continue;
                        }
                        double weight = gaussTemplate[templateH + filterRadius][templateW + filterRadius];
                        sum += (imgArrays[rowIndex][columnIndex] * weight);
                        weightTotal += weight;
                    }
                }
                newImgArrays[h][w] = (int) (sum / weightTotal);
            }
        }
        return newImgArrays;
    }

    
    //灰度处理的方法
    public static final byte Gray_Type_Default = 0;//默认加权法
    public static final byte Gray_Type_Min = 1;//最大值法
    public static final byte Gray_Type_Max = 2;//最小值法
    public static final byte Gray_Type_Average = 3;//平均值法
    public static final byte Gray_Type_Weight = 4;//加权法
    public static final byte Gray_Type_Red = 5;//红色值法
    public static final byte Gray_Type_Green = 6;//绿色值法
    public static final byte Gray_Type_Blue = 7;//蓝色值法

    //生成的图片是几通道的
    public static final byte Channel_Type_Default = 0;//默认三通道
    public static final byte Channel_Type_1 = 1;//单通道
    public static final byte Channel_Type_3 = 3;//三通道

    /**
     * 灰度化处理
     *
     * @param imgArrays 图像二维数组
     * @param grayType  灰度化方法
     */
    public static int[][] getGrayImg(int[][] imgArrays, int grayType) throws Exception {
        final int imgHeight = imgArrays.length;
        final int imgWidth = imgArrays[0].length;
        int[][] newImgArrays = new int[imgHeight][imgWidth];
        for (int h = 0; h < imgHeight; h++) {
            for (int w = 0; w < imgWidth; w++) {
                final int[] grb = getRgb(imgArrays[h][w]);
                newImgArrays[h][w] = getGray(grb, grayType);
            }
        }
        return newImgArrays;
    }

    /**
     * 通过像素值,返回r、g、b颜色通道的值
     *
     * @param pixel 像素值
     */
    public static int[] getRgb(int pixel) {
        int[] rgb = new int[3];
        rgb[0] = (pixel >> 16) & 0xff;
        rgb[1] = (pixel >> 8) & 0xff;
        rgb[2] = pixel & 0xff;
        return rgb;
    }

    /**
     * 根据不同的灰度化方法,返回灰度值
     *
     * @param rgb      r、g、b颜色通道的值
     * @param grayType 不同灰度处理的方法
     */
    public static int getGray(int[] rgb, int grayType) throws Exception {
        if (grayType == Gray_Type_Average) {
            return (rgb[0] + rgb[1] + rgb[2]) / 3;   //rgb之和除以3
        } else if (grayType == Gray_Type_Weight || grayType == Gray_Type_Default) {
            return (int) (0.3 * rgb[0] + 0.59 * rgb[1] + 0.11 * rgb[2]);
        } else if (grayType == Gray_Type_Red) {
            return rgb[0];//取红色值
        } else if (grayType == Gray_Type_Green) {
            return rgb[1];//取绿色值
        } else if (grayType == Gray_Type_Blue) {
            return rgb[2];//取蓝色值
        }
        //比较三个数的大小
        int gray = rgb[0];
        for (int i = 1; i < rgb.length; i++) {
            if (grayType == Gray_Type_Min) {
                if (gray > rgb[i]) {
                    gray = rgb[i];//取最小值
                }
            } else if (grayType == Gray_Type_Max) {
                if (gray < rgb[i]) {
                    gray = rgb[i];//取最大值
                }
            } else {
                throw new Exception("grayType出错");
            }
        }
        return gray;
    }

    /**
     * 获取二维像素
     *
     * @param image BufferedImage图像对象
     */
    public static int[][] getTwoDimension(BufferedImage image) {
        final int imgWidth = image.getWidth();
        final int imgHeight = image.getHeight();
        int[][] imgArrays = new int[imgHeight][imgWidth];
        for (int i = 0; i < imgHeight; i++) {
            for (int j = 0; j < imgWidth; j++) {
                imgArrays[i][j] = image.getRGB(j, i);
            }
        }
        return imgArrays;
    }

    /**
     * 将二维像素填充到图像中
     *
     * @param image       BufferedImage图像对象
     * @param imgArrays   二维像素
     * @param channelType 单通道还是三通道
     */
    public static void setTwoDimension(BufferedImage image, int[][] imgArrays, int channelType) throws Exception {
        final int imgWidth = image.getWidth();
        final int imgHeight = image.getHeight();
        for (int i = 0; i < imgHeight; i++) {
            for (int j = 0; j < imgWidth; j++) {
                if (channelType == Channel_Type_1) {
                    image.setRGB(j, i, (byte) imgArrays[i][j]);
                } else if (channelType == Channel_Type_3 || channelType == Channel_Type_Default) {
                    image.setRGB(j, i, imgArrays[i][j]);
                } else {
                    throw new Exception("channelType错误");
                }
            }
        }
    }
}

3、结果。可以跟没有权重的均值滤波进行对比,发现高斯滤波(带有权值的均值滤波)在细节上的保留效果来的更加的好些。

2016-03-05 12:45:16 u010899190 阅读数 767
  • OpenCV3.2 Java图像处理视频学习教程

    OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java OpenCV图像处理部分内容,包括Mat对象使用、图像读写、 基于常用核心API讲述基本原理、使用方法、参数、代码演示、图像处理思路与流程讲授。主要内容包括opencv像素操作、滤波、边缘提取、直线与圆检测、形态学操作与分水岭、图像金子塔融合重建、多尺度模板匹配、opencv人脸检测、OpenCV跟Tomcat使用实现服务器端图像处理服务。

    4118 人正在学习 去看看 贾志刚

主界面
主界面

原图
原图

方框滤波

均值滤波

高斯滤波

中值滤波

双边滤波

图像处理之滤波1代码

2019-07-07 22:29:41 wujuxKkoolerter 阅读数 509
  • OpenCV3.2 Java图像处理视频学习教程

    OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java OpenCV图像处理部分内容,包括Mat对象使用、图像读写、 基于常用核心API讲述基本原理、使用方法、参数、代码演示、图像处理思路与流程讲授。主要内容包括opencv像素操作、滤波、边缘提取、直线与圆检测、形态学操作与分水岭、图像金子塔融合重建、多尺度模板匹配、opencv人脸检测、OpenCV跟Tomcat使用实现服务器端图像处理服务。

    4118 人正在学习 去看看 贾志刚

高斯同态滤波图像增强

同态滤波是一种在频域中同时将图像亮度范围进行压缩并将图像对比度增强的方法。同态滤波增强属于图像频域处理范畴,作用是对图像灰度范围进行调整,通过消除图像上照明不均匀的问题,增强图像的细节,同时对不损失亮区的图像细节。

一幅图像 能够使用它的入射光分量和反射光分量来表示 ,关系如下:
f(x,y)=i(x,y)r(x,y) f(x,y) = i(x,y) \cdot r(x,y)
另外,入射光分量i(x,y)i(x,y)由照明决定,而反射光分量r(x,y)r(x,y)则是由物体本身特性决定;入射光分量同傅立叶平面的低频分量相关,而反射光分量则同高频分量相关。
对于f(x,y)=i(x,y)r(x,y)f(x,y) = i(x,y) \cdot r(x,y)取对数,然后再取傅立叶变换得:
Z(u,v)=I(u,v)+R(u,v)Z(u,v) = I(u,v) + R(u,v)
其中,I(u,v)I(u,v)R(u,v)R(u,v)分别是ln[i(x,y)]\ln[i(x,y)]ln[r(x,y)]\ln[r(x,y)]的傅立叶变换,如果选取一个滤波函数H(u,v)H(u,v)来处理Z(u,v)Z(u,v),则有:
S(u,v)=Z(u,v)H(u,v)=I(u,v)H(u,v)+R(u,v)H(u,v) S(u,v) = Z(u,v)H(u,v) = I(u,v)H(u,v) + R(u,v) * H(u,v)
其中,S(u,v)S(u,v)是滤波后的傅立叶变换。再对取指数即得到最终处理结果f(x,y)=exp(S(u,v))f&#x27;(x,y) = \exp(S(u,v))相当于高通滤波。

处理过程如下:
[外链图片转存失败(img-VrVGc9Ay-1562509670331)(images/03-1.png)]

Python实现代码如下:

def homomorphic_filtering(src,d0 = 10,r1 = 0.5,rh=2,c=4):
    gray = src.copy()
    if len(src.shape) > 2:
        gray = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)
    gray = np.float64(gray) 
    rows,cols = gray.shape
   
    gray_fft = np.fft.fft2(gray)
    gray_fftshift = np.fft.fftshift(gray_fft)
    dst_fftshift = np.zeros_like(gray_fftshift)
    M,N = np.meshgrid(np.arange(-cols // 2,cols // 2),np.arange(-rows//2,rows//2))
    D = np.sqrt(M ** 2 + N ** 2)
    Z = (rh - r1) * (1 - np.exp(-c * (D ** 2 / d0 ** 2))) + r1
    dst_fftshift = Z * gray_fftshift
    dst_ifftshift = np.fft.ifftshift(dst_fftshift)
    dst_ifft = np.fft.ifft2(dst_ifftshift)
    dst = np.real(dst_ifft)
    dst = np.uint8(np.clip(dst,0,255))
    return dst

程序运行结果如下:
在这里插入图片描述
左边为原图像,右边为高斯同态滤波后的结果

2015-04-23 20:13:23 chanxiaogang 阅读数 17171
  • OpenCV3.2 Java图像处理视频学习教程

    OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java OpenCV图像处理部分内容,包括Mat对象使用、图像读写、 基于常用核心API讲述基本原理、使用方法、参数、代码演示、图像处理思路与流程讲授。主要内容包括opencv像素操作、滤波、边缘提取、直线与圆检测、形态学操作与分水岭、图像金子塔融合重建、多尺度模板匹配、opencv人脸检测、OpenCV跟Tomcat使用实现服务器端图像处理服务。

    4118 人正在学习 去看看 贾志刚

1.图像频域滤波的基本概念
空间域和频域滤波的基础都是卷积定理。该定理可以写为
这里写图片描述
这里写图片描述
其中,符号*表示两个函数的卷积,双箭头两边的表达式组成了傅里叶变换对。第一个表达式表明两个空间函数的卷积可以通过计算两个傅里叶变换函数的乘积逆变换得到。在滤波问题上,我们更关注第一个表达式,它构成了整个频域滤波的基础,式中的乘积实际上就是两个二维矩阵F(u,v)和H(u,v)对应元素之间的乘积。
傅立叶变换相关函数
MATLAB提供了几个和傅里叶变换相关的函数。其说明如下:
fft2(F); 二维傅立叶变换
abs(F); 获得傅立叶频谱
fftshift(F); 将变换的原点移至频率矩形的中心
ifft2(F); 二维傅立叶反变换
real(ifft2(F)); 提取变换后的实部
imag(ifft2(F)); 提取变换后的虚部
2. 频域滤波的基本步骤
频域滤波通常应遵循以下步骤。
(1)计算原始图像f(x,y)的DFT,得到F(u,v)。
(2)将频谱F(u,v)的零频点移动到频谱图的中心位置。
(3)计算滤波器函数H(u,v)与F(u,v)的乘积G(u,v)。
(4)将频谱G(u,v)的零频点移回到频谱图的左上角位置。
(5)计算第(4)步计算结果的傅里叶反变换g(x,y)。
(6)取g(x,y)的实部作为最终滤波后的结果图像。
按照该步骤,在MATLAB中很容易编程实现频域滤波。滤波能否取得理想结果的关键取决于频域滤波函数H(u,v),常常称之为滤波器,或滤波器传递函数。因为它在滤波中抑制或滤除了频谱中某些频率的分量,而保留其他一些频率不受影响。
频域滤波的方框图表示
3 频域滤波器
1 理想低通滤波器(ILPF)
这里写图片描述

D(u,v)是点(u,v)距频率原点的距离,D0为截止频率。如果图像大小为M×N,其变换亦为M×N。中心化之后,矩形中心在(M/2,N/2)

这里写图片描述

说明:在半径为D0的圆内,所有频率没有衰减地通过滤波器,而在此半径的圆之外的所有频率完全被衰减掉。虽然这个滤波器不能使电子元件来模拟实现,但可以在计算机中用传递函数实现。由于理想低通滤波器的过度特性过于急峻,所以会产生了振铃现象。
理想低通滤波器三维透视图
2 n阶巴特沃斯低通滤波器(BLPF)
这里写图片描述

n表示的是巴特沃斯滤波器的次数。随着次数的增加,振铃现象会越来越明显。与理想低通滤波器不同的是,巴特沃斯低通滤波器传递函数并不是在D0处突然不连续。对于具有平滑传递函数的滤波器,我们通常要定义一个截止频率,在该点处H(u,v)会降低为其最大值的某个给定比例。例如当D(u,v)=D0时,H(u,v)=0.5。通常,BLPF的平滑效果好于ILPF。
巴特沃斯低通滤波器三维透视图
3 高斯低通滤波器(GLPF)
这里写图片描述
D0为截止频率,当D(u,v)=D0 时,滤波器下降到其最大值的0.607,无振铃现象。
高斯低通滤波器三维透视图
4 理想高通滤波器(IHPF)
这里写图片描述
D(u,v)是点(u,v)距频率原点的距离,D0为截止频率。如果图像大小为M×N,其变换亦为M×N。中心化之后,矩形中心在(M/2,N/2)
这里写图片描述

在半径为D0的圆外,所有频率没有衰减地通过滤波器,而在此半径的圆之内的所有频率完全被衰减掉。虽然这个滤波器不能使电子元件来模拟实现,但可以在计算机中用传递函数实现。由于理想高通滤波器的过度特性过于急峻,所以会产生了振铃现象。
![理想高通滤波器三维透视图](http://img.blog.csdn.net/20150423211457107)
5  n阶巴特沃斯高通滤波器(BHPF)

这里写图片描述
n表示的是巴特沃斯滤波器的次数。随着次数的增加,振铃现象会越来越明显。与理想高通滤波器不同的是,巴特沃斯高通滤波器传递函数并不是在D0处突然不连续。对于具有平滑传递函数的滤波器,我们通常要定义一个截止频率,在该点处H(u,v)会降低为其最大值的某个给定比例。例如当D(u,v)=D0时,H(u,v)=0.5。通常,BHPF的平滑效果好于IHPF。
巴特沃斯高通滤波器三维透视图
6 高斯高通滤波器(GHPF)
这里写图片描述
高斯高通滤波器三维透视图

程序代码如下:

function [U,V] = dftuv( M,N )
%DFTUV computes meshgrid frequency matrices
%set up range of variables
u=0:(M-1);
v=0:(N-1);
%compute the indices for use in meshgrid
idx=find(u > M/2);
u(idx)=u(idx)-M;
idy=find(v > N/2);
v(idy)=v(idy)-N;
%compute the meshgrid arrays
[V,U]=meshgrid(v,u);
End
function [H,D] = lpfilter( type,M,N,D0,n)
%lpfilter computes frequency domin lowpass filters
%H creates the transfer function of a lowpass filter

%use function dftuv to set up the meshgrid arrays needed for computing 
%the required distances
[U,V]=dftuv(M,N);
D=sqrt(U.^2+V.^2);
%begin filter computations
switch type
    case 'ideal'
        H=double(D<=D0);
    case 'btw'
        if nargin ==4
            n=1;
        end
        H=1./(1+(D./D0).^(2*n));
    case 'gaussian'
        H=exp(-(D.^2)./(2*(D0^2)));
    otherwise
        error('unknown filter type')  
end        
end
function H = hpfilter( type,M,N,D0,n )
%hpfilter computes frequency domin highpass filters
%H creates the transfer function of a highpass filter
%the transfer function Hhp of a highpass filter is 1-Hlp
%we can use function lpfilter to generate highpass filters.
if nargin==4
    n=1; 
end
%generate highpass filter.
hlp=lpfilter(type,M,N,D0,n);
H=1-hlp;

end
%图像频域高通滤波主程序
clear all;
I=imread('man.bmp'); %读入原图像
F=fft2(double(I));   %快速傅里叶变换
F=fftshift(F);       %图像零频点移动到频谱图中心

[M,N]=size(F);       %计算矩阵F的大小
%调用高通滤波器函数
H=hpfilter('ideal',M,N,40); 
%H=hpfilter('btw',M,N,40);
%H=hpfilter('gaussian',M,N,40);

H=fftshift(H);
G =F .* H;        %应用滤镜
%傅里叶反变换
g=ifft2(G);
%显示并比较结果
figure(1),imshow(I);  
title('显示原图像');
figure(2),imshow(log(1+abs(F)),[]);  
title('傅立叶变换后的频谱图');
figure(3),imshow(H,[]);
title('高通滤波器频域图像');
figure(4),imshow(log(1+abs(G)),[]);
title('高通滤波器处理后的频谱图');
figure(5),imshow(abs(real(g)),[]);
title('傅里叶反变换后的图像');

结论
在频谱中,低频主要对应图像在平滑区域的总体灰度级分布,而高频对应图像的细节部分,如边缘和噪声。

2019-02-13 14:57:38 fzzc12138 阅读数 160
  • OpenCV3.2 Java图像处理视频学习教程

    OpenCV3.2 Java图像处理视频培训课程:基于OpenCV新版本3.2.0详细讲述Java OpenCV图像处理部分内容,包括Mat对象使用、图像读写、 基于常用核心API讲述基本原理、使用方法、参数、代码演示、图像处理思路与流程讲授。主要内容包括opencv像素操作、滤波、边缘提取、直线与圆检测、形态学操作与分水岭、图像金子塔融合重建、多尺度模板匹配、opencv人脸检测、OpenCV跟Tomcat使用实现服务器端图像处理服务。

    4118 人正在学习 去看看 贾志刚

最近做一些图像处理的工作,搜寻资料发现很多大家都推荐导向滤波,不过这类大都是opencv的代码较多,所以我仿照网上的一些资料转了一份C#版本,如有错误请指正,互相交流学习。

开发环境:vs2017,win10。EmguCV通过“项目→管理NuGet程序包”,搜索emgucv导入即可。

代码如下:

using System;
using System.Drawing;
using System.Drawing.Imaging;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;

public static class PictureProcessing
{
    public static Bitmap GuidedFilter(Mat srcMat, Mat guidedMat, int radius, double eps)
    {
        //------------【0】转换源图像信息,将输入扩展为64位浮点型,以便以后做乘法------------
        srcMat.ConvertTo(srcMat, DepthType.Cv64F);
        guidedMat.ConvertTo(guidedMat, DepthType.Cv64F);

        //--------------【1】各种均值计算----------------------------------
        Mat mean_p = new Mat();
        Mat mean_I = new Mat();
        Mat mean_Ip = new Mat();
        Mat mean_II = new Mat();

        CvInvoke.BoxFilter(srcMat, mean_p, DepthType.Cv64F, new Size(radius, radius), new Point(-1, -1));//生成待滤波图像均值mean_p
        CvInvoke.BoxFilter(guidedMat, mean_I, DepthType.Cv64F, new Size(radius, radius), new Point(-1, -1));//生成引导图像均值mean_I

        Mat sg = new Mat();
        Mat gg = new Mat();
        CvInvoke.Multiply(srcMat, guidedMat, sg);
        CvInvoke.Multiply(guidedMat, guidedMat, gg);

        CvInvoke.BoxFilter(sg, mean_Ip, DepthType.Cv64F, new Size(radius, radius), new Point(-1, -1));//生成互相关均值mean_Ip
        CvInvoke.BoxFilter(gg, mean_II, DepthType.Cv64F, new Size(radius, radius), new Point(-1, -1));//生成引导图像自相关均值mean_II

        //--------------【2】计算相关系数,计算Ip的协方差cov和I的方差var------------------
        Mat cov_Ip = new Mat();
        Mat Ip = new Mat();
        CvInvoke.Multiply(mean_I, mean_p, Ip);
        CvInvoke.Subtract(mean_Ip, Ip, cov_Ip);

        Mat var_I = new Mat();
        Mat II = new Mat();
        CvInvoke.Multiply(mean_I, mean_I, II);
        CvInvoke.Subtract(mean_II, II, var_I);

        //---------------【3】计算参数系数a、b-------------------
        Mat a = new Mat();
        Mat b = new Mat();

        Mat I_eps = new Mat();
        CvInvoke.Add(var_I, new ScalarArray(eps), I_eps);
        CvInvoke.Divide(cov_Ip, I_eps, a);

        Mat aI = new Mat();
        CvInvoke.Multiply(a, mean_I, aI);
        CvInvoke.Subtract(mean_p, aI, b);

        //--------------【4】计算系数a、b的均值-----------------
        Mat mean_a = new Mat();
        Mat mean_b = new Mat();
        CvInvoke.BoxFilter(a, mean_a, DepthType.Cv64F, new Size(radius, radius), new Point(-1, -1));
        CvInvoke.BoxFilter(b, mean_b, DepthType.Cv64F, new Size(radius, radius), new Point(-1, -1));

        //---------------【5】生成输出矩阵------------------
        Mat axsrc = new Mat();
        CvInvoke.Multiply(mean_a, srcMat, axsrc);

        Mat dstImage = new Mat();
        CvInvoke.Add(axsrc, mean_b, dstImage);

        mean_p.Dispose();
        mean_I.Dispose();
        mean_Ip.Dispose();
        mean_II.Dispose();
        sg.Dispose();
        gg.Dispose();
        cov_Ip.Dispose();
        Ip.Dispose();
        var_I.Dispose();
        II.Dispose();
        a.Dispose();
        b.Dispose();
        I_eps.Dispose();
        aI.Dispose();
        mean_a.Dispose();
        mean_b.Dispose();
        axsrc.Dispose();

        return dstImage.Bitmap;
    }
}

使用时直接调用:

Mat src = new Mat(openFileDialog.FileName);

pictureBox1.Image = PictureProcessing.GuidedFilter(src, src, 50, 300);

主要就是参数radius和eps的配置,看自己喜好。网上亦有很多改进效率的方法,还在琢磨中。

参考资料:https://blog.csdn.net/sinat_36264666/article/details/77990790

图像平滑滤波

阅读数 58

没有更多推荐了,返回首页