Opencv Java 直方图 傅里叶变换

Java 版本: JavaCV

用OpenCV读一张图片并显示。只需将程序运行时的截图回复。如何安装配置创建项目编写OpenCV代码,可参考何东健课件和源代码或其他资源。

1. 用OpenCV读一张图片,显示该图的直方图。只需截图回复。如何安装配置创建项目编写OpenCV代码,可参考何东健课件和源代码的第3章或其他资源。
2. 用OpenCV读一张图片,求该图的离散傅立叶变换,并显示其频谱。只需截图回复。如何安装配置创建项目编写OpenCV代码,可参考何东健课件和源代码的第5章或其他资源。
3. 虽然我们是以OpenCV来布置实践,但是如果同学们采用其他方式,也是可以的,比如使用Matlab等等。只要能把问题解决。不同的途径有不同的特点,在实践过程中同学们可以去体会。
4. 对第3章理论内容,只要求同学们了解会用即可,如果想进一步了解相关内容,同学们可以参考数字信号处理相关书籍或者其他数字图像处理书籍。

直方图


/**
 * @program: learn-opencv
 * @description: 绘制图片直方图
 * @author: Mr.Dai
 * @create: 2020-03-03 16:30
 **/
public class Histogram {
    private final  static String path=System.getProperty("user.dir")+"\catton.jpg";
    static{
        platformUtils.loadLibraries();
    }

    public static void main(String[] args) {
        Mat imread = Imgcodecs.imread(path);
        HighGui.imshow(" 原图像",imread);
        plotGrayHistogram(imread);
        // 无限等待按键按下
        HighGui.waitKey(0);
    }

    public static void plotGrayHistogram(Mat img) {
        java.util.List<Mat> images = new ArrayList<>();
        images.add(img);
        MatOfInt channels = new MatOfInt(0); // 图像通道数,0表示只有一个通道
        MatOfInt histSize = new MatOfInt(256); // CV_8U类型的图片范围是0~255,共有256个灰度级
        Mat histogramOfGray = new Mat(); // 输出直方图结果,共有256行,行数的相当于对应灰度值,每一行的值相当于该灰度值所占比例
        MatOfFloat histRange = new MatOfFloat(0, 255);
        Imgproc.calcHist(images, channels, new Mat(), histogramOfGray, histSize, histRange, false);  // 计算直方图
        // 按行归一化
        Core.normalize(histogramOfGray, histogramOfGray, 0, histogramOfGray.rows(), Core.NORM_MINMAX, -1, new Mat());

        // 创建画布
        int histImgRows = 300;
        int histImgCols = 300;
        int colStep = (int) Math.floor(histImgCols / histSize.get(0, 0)[0]);
        Mat histImg = new Mat(histImgRows, histImgCols, CvType.CV_8UC3, new Scalar(255,255,255));  // 重新建一张图片,绘制直方图
        for (int i = 0; i < histSize.get(0, 0)[0]; i++) {  // 画出每一个灰度级分量的比例,注意OpenCV将Mat最左上角的点作为坐标原点
            Imgproc.line(histImg,
                    new org.opencv.core.Point(colStep * i, histImgRows - 20),
                    new org.opencv.core.Point(colStep * i, histImgRows - Math.round(histogramOfGray.get(i, 0)[0]) - 20),
                    new Scalar(0, 0,0), 2,8,0);
            if (i%50 == 0) {
                Imgproc.putText(histImg, Integer.toString(i), new org.opencv.core.Point(colStep * i, histImgRows - 5), 1, 1, new Scalar(0, 0, 0));  // 附上x轴刻度
            }
        }
        //显示出来  对namedWindos 与cv::imshow 封装
        HighGui.imshow("Gray Histogram",histImg);
    }
}




image_thumb1

傅里叶:

/**
 * @Description: 傅里叶变换
 * @Author: Dai.GuoWei
 * @Date: 2020/3/3
 */
public class TestDft {

    public Mat dftStart(Mat img) {
        img.convertTo(img, CvType.CV_32FC1);
        System.out.println("img类型: " + img.type() + " " + img.channels());
        int M = Core.getOptimalDFTSize(img.rows()); // 获得最佳DFT尺寸,为2的次方
        int N = Core.getOptimalDFTSize(img.cols()); // 同上
        Mat padded = new Mat();
        System.out.println("padded 类型: " + padded.size() + " " + padded.type() + " " + padded.channels());
        Core.copyMakeBorder(img, padded, 0, M - img.rows(), 0, N - img.cols(), Core.BORDER_CONSTANT, new Scalar(0)); // opencv中的边界扩展函数,提供多种方式扩展
        System.out.println("padded 类型: " + padded.size() + " " + padded.type() + " " + padded.channels());
        System.out.println("padded 类型: " + padded.size() + " " + padded.type() + " " + padded.channels());
        List<Mat> planes = new ArrayList<Mat>(); // Mat 数组,第一个为扩展后的图像,一个为空图像,
        planes.add(padded);
        planes.add(Mat.zeros(padded.size(), CvType.CV_32FC1));
        Mat complexImg = new Mat();

        System.out
                .println("complexImg 类型: " + complexImg.size() + " " + complexImg.type() + " " + complexImg.channels());
        Core.merge(planes, complexImg); // 合并成一个Mat
        System.out
                .println("complexImg 类型: " + complexImg.size() + " " + complexImg.type() + " " + complexImg.channels());

        Core.dft(complexImg, complexImg); // FFT变换, dft需要一个2通道的Mat

        // compute log(1 + sqrt(Re(DFT(img))**2 + Im(DFT(img))**2))
        Core.split(complexImg, planes); // 分离通道, planes[0] 为实数部分,planes[1]为虚数部分
        Core.magnitude(planes.get(0), planes.get(1), planes.get(0)); // 求模
        Mat mag = planes.get(0);
        Core.add(mag, new Scalar(1), mag);
//        mag += new Scalar(1);                                                                                            
        Core.log(mag, mag); // 模的对数

        // crop the spectrum, if it has an odd number of rows or columns
        mag = new Mat(mag, new Rect(0, 0, mag.cols() & -2, mag.rows() & -2)); // 保证偶数的边长

        int cx = mag.cols() / 2;
        int cy = mag.rows() / 2;

        // rearrange the quadrants of Fourier image //对傅立叶变换的图像进行重排,4个区块,从左到右,从上到下
        // 分别为q0, q1, q2, q3
        // so that the origin is at the image center // 对调q0和q3, q1和q2
        Mat tmp = new Mat();
        Mat q0 = new Mat(mag, new Rect(0, 0, cx, cy));
        Mat q1 = new Mat(mag, new Rect(cx, 0, cx, cy));
        Mat q2 = new Mat(mag, new Rect(0, cy, cx, cy));
        Mat q3 = new Mat(mag, new Rect(cx, cy, cx, cy));

        q0.copyTo(tmp);
        q3.copyTo(q0);
        tmp.copyTo(q3);

        q1.copyTo(tmp);
        q2.copyTo(q1);
        tmp.copyTo(q2);

       // Core.normalize(mag, mag, 0, 255, Core.NORM_MINMAX); // 规范化值到 0~1 显示图片的需要 归一化
        Core.normalize(mag,mag, 0, 255, Core.NORM_MINMAX,CvType.CV_8UC1,new Mat());
        System.out.println("mag 类型: " + mag.size() + " " + mag.type() + " " + mag.channels());
        mag.convertTo(mag, CvType.CV_8U);
        return mag;

    }
    private final  static String path=System.getProperty("user.dir")+"\catton.jpg";

    static{
        platformUtils.loadLibraries();
    }
    public static void main(String[] args) {
        Mat img = Imgcodecs.imread(path);
        Mat gray = new Mat();
        Imgproc.cvtColor(img, gray, Imgproc.COLOR_RGB2GRAY);
        TestDft t = new TestDft();
        Mat dst = t.dftStart(gray);
        HighGui.imshow("原图", img);
        HighGui.imshow("dft效果图", dst);
        HighGui.waitKey(0);
        HighGui.destroyAllWindows();
        System.exit(0);
    }
}
image_thumb3
原文地址:https://www.cnblogs.com/dgwblog/p/12403307.html