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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM